Version 2.2.1-dev.2.0

Merge commit '9d3988eb67b3c388fb8eb4425da3ba07182e08a2' into dev
diff --git a/.packages b/.packages
index a686ef2..87f497f 100644
--- a/.packages
+++ b/.packages
@@ -16,7 +16,6 @@
 args:third_party/pkg/args/lib
 async:third_party/pkg/async/lib
 async_helper:pkg/async_helper/lib
-barback:third_party/pkg/barback/lib
 bazel_worker:third_party/pkg/bazel_worker/lib
 boolean_selector:third_party/pkg/boolean_selector/lib
 build_integration:pkg/build_integration/lib
@@ -48,7 +47,6 @@
 http_retry:third_party/pkg/http_retry/lib
 http_throttle:third_party/pkg/http_throttle/lib
 intl:third_party/pkg/intl/lib
-isolate:third_party/pkg/isolate/lib
 js:pkg/js/lib
 js_ast:pkg/js_ast/lib
 js_runtime:sdk/lib/_internal/js_runtime/lib
@@ -67,9 +65,8 @@
 package_config:third_party/pkg_tested/package_config/lib
 package_resolver:third_party/pkg_tested/package_resolver/lib
 path:third_party/pkg/path/lib
-plugin:third_party/pkg/plugin/lib
 pool:third_party/pkg/pool/lib
-protobuf:third_party/pkg/protobuf/lib
+protobuf:third_party/pkg/protobuf/protobuf/lib
 pub:third_party/pkg/pub/lib
 pub_semver:third_party/pkg/pub_semver/lib
 quiver:third_party/pkg/quiver/lib
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 37704bb..110eaf0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,5 @@
+## 2.2.1-dev.2.0
+
 ## 2.2.1-dev.1.1
 
 * Cherry-pick 567d552de8ff93d704111467e7f3bf3b896ab684 to dev
@@ -5,6 +7,8 @@
 
 ## 2.2.1-dev.1.0
 
+* RegExp patterns can now use lookbehind assertions.
+
 ### Tool Changes
 
 #### Pub client
diff --git a/DEPS b/DEPS
index f1860721..c6f2c79 100644
--- a/DEPS
+++ b/DEPS
@@ -36,7 +36,7 @@
   "chromium_git": "https://chromium.googlesource.com",
   "fuchsia_git": "https://fuchsia.googlesource.com",
 
-  "co19_2_rev": "b54821029f62b5b5873925cfef6c01f1100d1982",
+  "co19_2_rev": "2d157d6b9135f891ffd1d35b7a2d5dfa57611f63",
 
   # As Flutter does, we use Fuchsia's GN and Clang toolchain. These revision
   # should be kept up to date with the revisions pulled by the Flutter engine.
@@ -54,7 +54,7 @@
   # Revisions of /third_party/* dependencies.
   "args_tag": "1.4.4",
   "async_tag": "2.0.8",
-  "bazel_worker_tag": "0.1.14",
+  "bazel_worker_tag": "bazel_worker-v0.1.20",
   "boolean_selector_tag" : "1.0.4",
   "boringssl_gen_rev": "bbf52f18f425e29b1185f2f6753bec02ed8c5880",
   "boringssl_rev" : "702e2b6d3831486535e958f262a05c75a5cb312e",
@@ -108,10 +108,9 @@
   "package_config_tag": "1.0.5",
   "package_resolver_tag": "1.0.10",
   "path_tag": "1.6.2",
-  "plugin_tag": "f5b4b0e32d1406d62daccea030ba6457d14b1c47",
   "ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_tag": "1.3.6",
-  "protobuf_tag": "0.9.0",
+  "protobuf_rev": "0c77167b16d00b561a6055bfe26690af7f26ae88",
   "pub_rev": "3c060aae47985e9a248b850f1d0450304a5c97e3",
   "pub_semver_tag": "1.4.2",
   "quiver_tag": "2.0.0+1",
@@ -157,7 +156,7 @@
   Var("dart_root") + "/tools/sdks": {
       "packages": [{
           "package": "dart/dart-sdk/${{platform}}",
-          "version": "version:2.2.1-dev.0.0",
+          "version": "version:2.2.1-dev.1.1",
       }],
       "dep_type": "cipd",
   },
@@ -303,12 +302,10 @@
       + "@" + Var("package_resolver_tag"),
   Var("dart_root") + "/third_party/pkg/path":
       Var("dart_git") + "path.git" + "@" + Var("path_tag"),
-  Var("dart_root") + "/third_party/pkg/plugin":
-      Var("dart_git") + "plugin.git" + "@" + Var("plugin_tag"),
   Var("dart_root") + "/third_party/pkg/pool":
       Var("dart_git") + "pool.git" + "@" + Var("pool_tag"),
   Var("dart_root") + "/third_party/pkg/protobuf":
-      Var("dart_git") + "protobuf.git" + "@" + Var("protobuf_tag"),
+      Var("dart_git") + "protobuf.git" + "@" + Var("protobuf_rev"),
   Var("dart_root") + "/third_party/pkg/pub_semver":
       Var("dart_git") + "pub_semver.git" + "@" + Var("pub_semver_tag"),
   Var("dart_root") + "/third_party/pkg/pub":
diff --git a/docs/process/breaking-changes.md b/docs/process/breaking-changes.md
index adf71a2..5ed9bcb 100644
--- a/docs/process/breaking-changes.md
+++ b/docs/process/breaking-changes.md
@@ -66,7 +66,7 @@
 
 [TODO: Link to an issue template for this]
 
-* Email `announce@dartlang.org, flutter-announce@googlegroups.com`,:
+* Email Dart Announce (`announce@dartlang.org`):
 
   * Subject: 'Breaking change [bug ID]: [short summary]'
 
@@ -77,6 +77,9 @@
   * A request that developers may leave comments in the linked issue, if this
     breaking change poses a severe problem.
 
+* Once you have sent the announce email, please let `aadilmaan@google.com` know
+as he will help drive the request through approval review process.
+
 ### Step 2: Approval
 
 If there is a general agreement that the benefit of the change outweighs the
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index d4f29d6..a08c3bc 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -196,7 +196,11 @@
       try {
         var analysisDriver = server.getAnalysisDriver(file);
         var session = analysisDriver.currentSession;
-        var resolvedLibrary = await session.getResolvedLibrary(file);
+
+        var fileElement = await session.getUnitElement(file);
+        var libraryPath = fileElement.element.librarySource.fullName;
+
+        var resolvedLibrary = await session.getResolvedLibrary(libraryPath);
         var requestedLibraryElement = await session.getLibraryByUri(
           library.uriStr,
         );
@@ -214,10 +218,10 @@
 
         var completion = params.label;
         var builder = DartChangeBuilder(session);
-        await builder.addFileEdit(file, (builder) {
+        await builder.addFileEdit(libraryPath, (builder) {
           var result = builder.importLibraryElement(
             targetLibrary: resolvedLibrary,
-            targetPath: file,
+            targetPath: libraryPath,
             targetOffset: params.offset,
             requestedLibrary: requestedLibraryElement,
             requestedElement: requestedElement,
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
index c5ee92f..26a8028 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
@@ -43,6 +43,12 @@
   Expression get dotTarget;
 
   /**
+   * Return a list containing the names of the experiments that have been
+   * enabled.
+   */
+  List<String> get enabledExperiments;
+
+  /**
    * Return `true` if free standing identifiers should be suggested
    */
   bool get includeIdentifiers;
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 1d493ed..70f98dc 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -30,7 +30,6 @@
 import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:args/args.dart';
 import 'package:linter/src/rules.dart' as linter;
-import 'package:plugin/manager.dart';
 import 'package:telemetry/crash_reporting.dart';
 import 'package:telemetry/telemetry.dart' as telemetry;
 
@@ -440,10 +439,8 @@
     final serve_http = diagnosticServerPort != null;
 
     //
-    // Process all of the plugins so that extensions are registered.
+    // Register lint rules.
     //
-    ExtensionManager manager = new ExtensionManager();
-    manager.processPlugins(AnalysisEngine.instance.requiredPlugins);
     linter.registerLintRules();
 
     _DiagnosticServerImpl diagnosticServer = new _DiagnosticServerImpl();
@@ -701,6 +698,15 @@
     return sdk;
   }
 
+  /**
+   * Constructs a uuid combining the current date and a random integer.
+   */
+  String _generateUuidString() {
+    int millisecondsSinceEpoch = new DateTime.now().millisecondsSinceEpoch;
+    int random = new Random().nextInt(0x3fffffff);
+    return '$millisecondsSinceEpoch$random';
+  }
+
   String _getSdkPath(ArgResults args) {
     if (args[SDK_OPTION] != null) {
       return args[SDK_OPTION];
@@ -768,15 +774,6 @@
   }
 
   /**
-   * Constructs a uuid combining the current date and a random integer.
-   */
-  String _generateUuidString() {
-    int millisecondsSinceEpoch = new DateTime.now().millisecondsSinceEpoch;
-    int random = new Random().nextInt(0x3fffffff);
-    return '$millisecondsSinceEpoch$random';
-  }
-
-  /**
    * Perform log files rolling.
    *
    * Rename existing files with names `[path].(x)` to `[path].(x+1)`.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index a53579e..710ca2d 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -326,6 +326,10 @@
   }
 
   @override
+  List<String> get enabledExperiments =>
+      result.session.analysisContext.analysisOptions.enabledExperiments;
+
+  @override
   bool get includeIdentifiers {
     return opType.includeIdentifiers;
   }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
index ecc25d3..fb9885d 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
@@ -327,6 +328,13 @@
   }
 
   @override
+  visitForElement(ForElement node) {
+    _addCollectionElementKeywords();
+    _addExpressionKeywords(node);
+    return super.visitForElement(node);
+  }
+
+  @override
   visitFormalParameterList(FormalParameterList node) {
     AstNode constructorDeclaration =
         node.thisOrAncestorOfType<ConstructorDeclaration>();
@@ -387,6 +395,13 @@
   }
 
   @override
+  visitIfElement(IfElement node) {
+    _addCollectionElementKeywords();
+    _addExpressionKeywords(node);
+    return super.visitIfElement(node);
+  }
+
+  @override
   visitIfStatement(IfStatement node) {
     if (_isPreviousTokenSynthetic(entity, TokenType.CLOSE_PAREN)) {
       // analyzer parser
@@ -449,6 +464,12 @@
   }
 
   @override
+  visitListLiteral(ListLiteral node) {
+    _addCollectionElementKeywords();
+    super.visitListLiteral(node);
+  }
+
+  @override
   visitMethodDeclaration(MethodDeclaration node) {
     if (entity == node.body) {
       if (isEmptyBody(node.body)) {
@@ -549,6 +570,18 @@
   }
 
   @override
+  visitSetOrMapLiteral(SetOrMapLiteral node) {
+    _addCollectionElementKeywords();
+    super.visitSetOrMapLiteral(node);
+  }
+
+  @override
+  visitSpreadElement(SpreadElement node) {
+    _addExpressionKeywords(node);
+    return super.visitSpreadElement(node);
+  }
+
+  @override
   visitStringLiteral(StringLiteral node) {
     // ignored
   }
@@ -627,6 +660,17 @@
     }
   }
 
+  void _addCollectionElementKeywords() {
+    List<String> enabledExperiments = request.enabledExperiments;
+    if (enabledExperiments.contains(EnableString.control_flow_collections) ||
+        enabledExperiments.contains(EnableString.spread_collections)) {
+      _addSuggestions([
+        Keyword.FOR,
+        Keyword.IF,
+      ]);
+    }
+  }
+
   void _addCompilationUnitKeywords() {
     _addSuggestions([
       Keyword.ABSTRACT,
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
index 63faf71..50e4b46 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
@@ -76,9 +76,11 @@
     }
     String containingMethodName;
     List<InterfaceType> mixins;
+    List<InterfaceType> superclassConstraints;
     if (expression is SuperExpression && type is InterfaceType) {
       // Suggest members from superclass if target is "super"
       mixins = (type as InterfaceType).mixins;
+      superclassConstraints = (type as InterfaceType).superclassConstraints;
       type = (type as InterfaceType).superclass;
       // Determine the name of the containing method because
       // the most likely completion is a super expression with same name
@@ -99,7 +101,8 @@
     // Build the suggestions
     if (type is InterfaceType) {
       _SuggestionBuilder builder = new _SuggestionBuilder(containingLibrary);
-      builder.buildSuggestions(type, containingMethodName, mixins: mixins);
+      builder.buildSuggestions(type, containingMethodName,
+          mixins: mixins, superclassConstraints: superclassConstraints);
       return builder.suggestions.toList();
     }
     return const <CompletionSuggestion>[];
@@ -290,7 +293,7 @@
    * is the name of the method in which the completion is requested.
    */
   void buildSuggestions(InterfaceType type, String containingMethodName,
-      {List<InterfaceType> mixins}) {
+      {List<InterfaceType> mixins, List<InterfaceType> superclassConstraints}) {
     // Visit all of the types in the class hierarchy, collecting possible
     // completions.  If multiple elements are found that complete to the same
     // identifier, addSuggestion will discard all but the first (with a few
@@ -299,6 +302,9 @@
     if (mixins != null) {
       types.addAll(mixins);
     }
+    if (superclassConstraints != null) {
+      types.addAll(superclassConstraints);
+    }
     for (InterfaceType targetType in types) {
       for (MethodElement method in targetType.methods) {
         // Exclude static methods when completion on an instance
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index 2b18345..4c4e5a8 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -60,6 +60,11 @@
   static const CONVERT_INTO_FINAL_FIELD = const AssistKind(
       'dart.assist.convert.getterToFinalField', 30, "Convert to final field",
       associatedErrorCodes: <String>['prefer_final_fields']);
+  static const CONVERT_INTO_ABSOLUTE_IMPORT = const AssistKind(
+      'dart.assist.convert.relativeToAbsoluteImport',
+      30,
+      "Convert to absolute import",
+      associatedErrorCodes: <String>['avoid_relative_lib_imports']);
   static const CONVERT_INTO_FOR_INDEX = const AssistKind(
       'dart.assist.convert.forEachToForIndex', 30, "Convert to for-index loop");
   static const CONVERT_INTO_GENERIC_FUNCTION_SYNTAX = const AssistKind(
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index f092854..ee38d9c 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -104,6 +104,7 @@
     await _addProposal_convertMapConstructorToMapLiteral();
     await _addProposal_convertPartOfToUri();
     await _addProposal_convertSetConstructorToSetLiteral();
+    await _addProposal_convertToAbsoluteImport();
     await _addProposal_convertToAsyncFunctionBody();
     await _addProposal_convertToBlockFunctionBody();
     await _addProposal_convertToDoubleQuotedString();
@@ -1725,6 +1726,29 @@
         changeBuilder, DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY);
   }
 
+  Future<void> _addProposal_convertToAbsoluteImport() async {
+    var node = this.node;
+    if (node is StringLiteral) {
+      node = node.parent;
+    }
+    if (node is ImportDirective) {
+      var importDirective = node;
+      var importUri = node.uriSource?.uri;
+      if (importUri?.scheme != 'package') {
+        return;
+      }
+      var changeBuilder = _newDartChangeBuilder();
+      await changeBuilder.addFileEdit(file, (builder) {
+        builder.addSimpleReplacement(
+            range.node(importDirective.uri), "'$importUri'");
+      });
+      _addAssistFromBuilder(
+        changeBuilder,
+        DartAssistKind.CONVERT_INTO_ABSOLUTE_IMPORT,
+      );
+    }
+  }
+
   Future<void> _addProposal_convertToMultilineString() async {
     var node = this.node;
     if (node is InterpolationElement) {
@@ -2516,7 +2540,10 @@
     await changeBuilder.addFileEdit(file, (builder) {
       builder.addReplacement(range.node(widgetExpr), (builder) {
         builder.writeType(streamBuilderElement.type);
-        builder.writeln('<Object>(');
+
+        builder.write('<');
+        builder.addSimpleLinkedEdit('type', 'Object');
+        builder.writeln('>(');
 
         String indentOld = utils.getLinePrefix(widgetExpr.offset);
         String indentNew1 = indentOld + utils.getIndent(1);
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index ec60587..3bb80d7 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -73,15 +73,36 @@
     errorCode == StaticTypeWarningCode.UNDEFINED_SETTER ||
     errorCode == CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER ||
     (errorCode is LintCode &&
-        (errorCode.name == LintNames.annotate_overrides ||
+        (errorCode.name == LintNames.always_require_non_null_named_parameters ||
+            errorCode.name == LintNames.annotate_overrides ||
+            errorCode.name == LintNames.avoid_annotating_with_dynamic ||
+            errorCode.name == LintNames.avoid_empty_else ||
             errorCode.name == LintNames.avoid_init_to_null ||
+            errorCode.name == LintNames.avoid_return_types_on_setters ||
+            errorCode.name == LintNames.avoid_types_on_closure_parameters ||
+            errorCode.name == LintNames.await_only_futures ||
+            errorCode.name == LintNames.empty_catches ||
+            errorCode.name == LintNames.empty_constructor_bodies ||
+            errorCode.name == LintNames.empty_statements ||
+            errorCode.name == LintNames.no_duplicate_case_values ||
+            errorCode.name == LintNames.non_constant_identifier_names ||
+            errorCode.name == LintNames.null_closures ||
             errorCode.name == LintNames.prefer_collection_literals ||
             errorCode.name == LintNames.prefer_conditional_assignment ||
             errorCode.name == LintNames.prefer_const_declarations ||
+            errorCode.name == LintNames.prefer_equal_for_default_values ||
+            errorCode.name == LintNames.prefer_final_fields ||
+            errorCode.name == LintNames.prefer_final_locals ||
+            errorCode.name == LintNames.prefer_is_not_empty ||
+            errorCode.name == LintNames.type_init_formals ||
+            errorCode.name == LintNames.unawaited_futures ||
             errorCode.name == LintNames.unnecessary_brace_in_string_interps ||
             errorCode.name == LintNames.unnecessary_const ||
             errorCode.name == LintNames.unnecessary_lambdas ||
-            errorCode.name == LintNames.unnecessary_this));
+            errorCode.name == LintNames.unnecessary_new ||
+            errorCode.name == LintNames.unnecessary_overrides ||
+            errorCode.name == LintNames.unnecessary_this ||
+            errorCode.name == LintNames.use_rethrow_when_possible));
 
 /**
  * The implementation of [DartFixContext].
@@ -105,6 +126,8 @@
 class DartFixKind {
   static const ADD_ASYNC =
       const FixKind('ADD_ASYNC', 50, "Add 'async' modifier");
+  static const ADD_AWAIT =
+      const FixKind('ADD_AWAIT', 50, "Add 'await' keyword");
   static const ADD_EXPLICIT_CAST = const FixKind(
       'ADD_EXPLICIT_CAST', 50, "Add cast",
       appliedTogetherMessage: "Add all casts in file");
@@ -262,8 +285,12 @@
   static const REPLACE_BOOLEAN_WITH_BOOL = const FixKind(
       'REPLACE_BOOLEAN_WITH_BOOL', 50, "Replace 'boolean' with 'bool'",
       appliedTogetherMessage: "Replace all 'boolean' with 'bool' in file");
+  static const REPLACE_COLON_WITH_EQUALS =
+      const FixKind('REPLACE_COLON_WITH_EQUALS', 50, "Replace ':' with '='");
   static const REPLACE_FINAL_WITH_CONST = const FixKind(
       'REPLACE_FINAL_WITH_CONST', 50, "Replace 'final' with 'const'");
+  static const REPLACE_NULL_WITH_CLOSURE = const FixKind(
+      'REPLACE_NULL_WITH_CLOSURE', 50, "Replace 'null' with a closure");
   static const REPLACE_RETURN_TYPE_FUTURE = const FixKind(
       'REPLACE_RETURN_TYPE_FUTURE',
       50,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 322e99a..adeb0f9 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -592,12 +592,18 @@
       if (name == LintNames.non_constant_identifier_names) {
         await _addFix_renameToCamelCase();
       }
+      if (name == LintNames.null_closures) {
+        await _addFix_replaceNullWithClosure();
+      }
       if (name == LintNames.prefer_conditional_assignment) {
         await _addFix_replaceWithConditionalAssignment();
       }
       if (errorCode.name == LintNames.prefer_const_declarations) {
         await _addFix_replaceFinalWithConst();
       }
+      if (errorCode.name == LintNames.prefer_equal_for_default_values) {
+        await _addFix_replaceColonWithEquals();
+      }
       if (name == LintNames.prefer_final_fields) {
         await _addFix_makeVariableFinal();
       }
@@ -610,6 +616,9 @@
       if (name == LintNames.type_init_formals) {
         await _addFix_removeTypeAnnotation();
       }
+      if (name == LintNames.unawaited_futures) {
+        await _addFix_addAwait();
+      }
       if (name == LintNames.unnecessary_brace_in_string_interps) {
         await _addFix_removeInterpolationBraces();
       }
@@ -656,6 +665,14 @@
     }
   }
 
+  Future<void> _addFix_addAwait() async {
+    var changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addSimpleInsertion(node.offset, 'await ');
+    });
+    _addFixFromBuilder(changeBuilder, DartFixKind.ADD_AWAIT);
+  }
+
   Future<void> _addFix_addExplicitCast() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
@@ -3162,6 +3179,17 @@
         args: [newName]);
   }
 
+  Future<void> _addFix_replaceColonWithEquals() async {
+    if (node is DefaultFormalParameter) {
+      var changeBuilder = _newDartChangeBuilder();
+      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+        builder.addSimpleReplacement(
+            range.token((node as DefaultFormalParameter).separator), '=');
+      });
+      _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_COLON_WITH_EQUALS);
+    }
+  }
+
   Future<void> _addFix_replaceFinalWithConst() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
@@ -3185,6 +3213,39 @@
     _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_VAR_WITH_DYNAMIC);
   }
 
+  Future<void> _addFix_replaceNullWithClosure() async {
+    var nodeToFix;
+    var parameters = const <ParameterElement>[];
+    if (coveredNode is NamedExpression) {
+      NamedExpression namedExpression = coveredNode;
+      var expression = namedExpression.expression;
+      if (expression is NullLiteral) {
+        var element = namedExpression.element;
+        if (element is ParameterElement) {
+          var type = element.type;
+          if (type is FunctionType) {
+            parameters = type.parameters;
+          }
+        }
+        nodeToFix = expression;
+      }
+    } else if (coveredNode is NullLiteral) {
+      nodeToFix = coveredNode;
+    }
+
+    if (nodeToFix != null) {
+      var changeBuilder = _newDartChangeBuilder();
+      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+        builder.addReplacement(range.node(nodeToFix),
+            (DartEditBuilder builder) {
+          builder.writeParameters(parameters);
+          builder.write(' => null');
+        });
+      });
+      _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_NULL_WITH_CLOSURE);
+    }
+  }
+
   Future<void> _addFix_replaceWithConditionalAssignment() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
@@ -4341,14 +4402,18 @@
   static const String no_duplicate_case_values = 'no_duplicate_case_values';
   static const String non_constant_identifier_names =
       'non_constant_identifier_names';
+  static const String null_closures = 'null_closures';
   static const String prefer_collection_literals = 'prefer_collection_literals';
   static const String prefer_conditional_assignment =
       'prefer_conditional_assignment';
   static const String prefer_const_declarations = 'prefer_const_declarations';
+  static const String prefer_equal_for_default_values =
+      'prefer_equal_for_default_values';
   static const String prefer_final_fields = 'prefer_final_fields';
   static const String prefer_final_locals = 'prefer_final_locals';
   static const String prefer_is_not_empty = 'prefer_is_not_empty';
   static const String type_init_formals = 'type_init_formals';
+  static const String unawaited_futures = 'unawaited_futures';
   static const String unnecessary_brace_in_string_interps =
       'unnecessary_brace_in_string_interps';
   static const String unnecessary_const = 'unnecessary_const';
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index 6135864..f4593b4 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -23,7 +23,6 @@
 import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
 import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' as plugin;
-import 'package:plugin/manager.dart';
 import 'package:test/test.dart';
 import 'package:watcher/watcher.dart';
 
@@ -108,11 +107,6 @@
 
   AnalysisServer createAnalysisServer() {
     //
-    // Process plugins
-    //
-    ExtensionManager manager = new ExtensionManager();
-    manager.processPlugins(AnalysisEngine.instance.requiredPlugins);
-    //
     // Create an SDK in the mock file system.
     //
     new MockSdk(
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 4a7e95d..88938f1 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -17,6 +17,7 @@
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
 import 'package:analyzer/src/generated/sdk.dart';
@@ -30,7 +31,6 @@
 import 'package:linter/src/rules.dart';
 import 'package:linter/src/rules/avoid_as.dart';
 import 'package:path/path.dart' as path;
-import 'package:plugin/manager.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 import 'package:watcher/watcher.dart';
@@ -1722,9 +1722,6 @@
       .firstWhere((ErrorProcessor p) => p.appliesTo(error), orElse: () => null);
 
   void processRequiredPlugins() {
-    ExtensionManager manager = new ExtensionManager();
-    manager.processPlugins(AnalysisEngine.instance.requiredPlugins);
-
     registerLintRules();
   }
 
@@ -1981,7 +1978,9 @@
     String sdkExtPath = '$projPath/sdk_ext';
     newFile('$projPath/test', content: 'test.dart');
     newFile('$sdkExtPath/entry.dart');
-    List<int> bytes = new SummaryBuilder([], null).build();
+    List<int> bytes = new SummaryBuilder(
+            [], RestrictedAnalysisContext(analysisOptions, null, null))
+        .build();
     newFileWithBytes('$projPath/sdk.ds', bytes);
     // Setup _embedder.yaml.
     newFile('$libPath/_embedder.yaml', content: r'''
@@ -2045,8 +2044,10 @@
 
     expect(
         lintNames,
-        unorderedEquals(
-            ['avoid_as' /* embedder */, 'camel_case_types' /* options */]));
+        unorderedEquals([
+          'avoid_as' /* embedder */,
+          'camel_case_types' /* options */
+        ]));
 
     // Sanity check embedder libs.
     var source = sourceFactory.forUri('dart:foobar');
@@ -2498,20 +2499,12 @@
 
     ContextBuilder builder =
         createContextBuilder(folder, options, useSummaries: true);
-    AnalysisContext context = builder.buildContext(folder.path);
-    SourceFactory sourceFactory = context.sourceFactory;
-    AnalysisOptions analysisOptions = context.analysisOptions;
-    context.dispose();
+    builder.analysisDriverScheduler = scheduler;
+    builder.byteStore = MemoryByteStore();
+    builder.performanceLog = logger;
+    builder.fileContentOverlay = FileContentOverlay();
+    currentDriver = builder.buildDriver(contextRoot);
 
-    currentDriver = new AnalysisDriver(
-        scheduler,
-        logger,
-        resourceProvider,
-        new MemoryByteStore(),
-        new FileContentOverlay(),
-        contextRoot,
-        sourceFactory,
-        analysisOptions);
     driverMap[path] = currentDriver;
     currentDriver.exceptions.listen((ExceptionResult result) {
       AnalysisEngine.instance.logger
diff --git a/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart b/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart
index c9be4cd..1ea7f7c 100644
--- a/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart
@@ -44,6 +44,7 @@
 class int {}
 class num {}
 class Object {}
+class Iterable<E> {}
 class Map<K, V> {}
 class Null {}
 class String {}
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index 73f5b37..2955d79 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -5,6 +5,7 @@
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/keyword_contributor.dart';
 import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -14,6 +15,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(KeywordContributorTest);
+    defineReflectiveTests(KeywordContributorWithUiAsCodeTest);
   });
 }
 
@@ -1882,3 +1884,153 @@
     return true;
   }
 }
+
+@reflectiveTest
+class KeywordContributorWithUiAsCodeTest extends KeywordContributorTest {
+  static const List<Keyword> COLLECTION_ELEMENT_START = const [
+    Keyword.CONST,
+    Keyword.FALSE,
+    Keyword.FOR,
+    Keyword.IF,
+    Keyword.NEW,
+    Keyword.NULL,
+    Keyword.TRUE,
+  ];
+
+  @override
+  void setupResourceProvider() {
+    super.setupResourceProvider();
+    createAnalysisOptionsFile(experiments: [
+      EnableString.control_flow_collections,
+      EnableString.spread_collections
+    ]);
+  }
+
+  test_ifOrForElement_forElement() async {
+    addTestSource('''
+f() => [for (var e in c) ^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_ifElement_else() async {
+    addTestSource('''
+f() => [if (true) 1 else ^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_ifElement_then() async {
+    addTestSource('''
+f() => [if (true) ^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_list_empty() async {
+    addTestSource('''
+f() => [^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_list_first() async {
+    addTestSource('''
+f() => [^1, 2];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_list_last() async {
+    addTestSource('''
+f() => [1, 2, ^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_list_middle() async {
+    addTestSource('''
+f() => [1, ^, 2];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_map_empty() async {
+    addTestSource('''
+f() => <String, int>{^};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_map_first() async {
+    addTestSource('''
+f() => <String, int>{^'a' : 1};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_map_last() async {
+    addTestSource('''
+f() => <String, int>{'a' : 1, 'b' : 2, ^};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_map_middle() async {
+    addTestSource('''
+f() => <String, int>{'a' : 1, ^, 'b' : 2];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_set_empty() async {
+    addTestSource('''
+f() => <int>{^};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_set_first() async {
+    addTestSource('''
+f() => <int>{^1, 2};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_set_last() async {
+    addTestSource('''
+f() => <int>{1, 2, ^};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_set_middle() async {
+    addTestSource('''
+f() => <int>{1, ^, 2};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_spreadElement() async {
+    addTestSource('''
+f() => [...^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(KeywordContributorTest.EXPRESSION_START_NO_INSTANCE);
+  }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
index c3712b1..11eb5eb 100644
--- a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
@@ -3659,6 +3659,19 @@
     assertNotSuggested('ms3');
   }
 
+  test_super_fromSuperclassConstraint() async {
+    addTestSource('''
+class C {
+  void c(x, int y) {}
+}
+mixin M on C {
+  m() {super.^}
+}
+''');
+    await computeSuggestions();
+    assertSuggestMethod('c', 'C', 'void');
+  }
+
   test_super_withMixin() async {
     addTestSource('''
 mixin M {
diff --git a/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart b/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
index 4dbfd3c..e99991e 100644
--- a/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
+++ b/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
@@ -134,6 +134,35 @@
 ''');
   }
 
+  test_newImport_part() async {
+    var partCode = r'''
+part of 'test.dart';
+
+main() {} // ref
+''';
+    var partPath = newFile('/home/test/lib/a.dart', content: partCode).path;
+    addTestFile(r'''
+part 'a.dart';
+''');
+
+    var mathSet = await waitForSetWithUri('dart:math');
+    var result = await _getSuggestionDetails(
+      _buildRequest(
+        file: partPath,
+        id: mathSet.id,
+        label: 'sin',
+        offset: partCode.indexOf('} // ref'),
+      ),
+    );
+
+    expect(result.completion, 'sin');
+    _assertTestFileChange(result.change, r'''
+import 'dart:math';
+
+part 'a.dart';
+''');
+  }
+
   void _assertEmptyChange(SourceChange change) {
     expect(change.edits, isEmpty);
   }
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_absolute_import_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_absolute_import_test.dart
new file mode 100644
index 0000000..36e3fab
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_absolute_import_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2019, 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 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertIntoAbsoluteImportTest);
+  });
+}
+
+@reflectiveTest
+class ConvertIntoAbsoluteImportTest extends AssistProcessorTest {
+  @override
+  AssistKind get kind => DartAssistKind.CONVERT_INTO_ABSOLUTE_IMPORT;
+
+  test_fileName_onUri() async {
+    addSource('/home/test/lib/foo.dart', '');
+
+    await resolveTestUnit('''
+import 'foo.dart';
+''');
+    await assertHasAssistAt('foo.dart', '''
+import 'package:test/foo.dart';
+''');
+  }
+
+  test_fileName_onImport() async {
+    addSource('/home/test/lib/foo.dart', '');
+
+    await resolveTestUnit('''
+import 'foo.dart';
+''');
+    // Validate assist is on import keyword too.
+    await assertHasAssistAt('import', '''
+import 'package:test/foo.dart';
+''');
+  }
+
+  test_nonPackage_Uri() async {
+    addSource('/home/test/lib/foo.dart', '');
+
+    await resolveTestUnit('''
+import 'dart:core';
+''');
+
+    await assertNoAssistAt('dart:core');
+    await assertNoAssistAt('import');
+  }
+
+  test_path() async {
+    addSource('/home/test/lib/foo/bar.dart', '');
+
+    testFile = convertPath('/home/test/lib/src/test.dart');
+
+    await resolveTestUnit('''
+import '../foo/bar.dart';
+''');
+    await assertHasAssistAt('bar.dart', '''
+import 'package:test/foo/bar.dart';
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
index 1d75bb9..9bba973 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
@@ -11,6 +11,7 @@
     as convert_documentation_into_block;
 import 'convert_documentation_into_line_test.dart'
     as convert_documentation_into_line;
+import 'convert_into_absolute_import_test.dart' as convert_into_absolute_import;
 import 'convert_into_async_body_test.dart' as convert_into_async_body;
 import 'convert_into_block_body_test.dart' as convert_into_block_body;
 import 'convert_into_expression_body_test.dart' as convert_into_expression_body;
@@ -82,6 +83,7 @@
     convert_class_to_mixin.main();
     convert_documentation_into_block.main();
     convert_documentation_into_line.main();
+    convert_into_absolute_import.main();
     convert_into_async_body.main();
     convert_into_block_body.main();
     convert_into_expression_body.main();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_await_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_await_test.dart
new file mode 100644
index 0000000..1391007
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_await_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2019, 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 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix_internal.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(AddAwaitTest);
+  });
+}
+
+@reflectiveTest
+class AddAwaitTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.ADD_AWAIT;
+
+  @override
+  String get lintCode => LintNames.unawaited_futures;
+
+  test_intLiteral() async {
+    await resolveTestUnit('''
+Future doSomething() => new Future();
+
+void main() async {
+  doSomething()/*LINT*/;
+}
+''');
+    await assertHasFix('''
+Future doSomething() => new Future();
+
+void main() async {
+  await doSomething()/*LINT*/;
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart
new file mode 100644
index 0000000..375a662
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2019, 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 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix_internal.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ReplaceColonWithEqualsTest);
+  });
+}
+
+@reflectiveTest
+class ReplaceColonWithEqualsTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.REPLACE_COLON_WITH_EQUALS;
+
+  @override
+  String get lintCode => LintNames.prefer_equal_for_default_values;
+
+  test_method() async {
+    await resolveTestUnit('''
+void f1({int a}) { }    
+
+f1({a/*LINT*/: 1}) => null;
+''');
+    await assertHasFix('''
+void f1({int a}) { }    
+
+f1({a/*LINT*/= 1}) => null;
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_null_with_closure_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_null_with_closure_test.dart
new file mode 100644
index 0000000..4ada2dd
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_null_with_closure_test.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2019, 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 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix_internal.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ReplaceNullWithClosureTest);
+  });
+}
+
+@reflectiveTest
+class ReplaceNullWithClosureTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.REPLACE_NULL_WITH_CLOSURE;
+
+  @override
+  String get lintCode => LintNames.null_closures;
+
+  test_null_closure_named_expression() async {
+    await resolveTestUnit('''
+main() {
+  [1, 3, 5].firstWhere((e) => e.isOdd, orElse: /*LINT*/null);
+}
+''');
+    await assertHasFix('''
+main() {
+  [1, 3, 5].firstWhere((e) => e.isOdd, orElse: /*LINT*/() => null);
+}
+''');
+  }
+
+  test_null_closure_named_expression_with_args() async {
+    await resolveTestUnit('''
+void f({int closure(x, y)}) { }
+main() {
+  f(closure: /*LINT*/null);
+}
+''');
+    await assertHasFix('''
+void f({int closure(x, y)}) { }
+main() {
+  f(closure: /*LINT*/(x, y) => null);
+}
+''');
+  }
+
+  test_null_closure_named_expression_with_args_2() async {
+    await resolveTestUnit('''
+void f({int closure(x, y, {z})}) { }
+main() {
+  f(closure: /*LINT*/null);
+}
+''');
+    await assertHasFix('''
+void f({int closure(x, y, {z})}) { }
+main() {
+  f(closure: /*LINT*/(x, y, {z}) => null);
+}
+''');
+  }
+
+  /// Currently failing since the LINT annotation is tagging the ArgumentList
+  /// where the fix (and lint) expect a NullLiteral.
+  /// todo (pq): re-write FixProcessorLintTest to run the actual lints.
+  @failingTest
+  test_null_closure_literal() async {
+    await resolveTestUnit('''
+void f(dynamic x) { }
+main() {
+  f(null/*LINT*/);
+}
+''');
+    await assertHasFix('''
+void f(dynamic x) { }
+main() {
+  f(/*LINT*/() => null);
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index 07369fb..9e4fffb 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -5,6 +5,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'add_async_test.dart' as add_async;
+import 'add_await_test.dart' as add_await;
 import 'add_explicit_cast_test.dart' as add_explicit_cast;
 import 'add_field_formal_parameters_test.dart' as add_field_formal_parameters;
 import 'add_missing_parameter_named_test.dart' as add_missing_parameter_named;
@@ -57,6 +58,7 @@
 import 'remove_annotation_test.dart' as remove_annotation;
 import 'remove_await_test.dart' as remove_await;
 import 'remove_dead_code_test.dart' as remove_dead_code;
+import 'remove_duplicate_case_test.dart' as remove_duplicate_case;
 import 'remove_empty_catch_test.dart' as remove_empty_catch;
 import 'remove_empty_constructor_body_test.dart'
     as remove_empty_constructor_body;
@@ -81,7 +83,9 @@
 import 'remove_unused_import_test.dart' as remove_unused_import;
 import 'rename_to_camel_case_test.dart' as rename_to_camel_case;
 import 'replace_boolean_with_bool_test.dart' as replace_boolean_with_bool;
+import 'replace_colon_with_equals_test.dart' as replace_colon_with_equals;
 import 'replace_final_with_const_test.dart' as replace_final_with_const;
+import 'replace_null_with_closure_test.dart' as replace_null_with_closure;
 import 'replace_return_type_future_test.dart' as replace_return_type_future;
 import 'replace_var_with_dynamic_test.dart' as replace_var_with_dynamic;
 import 'replace_with_brackets_test.dart' as replace_with_brackets;
@@ -97,10 +101,12 @@
 import 'use_eq_eq_null_test.dart' as use_eq_eq_null;
 import 'use_is_not_empty_test.dart' as use_is_not_empty;
 import 'use_not_eq_null_test.dart' as use_not_eq_null;
+import 'use_rethrow_test.dart' as use_rethrow;
 
 main() {
   defineReflectiveSuite(() {
     add_async.main();
+    add_await.main();
     add_explicit_cast.main();
     add_field_formal_parameters.main();
     add_missing_parameter_named.main();
@@ -147,6 +153,7 @@
     remove_annotation.main();
     remove_await.main();
     remove_dead_code.main();
+    remove_duplicate_case.main();
     remove_empty_catch.main();
     remove_empty_constructor_body.main();
     remove_empty_else.main();
@@ -168,7 +175,9 @@
     remove_unused_import.main();
     rename_to_camel_case.main();
     replace_boolean_with_bool.main();
+    replace_colon_with_equals.main();
     replace_final_with_const.main();
+    replace_null_with_closure.main();
     replace_return_type_future.main();
     replace_var_with_dynamic.main();
     replace_with_brackets.main();
@@ -182,5 +191,6 @@
     use_eq_eq_null.main();
     use_is_not_empty.main();
     use_not_eq_null.main();
+    use_rethrow.main();
   }, name: 'fix');
 }
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 88eea40..e376b96 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,4 +1,4 @@
-##
+## 0.35.4
 * Deprecated AST structures that will no longer be used after the
   control_flow_collections and spread_collections experiments are enabled.  The
   following AST node types are deprecated:
@@ -13,6 +13,13 @@
   * `visitForStatement` (override `visitForStatement2` instead)
   * `visitMapLiteral` (override `visitSetOrMapLiteral` instead)
   * `visitSetLiteral` (override `visitSetOrMapLiteral` instead)
+* Deprecated ASTFactory methods that will no longer be available after the
+  control_flow_collections and spread_collections experiments are enabled.  The
+  following factory methods are deprecated:
+  * `mapLiteral` and `mapLiteral2` (use `setOrMapLiteral` instead)
+  * `setLiteral` and `setLiteral2` (use `setOrMapLiteral` instead)
+* Bug fixes: #33119, #33241, #35747, #35900, #36048, #36129
+* The analyzer no longer uses `package:html` (see #35802)
 
 ## 0.35.3
 * Further updates to the AST structure for the control_flow_collections and
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 271b921..b2ce8fa 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -4731,8 +4731,17 @@
   /// This getter will always return `false` if [isSet] returns `true`.
   ///
   /// However, this getter is _not_ the inverse of [isSet]. It is possible for
-  /// both getters to return `false` if the literal was either invalid or
-  /// ambiguous.
+  /// both getters to return `false` if
+  ///
+  /// - the AST has not been resolved (because determining the kind of the
+  ///   literal is done during resolution),
+  /// - the literal is ambiguous (contains one or more spread elements and none
+  ///   of those elements can be used to determine the kind of the literal), or
+  /// - the literal is invalid because it contains both expressions (for sets)
+  ///   and map entries (for maps).
+  ///
+  /// In both of the latter two cases there will be compilation errors
+  /// associated with the literal.
   bool get isMap;
 
   /// Return `true` if this literal represents a set literal.
@@ -4740,8 +4749,17 @@
   /// This getter will always return `false` if [isMap] returns `true`.
   ///
   /// However, this getter is _not_ the inverse of [isMap]. It is possible for
-  /// both getters to return `false` if the literal was either invalid or
-  /// ambiguous.
+  /// both getters to return `false` if
+  ///
+  /// - the AST has not been resolved (because determining the kind of the
+  ///   literal is done during resolution),
+  /// - the literal is ambiguous (contains one or more spread elements and none
+  ///   of those elements can be used to determine the kind of the literal), or
+  /// - the literal is invalid because it contains both expressions (for sets)
+  ///   and map entries (for maps).
+  ///
+  /// In both of the latter two cases there will be compilation errors
+  /// associated with the literal.
   bool get isSet;
 
   /// Return the left curly bracket.
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index f4ce6d91..156688d 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2014, 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.
 
@@ -39,13 +39,13 @@
 import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/task/api/model.dart' show AnalysisTarget;
-import 'package:analyzer/src/task/dart.dart';
 
 /// An element that represents a class or a mixin. The class can be defined by
 /// either a class declaration (with a class body), a mixin application (without
@@ -727,10 +727,6 @@
   /// subclasses as being immutable.
   bool get isImmutable;
 
-  /// Return `true` if this annotation marks the associated constructor as
-  /// being literal.
-  bool get isLiteral;
-
   /// Return `true` if this annotation marks the associated member as running
   /// a single test.
   bool get isIsTest;
@@ -743,6 +739,10 @@
   /// `JS` annotation.
   bool get isJS;
 
+  /// Return `true` if this annotation marks the associated constructor as
+  /// being literal.
+  bool get isLiteral;
+
   /// Return `true` if this annotation marks the associated member as requiring
   /// overriding methods to call super.
   bool get isMustCallSuper;
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 92894f9..a4ba3c5 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -67,6 +67,8 @@
   CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
   CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD,
   CompileTimeErrorCode.AMBIGUOUS_EXPORT,
+  CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH,
+  CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER,
   CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS,
   CompileTimeErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS,
   CompileTimeErrorCode.ARGUMENT_DEFINITION_TEST_NON_PARAMETER,
@@ -110,6 +112,8 @@
   CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
   CompileTimeErrorCode.CONST_NOT_INITIALIZED,
   CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
+  CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
+  CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP,
   CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS,
   CompileTimeErrorCode.CONST_WITH_NON_CONST,
   CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT,
@@ -127,6 +131,7 @@
   CompileTimeErrorCode.DUPLICATE_PART,
   CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY,
   CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
+  CompileTimeErrorCode.EXPRESSION_IN_MAP,
   CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS,
   CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
   CompileTimeErrorCode.EXTENDS_NON_CLASS,
@@ -181,6 +186,7 @@
   CompileTimeErrorCode.INVALID_USE_OF_COVARIANT,
   CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE,
   CompileTimeErrorCode.LABEL_UNDEFINED,
+  CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP,
   CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME,
   CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL,
   CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL,
@@ -226,6 +232,8 @@
   CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR,
   CompileTimeErrorCode.NON_SYNC_FACTORY,
   CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS,
+  CompileTimeErrorCode.NOT_ITERABLE_SPREAD,
+  CompileTimeErrorCode.NOT_MAP_SPREAD,
   CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS,
   CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT,
   CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT,
@@ -390,6 +398,7 @@
   ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND,
   ParserErrorCode.EXPECTED_CASE_OR_DEFAULT,
   ParserErrorCode.EXPECTED_CLASS_MEMBER,
+  ParserErrorCode.EXPECTED_ELSE_OR_COMMA,
   ParserErrorCode.EXPECTED_EXECUTABLE,
   ParserErrorCode.EXPECTED_INSTEAD,
   ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL,
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index b6fd429..95a75e7 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -3,57 +3,27 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
-import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/src/cancelable_future.dart';
 import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator;
 import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/utilities_collection.dart';
 import 'package:analyzer/src/plugin/resolver_provider.dart';
-import 'package:analyzer/src/plugin/task.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/api/general.dart';
 import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/dart.dart';
-import 'package:analyzer/src/task/dart_work_manager.dart';
 import 'package:analyzer/src/task/driver.dart';
-import 'package:analyzer/src/task/manager.dart';
-
-/**
- * Type of callback functions used by PendingFuture. Functions of this type
- * should perform a computation based on the data in [entry] and return it. If
- * the computation can't be performed yet because more analysis is needed,
- * `null` should be returned.
- *
- * The function may also throw an exception, in which case the corresponding
- * future will be completed with failure.
- *
- * Because this function is called while the state of analysis is being updated,
- * it should be free of side effects so that it doesn't cause reentrant changes
- * to the analysis state.
- */
-typedef T PendingFutureComputer<T>(CacheEntry entry);
 
 /**
  * An [AnalysisContext] in which analysis can be performed.
  */
 class AnalysisContextImpl implements InternalAnalysisContext {
   /**
-   * The flag that is `true` if the context is being analyzed.
-   */
-  bool _isActive = false;
-
-  /**
    * A client-provided name used to identify this context, or `null` if the
    * client has not provided a name.
    */
@@ -66,22 +36,6 @@
   AnalysisOptionsImpl _options = new AnalysisOptionsImpl();
 
   /**
-   * The embedder yaml locator for this context.
-   */
-  @deprecated
-  EmbedderYamlLocator _embedderYamlLocator = new EmbedderYamlLocator(null);
-
-  /**
-   * A flag indicating whether this context is disposed.
-   */
-  bool _disposed = false;
-
-  /**
-   * A cache of content used to override the default content of a source.
-   */
-  ContentCache _contentCache = new ContentCache();
-
-  /**
    * The source factory used to create the sources that can be analyzed in this
    * context.
    */
@@ -92,18 +46,6 @@
    */
   DeclaredVariables _declaredVariables = new DeclaredVariables();
 
-  /**
-   * The partition that contains analysis results that are not shared with other
-   * contexts.
-   */
-  CachePartition _privatePartition;
-
-  /**
-   * The cache in which information about the results associated with targets
-   * are stored.
-   */
-  AnalysisCache _cache;
-
   @override
   final ReentrantSynchronousStream<InvalidatedResult> onResultInvalidated =
       new ReentrantSynchronousStream<InvalidatedResult>();
@@ -111,55 +53,17 @@
   ReentrantSynchronousStreamSubscription onResultInvalidatedSubscription = null;
 
   /**
-   * Configuration data associated with this context.
-   */
-  final HashMap<ResultDescriptor, Object> _configurationData =
-      new HashMap<ResultDescriptor, Object>();
-
-  /**
-   * The task manager used to manage the tasks used to analyze code.
-   */
-  TaskManager _taskManager;
-
-  /**
    * A list of all [WorkManager]s used by this context.
    */
   @override
   final List<WorkManager> workManagers = <WorkManager>[];
 
   /**
-   * The [DartWorkManager] instance that performs Dart specific scheduling.
-   */
-  DartWorkManager dartWorkManager;
-
-  /**
    * The analysis driver used to perform analysis.
    */
   AnalysisDriver driver;
 
   /**
-   * A list containing sources for which data should not be flushed.
-   */
-  List<Source> _priorityOrder = <Source>[];
-
-  CacheConsistencyValidatorImpl _cacheConsistencyValidator;
-
-  /**
-   * A map from all sources for which there are futures pending to a list of
-   * the corresponding PendingFuture objects.  These sources will be analyzed
-   * in the same way as priority sources, except with higher priority.
-   */
-  Map<AnalysisTarget, List<PendingFuture>> _pendingFutureTargets =
-      new HashMap<AnalysisTarget, List<PendingFuture>>();
-
-  /**
-   * A table mapping sources to the change notices that are waiting to be
-   * returned related to that source.
-   */
-  Map<Source, ChangeNoticeImpl> _pendingNotices =
-      new HashMap<Source, ChangeNoticeImpl>();
-
-  /**
    * The [TypeProvider] for this context, `null` if not yet created.
    */
   TypeProvider _typeProvider;
@@ -170,23 +74,6 @@
   TypeSystem _typeSystem;
 
   /**
-   * The controller for sending [SourcesChangedEvent]s.
-   */
-  StreamController<SourcesChangedEvent> _onSourcesChangedController;
-
-  /**
-   * A subscription for a stream of events indicating when files are (and are
-   * not) being implicitly analyzed.
-   */
-  StreamController<ImplicitAnalysisEvent> _implicitAnalysisEventsController;
-
-  /**
-   * The listeners that are to be notified when various analysis results are
-   * produced in this context.
-   */
-  List<AnalysisListener> _listeners = new List<AnalysisListener>();
-
-  /**
    * Determines whether this context should attempt to make use of the global
    * SDK cache partition. Note that if this context is responsible for
    * resynthesizing the SDK element model, this flag should be set to `false`,
@@ -199,13 +86,6 @@
   ResultProvider resultProvider;
 
   /**
-   * The map of [ResultChangedEvent] controllers.
-   */
-  final Map<ResultDescriptor, StreamController<ResultChangedEvent>>
-      _resultChangedControllers =
-      <ResultDescriptor, StreamController<ResultChangedEvent>>{};
-
-  /**
    * The most recently incrementally resolved source, or `null` when it was
    * already validated, or the most recent change was not incrementally resolved.
    */
@@ -230,30 +110,12 @@
   /**
    * Initialize a newly created analysis context.
    */
-  AnalysisContextImpl() {
-    AnalysisEngine.instance.processRequiredPlugins();
-    _privatePartition = new UniversalCachePartition(this);
-    _cache = createCacheFromSourceFactory(null);
-    _taskManager = AnalysisEngine.instance.taskManager;
-    for (WorkManagerFactory factory
-        in AnalysisEngine.instance.enginePlugin.workManagerFactories) {
-      WorkManager workManager = factory(this);
-      if (workManager != null) {
-        workManagers.add(workManager);
-        if (workManager is DartWorkManager) {
-          dartWorkManager = workManager;
-        }
-      }
-    }
-    driver = new AnalysisDriver(_taskManager, workManagers, this);
-    _onSourcesChangedController =
-        new StreamController<SourcesChangedEvent>.broadcast();
-    _implicitAnalysisEventsController =
-        new StreamController<ImplicitAnalysisEvent>.broadcast();
-  }
+  AnalysisContextImpl();
 
   @override
-  AnalysisCache get analysisCache => _cache;
+  AnalysisCache get analysisCache {
+    throw UnimplementedError();
+  }
 
   @override
   AnalysisOptions get analysisOptions => _options;
@@ -261,37 +123,20 @@
   @override
   void set analysisOptions(AnalysisOptions options) {
     this._options = options;
-    for (WorkManager workManager in workManagers) {
-      workManager.onAnalysisOptionsChanged();
-    }
   }
 
   @override
   void set analysisPriorityOrder(List<Source> sources) {
-    if (sources == null || sources.isEmpty) {
-      _priorityOrder = const <Source>[];
-    } else {
-      while (sources.remove(null)) {
-        // Nothing else to do.
-      }
-      if (sources.isEmpty) {
-        _priorityOrder = const <Source>[];
-      } else {
-        _priorityOrder = sources;
-      }
-    }
-    for (WorkManager workManager in workManagers) {
-      workManager.applyPriorityTargets(_priorityOrder);
-    }
-    driver.reset();
+    throw UnimplementedError();
   }
 
-  CacheConsistencyValidator get cacheConsistencyValidator =>
-      _cacheConsistencyValidator ??= new CacheConsistencyValidatorImpl(this);
+  CacheConsistencyValidator get cacheConsistencyValidator {
+    throw UnimplementedError();
+  }
 
   @override
   set contentCache(ContentCache value) {
-    _contentCache = value;
+    throw UnimplementedError();
   }
 
   @override
@@ -306,117 +151,86 @@
 
   @deprecated
   @override
-  EmbedderYamlLocator get embedderYamlLocator => _embedderYamlLocator;
+  EmbedderYamlLocator get embedderYamlLocator {
+    throw UnimplementedError();
+  }
 
   @override
   List<AnalysisTarget> get explicitTargets {
-    List<AnalysisTarget> targets = <AnalysisTarget>[];
-    MapIterator<AnalysisTarget, CacheEntry> iterator = _cache.iterator();
-    while (iterator.moveNext()) {
-      if (iterator.value.explicitlyAdded) {
-        targets.add(iterator.key);
-      }
-    }
-    return targets;
+    throw UnimplementedError();
   }
 
   @override
-  List<Source> get htmlSources => _getSources(SourceKind.HTML);
+  List<Source> get htmlSources {
+    throw UnimplementedError();
+  }
 
   @override
-  Stream<ImplicitAnalysisEvent> get implicitAnalysisEvents =>
-      _implicitAnalysisEventsController.stream;
+  Stream<ImplicitAnalysisEvent> get implicitAnalysisEvents {
+    throw UnimplementedError();
+  }
 
   @override
-  bool get isActive => _isActive;
+  bool get isActive {
+    throw UnimplementedError();
+  }
 
   @override
   set isActive(bool active) {
-    if (active != _isActive) {
-      _isActive = active;
-      _privatePartition.isActive = active;
-    }
+    throw UnimplementedError();
   }
 
   @override
-  bool get isDisposed => _disposed;
+  bool get isDisposed {
+    throw UnimplementedError();
+  }
 
   @override
   List<Source> get launchableClientLibrarySources {
-    List<Source> sources = <Source>[];
-    for (Source source in _cache.sources) {
-      CacheEntry entry = _cache.get(source);
-      if (entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY &&
-          !source.isInSystemLibrary &&
-          isClientLibrary(source)) {
-        sources.add(source);
-      }
-    }
-    return sources;
+    throw UnimplementedError();
   }
 
   @override
   List<Source> get launchableServerLibrarySources {
-    List<Source> sources = <Source>[];
-    for (Source source in _cache.sources) {
-      CacheEntry entry = _cache.get(source);
-      if (entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY &&
-          !source.isInSystemLibrary &&
-          isServerLibrary(source)) {
-        sources.add(source);
-      }
-    }
-    return sources;
+    throw UnimplementedError();
   }
 
   @override
-  List<Source> get librarySources => _getSources(SourceKind.LIBRARY);
+  List<Source> get librarySources {
+    throw UnimplementedError();
+  }
 
   @override
-  Stream<SourcesChangedEvent> get onSourcesChanged =>
-      _onSourcesChangedController.stream;
-
-  /**
-   * Make _pendingFutureSources available to unit tests.
-   */
-  Map<AnalysisTarget, List<PendingFuture>>
-      get pendingFutureSources_forTesting => _pendingFutureTargets;
+  Stream<SourcesChangedEvent> get onSourcesChanged {
+    throw UnimplementedError();
+  }
 
   @override
-  List<Source> get prioritySources => _priorityOrder;
+  List<Source> get prioritySources {
+    throw UnimplementedError();
+  }
 
   @override
-  List<AnalysisTarget> get priorityTargets => prioritySources;
+  List<AnalysisTarget> get priorityTargets {
+    throw UnimplementedError();
+  }
 
   @override
-  CachePartition get privateAnalysisCachePartition => _privatePartition;
+  CachePartition get privateAnalysisCachePartition {
+    throw UnimplementedError();
+  }
 
   @override
   SourceFactory get sourceFactory => _sourceFactory;
 
   @override
   void set sourceFactory(SourceFactory factory) {
-    if (identical(_sourceFactory, factory)) {
-      return;
-    } else if (factory.context != null) {
-      throw new StateError(
-          "Source factories cannot be shared between contexts");
-    }
-    if (_sourceFactory != null) {
-      _sourceFactory.context = null;
-    }
-    factory.context = this;
     _sourceFactory = factory;
-    _cache?.dispose();
-    _cache = createCacheFromSourceFactory(factory);
-    for (WorkManager workManager in workManagers) {
-      workManager.onSourceFactoryChanged();
-    }
   }
 
   @override
   List<Source> get sources {
-    return _cache.sources.toList();
+    throw UnimplementedError();
   }
 
   /**
@@ -426,57 +240,15 @@
    * testing purposes only.
    */
   List<Source> get sourcesNeedingProcessing {
-    HashSet<Source> sources = new HashSet<Source>();
-    bool hintsEnabled = _options.hint;
-    bool lintsEnabled = _options.lint;
-
-    MapIterator<AnalysisTarget, CacheEntry> iterator =
-        _privatePartition.iterator();
-    while (iterator.moveNext()) {
-      AnalysisTarget target = iterator.key;
-      if (target is Source) {
-        _getSourcesNeedingProcessing(
-            target, iterator.value, false, hintsEnabled, lintsEnabled, sources);
-      }
-    }
-    return new List<Source>.from(sources);
+    throw UnimplementedError();
   }
 
-  List<Source> get test_priorityOrder => _priorityOrder;
+  List<Source> get test_priorityOrder {
+    throw UnimplementedError();
+  }
 
   @override
   TypeProvider get typeProvider {
-    // The `AnalysisContextTarget.request` results go into the SDK partition,
-    // and the TYPE_PROVIDER result is computed and put into the SDK partition
-    // only by the first non-SDK analysis context. So, in order to reuse it
-    // in other analysis contexts, we need to ask for it from the cache.
-    _typeProvider ??= getResult(AnalysisContextTarget.request, TYPE_PROVIDER);
-    if (_typeProvider != null) {
-      return _typeProvider;
-    }
-
-    // Make sure a task didn't accidentally try to call back into the context
-    // to retrieve the type provider.
-    assert(!driver.isTaskRunning);
-
-    Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE);
-    if (coreSource == null) {
-      throw new AnalysisException("Could not create a source for dart:core");
-    }
-    LibraryElement coreElement = computeLibraryElement(coreSource);
-    if (coreElement == null) {
-      throw new AnalysisException("Could not create an element for dart:core");
-    }
-
-    Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
-    if (asyncSource == null) {
-      throw new AnalysisException("Could not create a source for dart:async");
-    }
-    LibraryElement asyncElement = computeLibraryElement(asyncSource);
-    if (asyncElement == null) {
-      throw new AnalysisException("Could not create an element for dart:async");
-    }
-    _typeProvider = new TypeProviderImpl(coreElement, asyncElement);
     return _typeProvider;
   }
 
@@ -490,411 +262,175 @@
 
   @override
   TypeSystem get typeSystem {
-    if (_typeSystem == null) {
-      _typeSystem = TypeSystem.create(this);
-    }
-    return _typeSystem;
+    return _typeSystem ??= Dart2TypeSystem(typeProvider);
   }
 
   @override
   bool aboutToComputeResult(CacheEntry entry, ResultDescriptor result) {
-    return PerformanceStatistics.summary.makeCurrentWhile(() {
-      // Use this helper if it is set.
-      if (resultProvider != null && resultProvider.compute(entry, result)) {
-        return true;
-      }
-      // Ask the SDK.
-      DartSdk dartSdk = sourceFactory.dartSdk;
-      if (dartSdk != null) {
-        AnalysisContext sdkContext = dartSdk.context;
-        if (!identical(sdkContext, this) &&
-            sdkContext is InternalAnalysisContext) {
-          return sdkContext.aboutToComputeResult(entry, result);
-        }
-      }
-      // Cannot provide the result.
-      return false;
-    });
+    throw UnimplementedError();
   }
 
   @override
   void addListener(AnalysisListener listener) {
-    if (!_listeners.contains(listener)) {
-      _listeners.add(listener);
-    }
+    throw UnimplementedError();
   }
 
   @override
   void applyAnalysisDelta(AnalysisDelta delta) {
-    ChangeSet changeSet = new ChangeSet();
-    delta.analysisLevels.forEach((Source source, AnalysisLevel level) {
-      if (level == AnalysisLevel.NONE) {
-        changeSet.removedSource(source);
-      } else {
-        changeSet.addedSource(source);
-      }
-    });
-    applyChanges(changeSet);
+    throw UnimplementedError();
   }
 
   @override
   void applyChanges(ChangeSet changeSet) {
-    if (changeSet.isEmpty) {
-      return;
-    }
-    //
-    // First, compute the list of sources that have been removed.
-    //
-    List<Source> removedSources = changeSet.removedSources.toList();
-    for (SourceContainer container in changeSet.removedContainers) {
-      _addSourcesInContainer(removedSources, container);
-    }
-    //
-    // Then determine which cached results are no longer valid.
-    //
-    for (Source source in changeSet.addedSources) {
-      _sourceAvailable(source);
-    }
-    // Exclude sources that are overridden in the content cache, so the change
-    // will have no effect. Just ignore it to avoid wasting time doing
-    // re-analysis.
-    List<Source> changedSources = changeSet.changedSources
-        .where((s) => _contentCache.getContents(s) == null)
-        .toList();
-    for (Source source in changedSources) {
-      _sourceChanged(source);
-    }
-    changeSet.changedContents.forEach((Source key, String value) {
-      _contentsChanged(key, value, false);
-    });
-    changeSet.changedRanges
-        .forEach((Source source, ChangeSet_ContentChange change) {
-      _contentRangeChanged(source, change.contents, change.offset,
-          change.oldLength, change.newLength);
-    });
-    for (Source source in removedSources) {
-      _sourceRemoved(source);
-    }
-    for (WorkManager workManager in workManagers) {
-      workManager.applyChange(
-          changeSet.addedSources, changedSources, removedSources);
-    }
-    _onSourcesChangedController.add(new SourcesChangedEvent(changeSet));
+    throw UnimplementedError();
   }
 
   @override
-  String computeDocumentationComment(Element element) =>
-      element?.documentationComment;
+  String computeDocumentationComment(Element element) {
+    throw UnimplementedError();
+  }
 
   @override
   List<AnalysisError> computeErrors(Source source) {
-    return computeResult(source, DART_ERRORS);
+    throw UnimplementedError();
   }
 
   @override
-  List<Source> computeExportedLibraries(Source source) =>
-      computeResult(source, EXPORTED_LIBRARIES);
+  List<Source> computeExportedLibraries(Source source) {
+    throw UnimplementedError();
+  }
 
   @override
-  List<Source> computeImportedLibraries(Source source) =>
-      computeResult(source, EXPLICITLY_IMPORTED_LIBRARIES);
+  List<Source> computeImportedLibraries(Source source) {
+    throw UnimplementedError();
+  }
 
   @override
   SourceKind computeKindOf(Source source) {
-    String name = source.shortName;
-    if (AnalysisEngine.isDartFileName(name)) {
-      return computeResult(source, SOURCE_KIND);
-    }
-    return SourceKind.UNKNOWN;
+    throw UnimplementedError();
   }
 
   @override
   LibraryElement computeLibraryElement(Source source) {
-    //_computeResult(source, HtmlEntry.ELEMENT);
-    return computeResult(source, LIBRARY_ELEMENT);
+    throw UnimplementedError();
   }
 
   @override
-  LineInfo computeLineInfo(Source source) => computeResult(source, LINE_INFO);
+  LineInfo computeLineInfo(Source source) {
+    throw UnimplementedError();
+  }
 
   @override
   CancelableFuture<CompilationUnit> computeResolvedCompilationUnitAsync(
       Source unitSource, Source librarySource) {
-    if (!AnalysisEngine.isDartFileName(unitSource.shortName) ||
-        !AnalysisEngine.isDartFileName(librarySource.shortName)) {
-      return new CancelableFuture.error(new AnalysisNotScheduledError());
-    }
-    return new AnalysisFutureHelper<CompilationUnit>(this,
-            new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT)
-        .computeAsync();
+    throw UnimplementedError();
   }
 
   @override
   V computeResult<V>(AnalysisTarget target, ResultDescriptor<V> descriptor) {
-    // Make sure we are not trying to invoke the task model in a reentrant
-    // fashion.
-    assert(!driver.isTaskRunning);
-    CacheEntry entry = getCacheEntry(target);
-    CacheState state = entry.getState(descriptor);
-    if (state == CacheState.FLUSHED || state == CacheState.INVALID) {
-      // Check the result provider.
-      bool success = aboutToComputeResult(entry, descriptor);
-      if (success) {
-        return entry.getValue(descriptor);
-      }
-      // Compute the result.
-      driver.computeResult(target, descriptor);
-      entry = getCacheEntry(target);
-    }
-    state = entry.getState(descriptor);
-    if (state == CacheState.ERROR) {
-      throw new AnalysisException(
-          'Cannot compute $descriptor for $target', entry.exception);
-    }
-    return entry.getValue(descriptor);
+    throw UnimplementedError();
   }
 
   /**
    * Create an analysis cache based on the given source [factory].
    */
   AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
-    AnalysisCache createCache() {
-      if (factory == null) {
-        return new AnalysisCache(<CachePartition>[_privatePartition]);
-      }
-      if (!useSdkCachePartition) {
-        return new AnalysisCache(<CachePartition>[_privatePartition]);
-      }
-      DartSdk sdk = factory.dartSdk;
-      if (sdk == null) {
-        return new AnalysisCache(<CachePartition>[_privatePartition]);
-      }
-      return new AnalysisCache(<CachePartition>[
-        AnalysisEngine.instance.partitionManager.forSdk(sdk),
-        _privatePartition
-      ]);
-    }
-
-    AnalysisCache cache = createCache();
-    onResultInvalidatedSubscription?.cancel();
-    onResultInvalidatedSubscription =
-        cache.onResultInvalidated.listen((InvalidatedResult event) {
-      onResultInvalidated.add(event);
-      StreamController<ResultChangedEvent> controller =
-          _resultChangedControllers[event.descriptor];
-      if (controller != null) {
-        controller.add(new ResultChangedEvent(
-            this, event.entry.target, event.descriptor, event.value, false));
-      }
-    });
-    return cache;
+    throw UnimplementedError();
   }
 
   @override
-  void dispose() {
-    _disposed = true;
-    for (List<PendingFuture> pendingFutures in _pendingFutureTargets.values) {
-      for (PendingFuture pendingFuture in pendingFutures) {
-        pendingFuture.forciblyComplete();
-      }
-    }
-    _pendingFutureTargets.clear();
-    _privatePartition.dispose();
-    _cache.dispose();
-  }
+  void dispose() {}
 
   @override
   List<CompilationUnit> ensureResolvedDartUnits(Source unitSource) {
-    // Check every library.
-    List<CompilationUnit> units = <CompilationUnit>[];
-    List<Source> containingLibraries = getLibrariesContaining(unitSource);
-    for (Source librarySource in containingLibraries) {
-      LibrarySpecificUnit target =
-          new LibrarySpecificUnit(librarySource, unitSource);
-      CompilationUnit unit = getResult(target, RESOLVED_UNIT);
-      if (unit == null) {
-        units = null;
-        break;
-      }
-      units.add(unit);
-    }
-    // If we have results, then we're done.
-    if (units != null) {
-      return units;
-    }
-    // Schedule computing of RESOLVED_UNIT results.
-    for (Source librarySource in containingLibraries) {
-      LibrarySpecificUnit target =
-          new LibrarySpecificUnit(librarySource, unitSource);
-      dartWorkManager.addPriorityResult(target, RESOLVED_UNIT);
-    }
-    return null;
+    throw UnimplementedError();
   }
 
   @override
   bool exists(Source source) {
-    if (source == null) {
-      return false;
-    }
-    bool overriddenExists = _contentCache.getExists(source);
-    if (overriddenExists != null) {
-      return overriddenExists;
-    }
-    return source.exists();
+    throw UnimplementedError();
   }
 
   @override
   CacheEntry getCacheEntry(AnalysisTarget target) {
-    CacheEntry entry = _cache.get(target);
-    if (entry == null) {
-      entry = new CacheEntry(target);
-      ImplicitAnalysisEvent event = null;
-      if (target is Source) {
-        entry.modificationTime = getModificationStamp(target);
-        event = new ImplicitAnalysisEvent(target, true);
-      }
-      _cache.put(entry);
-      if (event != null) {
-        _implicitAnalysisEventsController.add(event);
-      }
-    }
-    return entry;
+    throw UnimplementedError();
   }
 
   @override
   CompilationUnitElement getCompilationUnitElement(
       Source unitSource, Source librarySource) {
-    AnalysisTarget target = new LibrarySpecificUnit(librarySource, unitSource);
-    return getResult(target, COMPILATION_UNIT_ELEMENT);
+    throw UnimplementedError();
   }
 
   @deprecated
   @override
-  V getConfigurationData<V>(ResultDescriptor<V> key) =>
-      (_configurationData[key] ?? key?.defaultValue) as V;
-
-  @override
-  TimestampedData<String> getContents(Source source) {
-    String contents = _contentCache.getContents(source);
-    if (contents != null) {
-      return new TimestampedData<String>(
-          _contentCache.getModificationStamp(source), contents);
-    }
-    return source.contents;
+  V getConfigurationData<V>(ResultDescriptor<V> key) {
+    throw UnimplementedError();
   }
 
   @override
-  InternalAnalysisContext getContextFor(Source source) =>
-      _cache.getContextFor(source) ?? this;
+  TimestampedData<String> getContents(Source source) {
+    throw UnimplementedError();
+  }
+
+  @override
+  InternalAnalysisContext getContextFor(Source source) {
+    throw UnimplementedError();
+  }
 
   @override
   Element getElement(ElementLocation location) {
-    // TODO(brianwilkerson) This should not be a "get" method.
-    try {
-      List<String> components = location.components;
-      Source source = _computeSourceFromEncoding(components[0]);
-      String sourceName = source.shortName;
-      if (AnalysisEngine.isDartFileName(sourceName)) {
-        ElementImpl element = computeLibraryElement(source) as ElementImpl;
-        for (int i = 1; i < components.length; i++) {
-          if (element == null) {
-            return null;
-          }
-          element = element.getChild(components[i]);
-        }
-        return element;
-      }
-    } catch (exception) {
-      // If the location cannot be decoded for some reason then the underlying
-      // cause should have been logged already and we can fall though to return
-      // null.
-    }
-    return null;
+    throw UnimplementedError();
   }
 
   @override
   AnalysisErrorInfo getErrors(Source source) {
-    List<AnalysisError> allErrors = <AnalysisError>[];
-    for (WorkManager workManager in workManagers) {
-      List<AnalysisError> errors = workManager.getErrors(source);
-      allErrors.addAll(errors);
-    }
-    LineInfo lineInfo = getLineInfo(source);
-    return new AnalysisErrorInfoImpl(allErrors, lineInfo);
+    throw UnimplementedError();
   }
 
   @override
   List<Source> getHtmlFilesReferencing(Source source) {
-    return const <Source>[];
+    throw UnimplementedError();
   }
 
   @override
   SourceKind getKindOf(Source source) {
-    String name = source.shortName;
-    if (AnalysisEngine.isDartFileName(name)) {
-      return getResult(source, SOURCE_KIND);
-    }
-    return SourceKind.UNKNOWN;
+    throw UnimplementedError();
   }
 
   @override
   List<Source> getLibrariesContaining(Source source) {
-    SourceKind kind = getKindOf(source);
-    if (kind == SourceKind.LIBRARY) {
-      return <Source>[source];
-    }
-    return dartWorkManager.getLibrariesContainingPart(source);
+    throw UnimplementedError();
   }
 
   @override
   List<Source> getLibrariesDependingOn(Source librarySource) {
-    List<Source> dependentLibraries = <Source>[];
-    for (Source source in _cache.sources) {
-      CacheEntry entry = _cache.get(source);
-      if (entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY) {
-        if (_contains(entry.getValue(EXPORTED_LIBRARIES), librarySource)) {
-          dependentLibraries.add(source);
-        }
-        if (_contains(entry.getValue(IMPORTED_LIBRARIES), librarySource)) {
-          dependentLibraries.add(source);
-        }
-      }
-    }
-    if (dependentLibraries.isEmpty) {
-      return const <Source>[];
-    }
-    return dependentLibraries;
+    throw UnimplementedError();
   }
 
   @override
   List<Source> getLibrariesReferencedFromHtml(Source htmlSource) {
-    return const <Source>[];
+    throw UnimplementedError();
   }
 
   @override
-  LibraryElement getLibraryElement(Source source) =>
-      getResult(source, LIBRARY_ELEMENT);
+  LibraryElement getLibraryElement(Source source) {
+    throw UnimplementedError();
+  }
 
   @override
-  LineInfo getLineInfo(Source source) => getResult(source, LINE_INFO);
+  LineInfo getLineInfo(Source source) {
+    throw UnimplementedError();
+  }
 
   @override
   int getModificationStamp(Source source) {
-    int stamp = _contentCache.getModificationStamp(source);
-    if (stamp != null) {
-      return stamp;
-    }
-    return source.modificationStamp;
+    throw UnimplementedError();
   }
 
   @override
   ChangeNoticeImpl getNotice(Source source) {
-    ChangeNoticeImpl notice = _pendingNotices[source];
-    if (notice == null) {
-      notice = new ChangeNoticeImpl(source);
-      _pendingNotices[source] = notice;
-    }
-    return notice;
+    throw UnimplementedError();
   }
 
   @override
@@ -913,87 +449,29 @@
   @override
   CompilationUnit getResolvedCompilationUnit(
       Source unitSource, LibraryElement library) {
-    if (library == null ||
-        !AnalysisEngine.isDartFileName(unitSource.shortName)) {
-      return null;
-    }
-    return getResolvedCompilationUnit2(unitSource, library.source);
+    throw UnimplementedError();
   }
 
   @override
   CompilationUnit getResolvedCompilationUnit2(
       Source unitSource, Source librarySource) {
-    if (!AnalysisEngine.isDartFileName(unitSource.shortName) ||
-        !AnalysisEngine.isDartFileName(librarySource.shortName)) {
-      return null;
-    }
-    return getResult(
-        new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT);
+    throw UnimplementedError();
   }
 
   @override
   V getResult<V>(AnalysisTarget target, ResultDescriptor<V> result) {
-    return _cache.getValue(target, result);
+    throw UnimplementedError();
   }
 
   @override
   List<Source> getSourcesWithFullName(String path) {
-    return analysisCache.getSourcesWithFullName(path);
+    throw UnimplementedError();
   }
 
   @override
   bool handleContentsChanged(
       Source source, String originalContents, String newContents, bool notify) {
-    CacheEntry entry = _cache.get(source);
-    if (entry == null) {
-      return false;
-    }
-    // If there were no "originalContents" in the content cache,
-    // use the contents of the file instead.
-    if (originalContents == null) {
-      try {
-        TimestampedData<String> fileContents = source.contents;
-        if (fileContents.modificationTime == entry.modificationTime) {
-          originalContents = fileContents.data;
-        }
-      } catch (e) {}
-    }
-    bool changed = newContents != originalContents;
-    if (newContents != null) {
-      if (changed) {
-        entry.modificationTime = _contentCache.getModificationStamp(source);
-        // Don't compare with old contents because the cache has already been
-        // updated, and we know at this point that it changed.
-        _sourceChanged(source, compareWithOld: false);
-        entry.setValue(CONTENT, newContents, const <TargetedResult>[]);
-      } else {
-        entry.modificationTime = _contentCache.getModificationStamp(source);
-      }
-    } else if (originalContents != null) {
-      // We are removing the overlay for the file, check if the file's
-      // contents is the same as it was in the overlay.
-      try {
-        TimestampedData<String> fileContents = getContents(source);
-        newContents = fileContents.data;
-        entry.modificationTime = fileContents.modificationTime;
-        if (newContents == originalContents) {
-          entry.setValue(CONTENT, newContents, const <TargetedResult>[]);
-          changed = false;
-        }
-      } catch (e) {}
-      // If not the same content (e.g. the file is being closed without save),
-      // then force analysis.
-      if (changed) {
-        if (newContents == null) {
-          _sourceChanged(source);
-        }
-      }
-    }
-    if (notify && changed) {
-      _onSourcesChangedController
-          .add(new SourcesChangedEvent.changedContent(source, newContents));
-    }
-    return changed;
+    throw UnimplementedError();
   }
 
   /**
@@ -1001,797 +479,97 @@
    * to do.
    */
   void invalidateCachedResults() {
-    _cache?.dispose();
-    _cache = createCacheFromSourceFactory(_sourceFactory);
-    for (WorkManager workManager in workManagers) {
-      workManager.onAnalysisOptionsChanged();
-    }
+    throw UnimplementedError();
   }
 
   @override
   void invalidateLibraryHints(Source librarySource) {
-    List<Source> sources = getResult(librarySource, UNITS);
-    if (sources != null) {
-      for (Source source in sources) {
-        getCacheEntry(source).setState(HINTS, CacheState.INVALID);
-      }
-    }
+    throw UnimplementedError();
   }
 
   @override
   bool isClientLibrary(Source librarySource) {
-    CacheEntry entry = _cache.get(librarySource);
-    return entry != null &&
-        _referencesDartHtml(librarySource) &&
-        entry.getValue(IS_LAUNCHABLE);
+    throw UnimplementedError();
   }
 
   @override
   bool isServerLibrary(Source librarySource) {
-    CacheEntry entry = _cache.get(librarySource);
-    return entry != null &&
-        !_referencesDartHtml(librarySource) &&
-        entry.getValue(IS_LAUNCHABLE);
+    throw UnimplementedError();
   }
 
   @override
   Stream<ResultChangedEvent> onResultChanged(ResultDescriptor descriptor) {
-    driver.onResultComputed(descriptor).listen((ResultChangedEvent event) {
-      _resultChangedControllers[descriptor]?.add(event);
-    });
-    return _resultChangedControllers.putIfAbsent(descriptor, () {
-      return new StreamController<ResultChangedEvent>.broadcast(sync: true);
-    }).stream;
+    throw UnimplementedError();
   }
 
   @override
   @deprecated
   Stream<ComputedResult> onResultComputed(ResultDescriptor descriptor) {
-    return onResultChanged(descriptor)
-        .where((event) => event.wasComputed)
-        .map((event) {
-      return new ComputedResult(
-          event.context, event.descriptor, event.target, event.value);
-    });
+    throw UnimplementedError();
   }
 
   @override
   CompilationUnit parseCompilationUnit(Source source) {
-    if (!AnalysisEngine.isDartFileName(source.shortName)) {
-      return null;
-    }
-    try {
-      getContents(source);
-    } catch (exception, stackTrace) {
-      throw new AnalysisException('Could not get contents of $source',
-          new CaughtException(exception, stackTrace));
-    }
-    return computeResult(source, PARSED_UNIT);
+    throw UnimplementedError();
   }
 
   @override
   AnalysisResult performAnalysisTask() {
-    return PerformanceStatistics.analysis.makeCurrentWhile(() {
-      _evaluatePendingFutures();
-      bool done = !driver.performAnalysisTask();
-      List<ChangeNotice> notices = _getChangeNotices(done);
-      if (notices != null) {
-        int noticeCount = notices.length;
-        for (int i = 0; i < noticeCount; i++) {
-          ChangeNotice notice = notices[i];
-          _notifyErrors(notice.source, notice.errors, notice.lineInfo);
-        }
-      }
-      return new AnalysisResult(notices, -1, '', -1);
-    });
+    throw UnimplementedError();
   }
 
   @override
   void recordLibraryElements(Map<Source, LibraryElement> elementMap) {
-    elementMap.forEach((Source librarySource, LibraryElement library) {
-      //
-      // Cache the element in the library's info.
-      //
-      CacheEntry entry = getCacheEntry(librarySource);
-      setValue(ResultDescriptor result, value) {
-        entry.setValue(result, value, const <TargetedResult>[]);
-      }
-
-      setValue(BUILD_DIRECTIVES_ERRORS, AnalysisError.NO_ERRORS);
-      setValue(BUILD_LIBRARY_ERRORS, AnalysisError.NO_ERRORS);
-      // CLASS_ELEMENTS
-      setValue(COMPILATION_UNIT_ELEMENT, library.definingCompilationUnit);
-      // CONSTRUCTORS
-      // CONSTRUCTORS_ERRORS
-      entry.setState(CONTENT, CacheState.FLUSHED);
-      setValue(EXPORTED_LIBRARIES, const <Source>[]);
-      // EXPORT_SOURCE_CLOSURE
-      setValue(IMPORTED_LIBRARIES, const <Source>[]);
-      // IMPORT_SOURCE_CLOSURE
-      setValue(INCLUDED_PARTS, const <Source>[]);
-      setValue(IS_LAUNCHABLE, false);
-      setValue(LIBRARY_ELEMENT, library);
-      setValue(LIBRARY_ELEMENT1, library);
-      setValue(LIBRARY_ELEMENT2, library);
-      setValue(LIBRARY_ELEMENT3, library);
-      setValue(LIBRARY_ELEMENT4, library);
-      setValue(LIBRARY_ELEMENT5, library);
-      setValue(LIBRARY_ELEMENT6, library);
-      setValue(LIBRARY_ELEMENT7, library);
-      setValue(LIBRARY_ELEMENT8, library);
-      setValue(LIBRARY_ELEMENT9, library);
-      setValue(LINE_INFO, new LineInfo(<int>[0]));
-      setValue(PARSE_ERRORS, AnalysisError.NO_ERRORS);
-      entry.setState(PARSED_UNIT, CacheState.FLUSHED);
-      entry.setState(RESOLVE_TYPE_NAMES_ERRORS, CacheState.FLUSHED);
-      entry.setState(RESOLVE_TYPE_BOUNDS_ERRORS, CacheState.FLUSHED);
-      setValue(SCAN_ERRORS, AnalysisError.NO_ERRORS);
-      setValue(SOURCE_KIND, SourceKind.LIBRARY);
-      entry.setState(TOKEN_STREAM, CacheState.FLUSHED);
-      setValue(UNITS, <Source>[librarySource]);
-
-      LibrarySpecificUnit unit =
-          new LibrarySpecificUnit(librarySource, librarySource);
-      entry = getCacheEntry(unit);
-      setValue(HINTS, AnalysisError.NO_ERRORS);
-      setValue(LINTS, AnalysisError.NO_ERRORS);
-      setValue(LIBRARY_UNIT_ERRORS, AnalysisError.NO_ERRORS);
-      setValue(RESOLVE_DIRECTIVES_ERRORS, AnalysisError.NO_ERRORS);
-      setValue(RESOLVE_TYPE_NAMES_ERRORS, AnalysisError.NO_ERRORS);
-      setValue(RESOLVE_UNIT_ERRORS, AnalysisError.NO_ERRORS);
-      entry.setState(RESOLVED_UNIT, CacheState.FLUSHED);
-      entry.setState(RESOLVED_UNIT1, CacheState.FLUSHED);
-      entry.setState(RESOLVED_UNIT2, CacheState.FLUSHED);
-      entry.setState(RESOLVED_UNIT3, CacheState.FLUSHED);
-      entry.setState(RESOLVED_UNIT4, CacheState.FLUSHED);
-      entry.setState(RESOLVED_UNIT5, CacheState.FLUSHED);
-      entry.setState(RESOLVED_UNIT6, CacheState.FLUSHED);
-      entry.setState(RESOLVED_UNIT7, CacheState.FLUSHED);
-      entry.setState(RESOLVED_UNIT8, CacheState.FLUSHED);
-      entry.setState(RESOLVED_UNIT9, CacheState.FLUSHED);
-      entry.setState(RESOLVED_UNIT10, CacheState.FLUSHED);
-      entry.setState(RESOLVED_UNIT11, CacheState.FLUSHED);
-      entry.setState(RESOLVED_UNIT12, CacheState.FLUSHED);
-      // USED_IMPORTED_ELEMENTS
-      // USED_LOCAL_ELEMENTS
-      setValue(STRONG_MODE_ERRORS, AnalysisError.NO_ERRORS);
-      setValue(VARIABLE_REFERENCE_ERRORS, AnalysisError.NO_ERRORS);
-      setValue(VERIFY_ERRORS, AnalysisError.NO_ERRORS);
-    });
-
-    CacheEntry entry = getCacheEntry(AnalysisContextTarget.request);
-    entry.setValue(TYPE_PROVIDER, typeProvider, const <TargetedResult>[]);
+    throw UnimplementedError();
   }
 
   @override
   void removeListener(AnalysisListener listener) {
-    _listeners.remove(listener);
+    throw UnimplementedError();
   }
 
   @override
   CompilationUnit resolveCompilationUnit(
       Source unitSource, LibraryElement library) {
-    if (library == null) {
-      return null;
-    }
-    return resolveCompilationUnit2(unitSource, library.source);
+    throw UnimplementedError();
   }
 
   @override
   CompilationUnit resolveCompilationUnit2(
       Source unitSource, Source librarySource) {
-    return computeResult(
-        new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT);
+    throw UnimplementedError();
   }
 
   @override
   void setChangedContents(Source source, String contents, int offset,
       int oldLength, int newLength) {
-    if (_contentRangeChanged(source, contents, offset, oldLength, newLength)) {
-      _onSourcesChangedController.add(new SourcesChangedEvent.changedRange(
-          source, contents, offset, oldLength, newLength));
-    }
+    throw UnimplementedError();
   }
 
   @deprecated
   @override
   void setConfigurationData(ResultDescriptor key, Object data) {
-    _configurationData[key] = data;
+    throw UnimplementedError();
   }
 
   @override
   void setContents(Source source, String contents) {
-    _contentsChanged(source, contents, true);
+    throw UnimplementedError();
   }
 
   @override
   bool shouldErrorsBeAnalyzed(Source source) {
-    CacheEntry entry = analysisCache.get(source);
-    if (source.isInSystemLibrary) {
-      return _options.generateSdkErrors;
-    } else if (!entry.explicitlyAdded) {
-      return _options.generateImplicitErrors;
-    } else {
-      return true;
-    }
+    throw UnimplementedError();
   }
 
   @override
   void test_flushAstStructures(Source source) {
-    CacheEntry entry = getCacheEntry(source);
-    entry.setState(PARSED_UNIT, CacheState.FLUSHED);
-    entry.setState(RESOLVED_UNIT1, CacheState.FLUSHED);
-    entry.setState(RESOLVED_UNIT2, CacheState.FLUSHED);
-    entry.setState(RESOLVED_UNIT3, CacheState.FLUSHED);
-    entry.setState(RESOLVED_UNIT4, CacheState.FLUSHED);
-    entry.setState(RESOLVED_UNIT5, CacheState.FLUSHED);
-    entry.setState(RESOLVED_UNIT6, CacheState.FLUSHED);
-    entry.setState(RESOLVED_UNIT7, CacheState.FLUSHED);
-    entry.setState(RESOLVED_UNIT8, CacheState.FLUSHED);
-    entry.setState(RESOLVED_UNIT9, CacheState.FLUSHED);
-    entry.setState(RESOLVED_UNIT10, CacheState.FLUSHED);
-    entry.setState(RESOLVED_UNIT11, CacheState.FLUSHED);
-    entry.setState(RESOLVED_UNIT12, CacheState.FLUSHED);
-    entry.setState(RESOLVED_UNIT, CacheState.FLUSHED);
+    throw UnimplementedError();
   }
 
   @override
   void visitContentCache(ContentCacheVisitor visitor) {
-    _contentCache.accept(visitor);
-  }
-
-  /**
-   * Add all of the sources contained in the given source [container] to the
-   * given list of [sources].
-   */
-  void _addSourcesInContainer(List<Source> sources, SourceContainer container) {
-    for (Source source in _cache.sources) {
-      if (container.contains(source)) {
-        sources.add(source);
-      }
-    }
-  }
-
-  /**
-   * Remove the given [pendingFuture] from [_pendingFutureTargets], since the
-   * client has indicated its computation is not needed anymore.
-   */
-  void _cancelFuture(PendingFuture pendingFuture) {
-    List<PendingFuture> pendingFutures =
-        _pendingFutureTargets[pendingFuture.target];
-    if (pendingFutures != null) {
-      pendingFutures.remove(pendingFuture);
-      if (pendingFutures.isEmpty) {
-        _pendingFutureTargets.remove(pendingFuture.target);
-      }
-    }
-  }
-
-  /**
-   * Given the encoded form of a source ([encoding]), use the source factory to
-   * reconstitute the original source.
-   */
-  Source _computeSourceFromEncoding(String encoding) =>
-      _sourceFactory.fromEncoding(encoding);
-
-  /**
-   * Return `true` if the given list of [sources] contains the given
-   * [targetSource].
-   */
-  bool _contains(List<Source> sources, Source targetSource) {
-    for (Source source in sources) {
-      if (source == targetSource) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Set the contents of the given [source] to the given [contents] and mark the
-   * source as having changed. The additional [offset], [oldLength] and
-   * [newLength] information is used by the context to determine what reanalysis
-   * is necessary. The method [setChangedContents] triggers a source changed
-   * event where as this method does not.
-   */
-  bool _contentRangeChanged(Source source, String contents, int offset,
-      int oldLength, int newLength) {
-    bool changed = false;
-    String originalContents = _contentCache.setContents(source, contents);
-    if (contents != null) {
-      if (contents != originalContents) {
-        _sourceChanged(source);
-        changed = true;
-        CacheEntry entry = _cache.get(source);
-        if (entry != null) {
-          entry.modificationTime = _contentCache.getModificationStamp(source);
-          entry.setValue(CONTENT, contents, const <TargetedResult>[]);
-        }
-      }
-    } else if (originalContents != null) {
-      _sourceChanged(source);
-      changed = true;
-    }
-    return changed;
-  }
-
-  /**
-   * Set the contents of the given [source] to the given [contents] and mark the
-   * source as having changed. This has the effect of overriding the default
-   * contents of the source. If the contents are `null` the override is removed
-   * so that the default contents will be returned. If [notify] is true, a
-   * source changed event is triggered.
-   */
-  void _contentsChanged(Source source, String contents, bool notify) {
-    String originalContents = _contentCache.setContents(source, contents);
-    handleContentsChanged(source, originalContents, contents, notify);
-  }
-
-  /**
-   * Create a cache entry for the given [source]. The source was explicitly
-   * added to this context if [explicitlyAdded] is `true`. Return the cache
-   * entry that was created.
-   */
-  CacheEntry _createCacheEntry(Source source, bool explicitlyAdded) {
-    CacheEntry entry = new CacheEntry(source);
-    entry.modificationTime = getModificationStamp(source);
-    entry.explicitlyAdded = explicitlyAdded;
-    _cache.put(entry);
-    if (!explicitlyAdded) {
-      _implicitAnalysisEventsController
-          .add(new ImplicitAnalysisEvent(source, true));
-    }
-    return entry;
-  }
-
-  /**
-   * Return a list containing all of the cache entries for targets associated
-   * with the given [source].
-   */
-  List<CacheEntry> _entriesFor(Source source) {
-    List<CacheEntry> entries = <CacheEntry>[];
-    MapIterator<AnalysisTarget, CacheEntry> iterator = _cache.iterator();
-    while (iterator.moveNext()) {
-      if (iterator.key.source == source) {
-        entries.add(iterator.value);
-      }
-    }
-    return entries;
-  }
-
-  void _evaluatePendingFutures() {
-    for (AnalysisTarget target in _pendingFutureTargets.keys) {
-      CacheEntry cacheEntry = _cache.get(target);
-      List<PendingFuture> pendingFutures = _pendingFutureTargets[target];
-      for (int i = 0; i < pendingFutures.length;) {
-        if (cacheEntry == null) {
-          pendingFutures[i].forciblyComplete();
-          pendingFutures.removeAt(i);
-        } else if (pendingFutures[i].evaluate(cacheEntry)) {
-          pendingFutures.removeAt(i);
-        } else {
-          i++;
-        }
-      }
-    }
-  }
-
-  /**
-   * Return a list containing all of the change notices that are waiting to be
-   * returned. If there are no notices, then return either `null` or an empty
-   * list, depending on the value of [nullIfEmpty].
-   */
-  List<ChangeNotice> _getChangeNotices(bool nullIfEmpty) {
-    if (_pendingNotices.isEmpty) {
-      if (nullIfEmpty) {
-        return null;
-      }
-      return const <ChangeNoticeImpl>[];
-    }
-    List<ChangeNotice> notices = new List.from(_pendingNotices.values);
-    _pendingNotices.clear();
-    return notices;
-  }
-
-  /**
-   * Return a list containing all of the sources known to this context that have
-   * the given [kind].
-   */
-  List<Source> _getSources(SourceKind kind) {
-    List<Source> sources = <Source>[];
-    if (kind == SourceKind.LIBRARY || kind == SourceKind.PART) {
-      for (Source source in _cache.sources) {
-        CacheEntry entry = _cache.get(source);
-        if (entry.getValue(SOURCE_KIND) == kind) {
-          sources.add(source);
-        }
-      }
-    }
-    if (sources.isEmpty) {
-      return const <Source>[];
-    }
-    return sources;
-  }
-
-  /**
-   * Look at the given [source] to see whether a task needs to be performed
-   * related to it. If so, add the source to the set of sources that need to be
-   * processed. This method is intended to be used for testing purposes only.
-   */
-  void _getSourcesNeedingProcessing(
-      Source source,
-      CacheEntry entry,
-      bool isPriority,
-      bool hintsEnabled,
-      bool lintsEnabled,
-      HashSet<Source> sources) {
-    CacheState state = entry.getState(CONTENT);
-    if (state == CacheState.INVALID ||
-        (isPriority && state == CacheState.FLUSHED)) {
-      sources.add(source);
-      return;
-    } else if (state == CacheState.ERROR) {
-      return;
-    }
-    state = entry.getState(SOURCE_KIND);
-    if (state == CacheState.INVALID ||
-        (isPriority && state == CacheState.FLUSHED)) {
-      sources.add(source);
-      return;
-    } else if (state == CacheState.ERROR) {
-      return;
-    }
-    SourceKind kind = entry.getValue(SOURCE_KIND);
-    if (kind == SourceKind.LIBRARY || kind == SourceKind.PART) {
-      state = entry.getState(SCAN_ERRORS);
-      if (state == CacheState.INVALID ||
-          (isPriority && state == CacheState.FLUSHED)) {
-        sources.add(source);
-        return;
-      } else if (state == CacheState.ERROR) {
-        return;
-      }
-      state = entry.getState(PARSE_ERRORS);
-      if (state == CacheState.INVALID ||
-          (isPriority && state == CacheState.FLUSHED)) {
-        sources.add(source);
-        return;
-      } else if (state == CacheState.ERROR) {
-        return;
-      }
-//      if (isPriority) {
-//        if (!entry.hasResolvableCompilationUnit) {
-//          sources.add(source);
-//          return;
-//        }
-//      }
-      for (Source librarySource in getLibrariesContaining(source)) {
-        CacheEntry libraryEntry = _cache.get(librarySource);
-        state = libraryEntry.getState(LIBRARY_ELEMENT);
-        if (state == CacheState.INVALID ||
-            (isPriority && state == CacheState.FLUSHED)) {
-          sources.add(source);
-          return;
-        } else if (state == CacheState.ERROR) {
-          return;
-        }
-        CacheEntry unitEntry =
-            _cache.get(new LibrarySpecificUnit(librarySource, source));
-        state = unitEntry.getState(RESOLVED_UNIT);
-        if (state == CacheState.INVALID ||
-            (isPriority && state == CacheState.FLUSHED)) {
-          sources.add(source);
-          return;
-        } else if (state == CacheState.ERROR) {
-          return;
-        }
-        if (shouldErrorsBeAnalyzed(source)) {
-          state = unitEntry.getState(VERIFY_ERRORS);
-          if (state == CacheState.INVALID ||
-              (isPriority && state == CacheState.FLUSHED)) {
-            sources.add(source);
-            return;
-          } else if (state == CacheState.ERROR) {
-            return;
-          }
-          if (hintsEnabled) {
-            state = unitEntry.getState(HINTS);
-            if (state == CacheState.INVALID ||
-                (isPriority && state == CacheState.FLUSHED)) {
-              sources.add(source);
-              return;
-            } else if (state == CacheState.ERROR) {
-              return;
-            }
-          }
-          if (lintsEnabled) {
-            state = unitEntry.getState(LINTS);
-            if (state == CacheState.INVALID ||
-                (isPriority && state == CacheState.FLUSHED)) {
-              sources.add(source);
-              return;
-            } else if (state == CacheState.ERROR) {
-              return;
-            }
-          }
-        }
-      }
-//    } else if (kind == SourceKind.HTML) {
-//      CacheState parsedUnitState = entry.getState(HtmlEntry.PARSED_UNIT);
-//      if (parsedUnitState == CacheState.INVALID ||
-//          (isPriority && parsedUnitState == CacheState.FLUSHED)) {
-//        sources.add(source);
-//        return;
-//      }
-//      CacheState resolvedUnitState =
-//          entry.getState(HtmlEntry.RESOLVED_UNIT);
-//      if (resolvedUnitState == CacheState.INVALID ||
-//          (isPriority && resolvedUnitState == CacheState.FLUSHED)) {
-//        sources.add(source);
-//        return;
-//      }
-    }
-  }
-
-  /**
-   * Log the given debugging [message].
-   */
-  void _logInformation(String message) {
-    AnalysisEngine.instance.logger.logInformation(message);
-  }
-
-  /**
-   * Notify all of the analysis listeners that the errors associated with the
-   * given [source] has been updated to the given [errors].
-   */
-  void _notifyErrors(
-      Source source, List<AnalysisError> errors, LineInfo lineInfo) {
-    int count = _listeners.length;
-    for (int i = 0; i < count; i++) {
-      _listeners[i].computedErrors(this, source, errors, lineInfo);
-    }
-  }
-
-  bool _referencesDartHtml(Source librarySource) {
-    Source htmlSource = sourceFactory.forUri(DartSdk.DART_HTML);
-    Set<Source> checkedSources = new Set<Source>();
-    bool _refHtml(Source source) {
-      if (!checkedSources.add(source)) {
-        return false;
-      }
-      if (source == htmlSource) {
-        return true;
-      }
-      LibraryElement library = _cache.getValue(source, LIBRARY_ELEMENT);
-      if (library != null) {
-        return library.importedLibraries.any((x) => _refHtml(x.source)) ||
-            library.exportedLibraries.any((x) => _refHtml(x.source));
-      }
-      return false;
-    }
-
-    return _refHtml(librarySource);
-  }
-
-  void _removeFromCache(Source source) {
-    CacheEntry entry = _cache.remove(source);
-    if (entry != null && !entry.explicitlyAdded) {
-      _implicitAnalysisEventsController
-          .add(new ImplicitAnalysisEvent(source, false));
-    }
-  }
-
-  /**
-   * Remove the given [source] from the priority order if it is in the list.
-   */
-  void _removeFromPriorityOrder(Source source) {
-    int count = _priorityOrder.length;
-    List<Source> newOrder = <Source>[];
-    for (int i = 0; i < count; i++) {
-      if (_priorityOrder[i] != source) {
-        newOrder.add(_priorityOrder[i]);
-      }
-    }
-    if (newOrder.length < count) {
-      analysisPriorityOrder = newOrder;
-    }
-  }
-
-  /**
-   * Create an entry for the newly added [source] and invalidate any sources
-   * that referenced the source before it existed.
-   */
-  void _sourceAvailable(Source source) {
-    driver.reset();
-    // TODO(brianwilkerson) This method needs to check whether the source was
-    // previously being implicitly analyzed. If so, the cache entry needs to be
-    // update to reflect the new status and an event needs to be generated to
-    // inform clients that it is no longer being implicitly analyzed.
-    CacheEntry entry = _cache.get(source);
-    if (entry == null) {
-      _createCacheEntry(source, true);
-    } else {
-      entry.explicitlyAdded = true;
-      entry.modificationTime = getModificationStamp(source);
-      entry.setState(CONTENT, CacheState.INVALID);
-      entry.setState(MODIFICATION_TIME, CacheState.INVALID);
-    }
-  }
-
-  /**
-   * Invalidate the [source] that was changed and any sources that referenced
-   * the source before it existed.
-   *
-   * Note: source may be considered "changed" if it was previously missing,
-   * but pointed to by an import or export directive.
-   */
-  void _sourceChanged(Source source, {bool compareWithOld: true}) {
-    CacheEntry entry = _cache.get(source);
-    // If the source has no cache entry, there is nothing to invalidate.
-    if (entry == null) {
-      return;
-    }
-
-    String oldContents = compareWithOld ? entry.getValue(CONTENT) : null;
-
-    // Flush so that from now on we will get new contents.
-    // (For example, in getLibrariesContaining.)
-    entry.setState(CONTENT, CacheState.FLUSHED);
-
-    // Prepare the new contents.
-    TimestampedData<String> fileContents;
-    try {
-      fileContents = getContents(source);
-    } catch (e) {}
-
-    // Update 'modificationTime' - we are going to update the entry.
-    {
-      int time = fileContents?.modificationTime ?? -1;
-      for (CacheEntry entry in _entriesFor(source)) {
-        entry.modificationTime = time;
-      }
-    }
-
-    // Fast path if the contents is the same as it was last time.
-    if (oldContents != null && fileContents?.data == oldContents) {
-      return;
-    }
-
-    // We're going to update the cache, so reset the driver.
-    driver.reset();
-
-    // We need to invalidate the cache.
-    {
-      entry.setState(CONTENT, CacheState.INVALID);
-      entry.setState(MODIFICATION_TIME, CacheState.INVALID);
-      entry.setState(SOURCE_KIND, CacheState.INVALID);
-    }
-    for (WorkManager workManager in workManagers) {
-      workManager
-          .applyChange(const <Source>[], <Source>[source], const <Source>[]);
-    }
-  }
-
-  /**
-   * Record that the given [source] has been removed.
-   */
-  void _sourceRemoved(Source source) {
-    driver.reset();
-    _removeFromCache(source);
-    _removeFromPriorityOrder(source);
-  }
-}
-
-/**
- * A helper class used to create futures for [AnalysisContextImpl].
- * Using a helper class allows us to preserve the generic parameter T.
- */
-class AnalysisFutureHelper<T> {
-  final AnalysisContextImpl _context;
-  final AnalysisTarget _target;
-  final ResultDescriptor<T> _descriptor;
-
-  AnalysisFutureHelper(this._context, this._target, this._descriptor);
-
-  /**
-   * Return a future that will be completed with the result specified
-   * in the constructor. If the result is cached, the future will be
-   * completed immediately with the resulting value. If not, then
-   * analysis is scheduled that will produce the required result.
-   * If the result cannot be generated, then the future will be completed with
-   * the error AnalysisNotScheduledError.
-   */
-  CancelableFuture<T> computeAsync() {
-    if (_context.isDisposed) {
-      // No further analysis is expected, so return a future that completes
-      // immediately with AnalysisNotScheduledError.
-      return new CancelableFuture.error(new AnalysisNotScheduledError());
-    }
-    CacheEntry entry = _context.getCacheEntry(_target);
-    PendingFuture<T> pendingFuture =
-        new PendingFuture<T>(_context, _target, (CacheEntry entry) {
-      CacheState state = entry.getState(_descriptor);
-      if (state == CacheState.ERROR) {
-        throw entry.exception;
-      } else if (state == CacheState.INVALID) {
-        return null;
-      }
-      return entry.getValue(_descriptor);
-    });
-    if (!pendingFuture.evaluate(entry)) {
-      _context._pendingFutureTargets
-          .putIfAbsent(_target, () => <PendingFuture>[])
-          .add(pendingFuture);
-      _context.dartWorkManager.addPriorityResult(_target, _descriptor);
-    }
-    return pendingFuture.future;
-  }
-}
-
-class CacheConsistencyValidatorImpl implements CacheConsistencyValidator {
-  final AnalysisContextImpl context;
-
-  CacheConsistencyValidatorImpl(this.context);
-
-  @override
-  List<Source> getSourcesToComputeModificationTimes() {
-    return context._privatePartition.sources.toList();
-  }
-
-  @override
-  bool sourceModificationTimesComputed(List<Source> sources, List<int> times) {
-    Stopwatch timer = new Stopwatch()..start();
-    HashSet<Source> changedSources = new HashSet<Source>();
-    HashSet<Source> removedSources = new HashSet<Source>();
-    for (int i = 0; i < sources.length; i++) {
-      Source source = sources[i];
-      // When a source is in the content cache,
-      // its modification time in the file system does not matter.
-      if (context._contentCache.getModificationStamp(source) != null) {
-        continue;
-      }
-      // When we were not able to compute the modification time in the
-      // file system, there is nothing to compare with, so skip the source.
-      int sourceTime = times[i];
-      if (sourceTime == null) {
-        continue;
-      }
-      // Compare with the modification time in the cache entry.
-      CacheEntry entry = context._privatePartition.get(source);
-      if (entry != null) {
-        if (entry.modificationTime != sourceTime) {
-          if (sourceTime == -1) {
-            removedSources.add(source);
-            PerformanceStatistics
-                .cacheConsistencyValidationStatistics.numOfRemoved++;
-          } else {
-            changedSources.add(source);
-            PerformanceStatistics
-                .cacheConsistencyValidationStatistics.numOfChanged++;
-          }
-        }
-      }
-    }
-    for (Source source in changedSources) {
-      context._sourceChanged(source);
-    }
-    for (Source source in removedSources) {
-      context._sourceRemoved(source);
-    }
-    if (changedSources.length > 0 || removedSources.length > 0) {
-      StringBuffer buffer = new StringBuffer();
-      buffer.write("Consistency check took ");
-      buffer.write(timer.elapsedMilliseconds);
-      buffer.writeln(" ms and found");
-      buffer.write("  ");
-      buffer.write(changedSources.length);
-      buffer.writeln(" changed sources");
-      buffer.write("  ");
-      buffer.write(removedSources.length);
-      buffer.write(" removed sources.");
-      context._logInformation(buffer.toString());
-    }
-    return changedSources.isNotEmpty || removedSources.isNotEmpty;
+    throw UnimplementedError();
   }
 }
 
@@ -1801,117 +579,16 @@
  */
 class PartitionManager {
   /**
-   * A table mapping SDK's to the partitions used for those SDK's.
-   */
-  Map<DartSdk, SdkCachePartition> _sdkPartitions =
-      new HashMap<DartSdk, SdkCachePartition>();
-
-  /**
    * Clear any cached data being maintained by this manager.
    */
-  void clearCache() {
-    _sdkPartitions.clear();
-  }
+  void clearCache() {}
 
   /**
    * Return the partition being used for the given [sdk], creating the partition
    * if necessary.
    */
   SdkCachePartition forSdk(DartSdk sdk) {
-    // Call sdk.context now, because when it creates a new
-    // InternalAnalysisContext instance, it calls forSdk() again, so creates an
-    // SdkCachePartition instance.
-    // So, if we initialize context after "partition == null", we end up
-    // with two SdkCachePartition instances.
-    InternalAnalysisContext sdkContext = sdk.context;
-    // Check cache for an existing partition.
-    SdkCachePartition partition = _sdkPartitions[sdk];
-    if (partition == null) {
-      partition = new SdkCachePartition(sdkContext);
-      _sdkPartitions[sdk] = partition;
-    }
-    return partition;
-  }
-}
-
-/**
- * Representation of a pending computation which is based on the results of
- * analysis that may or may not have been completed.
- */
-class PendingFuture<T> {
-  /**
-   * The context in which this computation runs.
-   */
-  final AnalysisContextImpl _context;
-
-  /**
-   * The target used by this computation to compute its value.
-   */
-  final AnalysisTarget target;
-
-  /**
-   * The function which implements the computation.
-   */
-  final PendingFutureComputer<T> _computeValue;
-
-  /**
-   * The completer that should be completed once the computation has succeeded.
-   */
-  CancelableCompleter<T> _completer;
-
-  PendingFuture(this._context, this.target, this._computeValue) {
-    _completer = new CancelableCompleter<T>(_onCancel);
-  }
-
-  /**
-   * Retrieve the future which will be completed when this object is
-   * successfully evaluated.
-   */
-  CancelableFuture<T> get future => _completer.future;
-
-  /**
-   * Execute [_computeValue], passing it the given [entry], and complete
-   * the pending future if it's appropriate to do so.  If the pending future is
-   * completed by this call, true is returned; otherwise false is returned.
-   *
-   * Once this function has returned true, it should not be called again.
-   *
-   * Other than completing the future, this method is free of side effects.
-   * Note that any code the client has attached to the future will be executed
-   * in a microtask, so there is no danger of side effects occurring due to
-   * client callbacks.
-   */
-  bool evaluate(CacheEntry entry) {
-    assert(!_completer.isCompleted);
-    try {
-      T result = _computeValue(entry);
-      if (result == null) {
-        return false;
-      } else {
-        _completer.complete(result);
-        return true;
-      }
-    } catch (exception, stackTrace) {
-      _completer.completeError(exception, stackTrace);
-      return true;
-    }
-  }
-
-  /**
-   * No further analysis updates are expected which affect this future, so
-   * complete it with an AnalysisNotScheduledError in order to avoid
-   * deadlocking the client.
-   */
-  void forciblyComplete() {
-    try {
-      throw new AnalysisNotScheduledError();
-    } catch (exception, stackTrace) {
-      _completer.completeError(exception, stackTrace);
-    }
-  }
-
-  void _onCancel() {
-    _context._cancelFuture(this);
+    throw UnimplementedError();
   }
 }
 
@@ -1955,15 +632,6 @@
 
   @override
   AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
-    if (factory == null) {
-      return super.createCacheFromSourceFactory(factory);
-    }
-    DartSdk sdk = factory.dartSdk;
-    if (sdk == null) {
-      throw new ArgumentError(
-          "The source factory for an SDK analysis context must have a DartUriResolver");
-    }
-    return new AnalysisCache(
-        <CachePartition>[AnalysisEngine.instance.partitionManager.forSdk(sdk)]);
+    throw UnimplementedError();
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 418b2ff..7a4b3d0 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2017, 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.
 
@@ -14,6 +14,7 @@
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/constant/compute.dart';
 import 'package:analyzer/src/dart/constant/constant_verifier.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/constant/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/handle.dart';
@@ -27,10 +28,10 @@
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/hint/sdk_constraint_verifier.dart';
+import 'package:analyzer/src/ignore_comments/ignore_info.dart';
 import 'package:analyzer/src/lint/linter.dart';
 import 'package:analyzer/src/lint/linter_visitor.dart';
 import 'package:analyzer/src/services/lint.dart';
-import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/src/task/strong/checker.dart';
 import 'package:pub_semver/pub_semver.dart';
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index 44f61a4..2b3f303 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -6,7 +6,6 @@
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/element/element.dart'
     show CompilationUnitElement, LibraryElement;
-import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
@@ -43,7 +42,7 @@
   /// We use it as an approximation for the heap size of elements.
   int _linkedDataInBytes = 0;
 
-  AnalysisContextImpl analysisContext;
+  RestrictedAnalysisContext analysisContext;
   SummaryResynthesizer resynthesizer;
   InheritanceManager2 inheritanceManager;
 
@@ -63,18 +62,19 @@
       store.addStore(externalSummaries);
     }
 
-    // Fill the store with summaries required for the initial library.
-    load(targetLibrary);
-
     analysisContext = new RestrictedAnalysisContext(
       analysisOptions,
       declaredVariables,
       sourceFactory,
     );
 
-    var provider = new InputPackagesResultProvider(analysisContext, store,
-        session: session);
-    resynthesizer = provider.resynthesizer;
+    // Fill the store with summaries required for the initial library.
+    load(targetLibrary);
+
+    resynthesizer = new StoreBasedSummaryResynthesizer(
+        analysisContext, session, sourceFactory, true, store);
+    analysisContext.typeProvider = resynthesizer.typeProvider;
+    resynthesizer.finishCoreAsyncLibraries();
 
     inheritanceManager = new InheritanceManager2(analysisContext.typeSystem);
   }
@@ -173,7 +173,7 @@
       }, (String uri) {
         UnlinkedUnit unlinkedUnit = store.unlinkedMap[uri];
         return unlinkedUnit;
-      }, (_) => null);
+      }, DeclaredVariables(), analysisContext.analysisOptions);
       logger.writeln('Linked ${linkedLibraries.length} libraries.');
     });
 
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 5144eeb..8dfa18b 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -3042,6 +3042,9 @@
   }
 
   @override
+  ParameterElement get declaredElement => _parameter.declaredElement;
+
+  @override
   Token get beginToken => _parameter.beginToken;
 
   @override
@@ -8990,6 +8993,19 @@
   /// whether the kind has not or cannot be determined.
   _SetOrMapKind _resolvedKind;
 
+  /// The context type computed by
+  /// [ResolverVisitor._computeSetOrMapContextType].
+  ///
+  /// Note that this is not the same as the context pushed down by type
+  /// inference (which can be obtained via [InferenceContext.getContext]).  For
+  /// example, in the following code:
+  ///
+  ///     var m = {};
+  ///
+  /// The context pushed down by type inference is null, whereas the
+  /// `contextType` is `Map<dynamic, dynamic>`.
+  InterfaceType contextType;
+
   /// Initialize a newly created set or map literal. The [constKeyword] can be
   /// `null` if the literal is not a constant. The [typeArguments] can be `null`
   /// if no type arguments were declared. The [elements] can be `null` if the
diff --git a/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart b/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart
index b6b9169..a919a7f 100644
--- a/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart
+++ b/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart
@@ -344,29 +344,26 @@
 
   @override
   Object visitSetOrMapLiteral(SetOrMapLiteral node) {
-    if (node.isMap) {
-      Map<String, Object> map = new HashMap<String, Object>();
-      for (CollectionElement element in node.elements2) {
-        if (element is MapLiteralEntry) {
-          Object key = element.key.accept(this);
-          Object value = element.value.accept(this);
-          if (key is String && !identical(value, NOT_A_CONSTANT)) {
-            map[key] = value;
-          } else {
-            return NOT_A_CONSTANT;
-          }
+    // There are a lot of constants that this class does not support, so we
+    // didn't add support for set literals. As a result, this assumes that we're
+    // looking at a map literal until we prove otherwise.
+    Map<String, Object> map = new HashMap<String, Object>();
+    for (CollectionElement element in node.elements2) {
+      if (element is MapLiteralEntry) {
+        Object key = element.key.accept(this);
+        Object value = element.value.accept(this);
+        if (key is String && !identical(value, NOT_A_CONSTANT)) {
+          map[key] = value;
         } else {
-          // There are a lot of constants that this class does not support, so
-          // we didn't add support for the extended collection support.
           return NOT_A_CONSTANT;
         }
+      } else {
+        // There are a lot of constants that this class does not support, so
+        // we didn't add support for the extended collection support.
+        return NOT_A_CONSTANT;
       }
-      return map;
-    } else if (node.isSet) {
-      // There are a lot of constants that this class does not support, so
-      // we didn't add support for set literals.
     }
-    return NOT_A_CONSTANT;
+    return map;
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 9588569..cb913fe 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -903,13 +903,20 @@
   }
 
   @override
-  SetOrMapLiteral visitSetOrMapLiteral(SetOrMapLiteral node) =>
-      astFactory.setOrMapLiteral(
-          constKeyword: cloneToken(node.constKeyword),
-          typeArguments: cloneNode(node.typeArguments),
-          leftBracket: cloneToken(node.leftBracket),
-          elements: cloneNodeList(node.elements2),
-          rightBracket: cloneToken(node.rightBracket));
+  SetOrMapLiteral visitSetOrMapLiteral(SetOrMapLiteral node) {
+    var result = astFactory.setOrMapLiteral(
+        constKeyword: cloneToken(node.constKeyword),
+        typeArguments: cloneNode(node.typeArguments),
+        leftBracket: cloneToken(node.leftBracket),
+        elements: cloneNodeList(node.elements2),
+        rightBracket: cloneToken(node.rightBracket));
+    if (node.isMap) {
+      (result as SetOrMapLiteralImpl).becomeMap();
+    } else if (node.isSet) {
+      (result as SetOrMapLiteralImpl).becomeSet();
+    }
+    return result;
+  }
 
   @override
   ShowCombinator visitShowCombinator(ShowCombinator node) => astFactory
diff --git a/pkg/analyzer/lib/src/dart/constant/compute.dart b/pkg/analyzer/lib/src/dart/constant/compute.dart
index 4031e2f..712d4b6 100644
--- a/pkg/analyzer/lib/src/dart/constant/compute.dart
+++ b/pkg/analyzer/lib/src/dart/constant/compute.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
@@ -10,7 +10,6 @@
     show TypeProvider, TypeSystem;
 import 'package:analyzer/src/summary/link.dart' as graph
     show DependencyWalker, Node;
-import 'package:analyzer/src/task/dart.dart';
 
 /// Compute values of the given [constants] with correct ordering.
 void computeConstants(
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index 3373f64..a8459c1 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -2,10 +2,9 @@
 // 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';
-
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -14,6 +13,7 @@
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/constant/evaluation.dart';
+import 'package:analyzer/src/dart/constant/potentially_constant.dart';
 import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/error/codes.dart';
@@ -143,20 +143,17 @@
   void visitListLiteral(ListLiteral node) {
     super.visitListLiteral(node);
     if (node.isConst) {
-      // Dummy sets of keys to accommodate the fact that
-      // `_validateCollectionElement` handles map literals.
-      HashSet<DartObject> keys = new HashSet<DartObject>();
-      List<Expression> invalidKeys = new List<Expression>();
+      InterfaceType nodeType = node.staticType;
+      DartType elementType = nodeType.typeArguments[0];
+      var verifier = _ConstLiteralVerifier(
+        this,
+        isConst: true,
+        errorCode: CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT,
+        forList: true,
+        listElementType: elementType,
+      );
       for (CollectionElement element in node.elements2) {
-        bool isValid = _validateCollectionElement(element, true, keys,
-            invalidKeys, CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT);
-        if (isValid && element is Expression) {
-          // TODO(brianwilkerson) Handle the other kinds of elements.
-          _reportErrorIfFromDeferredLibrary(
-              element,
-              CompileTimeErrorCode
-                  .NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY);
-        }
+        verifier.verify(element);
       }
     }
   }
@@ -171,69 +168,55 @@
   void visitSetOrMapLiteral(SetOrMapLiteral node) {
     super.visitSetOrMapLiteral(node);
     bool isConst = node.isConst;
-    HashSet<DartObject> keys = new HashSet<DartObject>();
-    List<Expression> invalidKeys = new List<Expression>();
     if (node.isSet) {
-      HashSet<DartObject> elements = new HashSet<DartObject>();
-      List<Expression> invalidElements = new List<Expression>();
       if (isConst) {
+        InterfaceType nodeType = node.staticType;
+        var elementType = nodeType.typeArguments[0];
+        var duplicateElements = <Expression>[];
+        var verifier = _ConstLiteralVerifier(
+          this,
+          isConst: isConst,
+          errorCode: CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT,
+          forSet: true,
+          setElementType: elementType,
+          setUniqueValues: Set<DartObject>(),
+          setDuplicateElements: duplicateElements,
+        );
         for (CollectionElement element in node.elements2) {
-          if (element is Expression) {
-            // TODO(mfairhurst): unify this with _validateCollectionElemet
-            DartObject result = _validate(
-                element, CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT);
-            if (result != null) {
-              _reportErrorIfFromDeferredLibrary(
-                  element,
-                  CompileTimeErrorCode
-                      .NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY);
-              if (!elements.add(result)) {
-                invalidElements.add(element);
-              }
-              DartType type = result.type;
-              if (_implementsEqualsWhenNotAllowed(type)) {
-                _errorReporter.reportErrorForNode(
-                    CompileTimeErrorCode
-                        .CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
-                    element,
-                    [type.displayName]);
-              }
-            }
-          } else {
-            bool isValid = _validateCollectionElement(element, isConst, keys,
-                invalidKeys, CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT);
-            if (isValid) {
-              // TODO(mfairhurst) report deferred library error
-            }
-          }
+          verifier.verify(element);
         }
-        for (var invalidElement in invalidElements) {
+        for (var duplicateElement in duplicateElements) {
           _errorReporter.reportErrorForNode(
-              StaticWarningCode.EQUAL_VALUES_IN_CONST_SET, invalidElement);
+            StaticWarningCode.EQUAL_VALUES_IN_CONST_SET,
+            duplicateElement,
+          );
         }
       }
     } else if (node.isMap) {
+      InterfaceType nodeType = node.staticType;
+      var keyType = nodeType.typeArguments[0];
+      var valueType = nodeType.typeArguments[1];
       bool reportEqualKeys = true;
+      var duplicateKeyElements = <Expression>[];
+      var verifier = _ConstLiteralVerifier(
+        this,
+        isConst: isConst,
+        errorCode: CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT,
+        forMap: true,
+        mapKeyType: keyType,
+        mapValueType: valueType,
+        mapUniqueKeys: Set<DartObject>(),
+        mapDuplicateKeyElements: duplicateKeyElements,
+      );
       for (CollectionElement entry in node.elements2) {
-        if (entry is MapLiteralEntry) {
-          // TODO(mfairhurst): Change non-const error to a hint, and report
-          // duplicates in constant evaluator instead.
-          // TODO(mfairhurst): unify this with _validateCollectionElemet
-          if (!_validateMapLiteralEntry(entry, isConst, keys, invalidKeys)) {
-            reportEqualKeys = false;
-          }
-        } else {
-          bool isValid = _validateCollectionElement(entry, isConst, keys,
-              invalidKeys, CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT);
-          if (isValid) {
-            // TODO(mfarihurst): handle deferred library checks
-          }
-        }
+        verifier.verify(entry);
       }
       if (reportEqualKeys) {
-        for (int i = 0; i < invalidKeys.length; i++) {
+        for (var duplicateKeyElement in duplicateKeyElements) {
           _errorReporter.reportErrorForNode(
-              StaticWarningCode.EQUAL_KEYS_IN_MAP, invalidKeys[i]);
+            StaticWarningCode.EQUAL_KEYS_IN_MAP,
+            duplicateKeyElement,
+          );
         }
       }
     }
@@ -452,38 +435,6 @@
     return result;
   }
 
-  bool _validateCollectionElement(
-      CollectionElement element,
-      bool isConst,
-      HashSet<DartObject> keys,
-      List<Expression> invalidKeys,
-      ErrorCode errorCode) {
-    if (element is Expression) {
-      return !isConst || _validate(element, errorCode) != null;
-    } else if (element is ForElement) {
-      if (isConst) {
-        _errorReporter.reportErrorForNode(errorCode, element);
-        return false;
-      }
-      return true;
-    } else if (element is IfElement) {
-      bool validCondition =
-          !isConst || _validate(element.condition, errorCode) != null;
-      return validCondition &&
-          _validateCollectionElement(
-                  element.thenElement, isConst, keys, invalidKeys, errorCode) !=
-              null &&
-          _validateCollectionElement(
-                  element.elseElement, isConst, keys, invalidKeys, errorCode) !=
-              null;
-    } else if (element is MapLiteralEntry) {
-      return _validateMapLiteralEntry(element, isConst, keys, invalidKeys);
-    } else if (element is SpreadElement) {
-      return !isConst || _validate(element.expression, errorCode) != null;
-    }
-    return null;
-  }
-
   /// Validate that if the passed arguments are constant expressions.
   ///
   /// @param argumentList the argument list to evaluate
@@ -632,52 +583,6 @@
       _validateInitializerExpression(parameterElements, argument);
     }
   }
-
-  bool _validateMapLiteralEntry(MapLiteralEntry entry, bool isConst,
-      HashSet<DartObject> keys, List<Expression> invalidKeys) {
-    Expression key = entry.key;
-    if (isConst) {
-      DartObjectImpl keyResult =
-          _validate(key, CompileTimeErrorCode.NON_CONSTANT_MAP_KEY);
-      Expression valueExpression = entry.value;
-      DartObjectImpl valueResult = _validate(
-          valueExpression, CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE);
-      if (valueResult != null) {
-        _reportErrorIfFromDeferredLibrary(valueExpression,
-            CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY);
-      }
-      if (keyResult != null) {
-        _reportErrorIfFromDeferredLibrary(key,
-            CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY);
-        if (!keys.add(keyResult)) {
-          invalidKeys.add(key);
-        }
-        DartType type = keyResult.type;
-        if (_implementsEqualsWhenNotAllowed(type)) {
-          _errorReporter.reportErrorForNode(
-              CompileTimeErrorCode
-                  .CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
-              key,
-              [type.displayName]);
-        }
-      }
-    } else {
-      // Note: we throw the errors away because this isn't actually a const.
-      AnalysisErrorListener errorListener = AnalysisErrorListener.NULL_LISTENER;
-      ErrorReporter subErrorReporter =
-          new ErrorReporter(errorListener, _errorReporter.source);
-      DartObjectImpl result =
-          key.accept(new ConstantVisitor(_evaluationEngine, subErrorReporter));
-      if (result != null) {
-        if (!keys.add(result)) {
-          invalidKeys.add(key);
-        }
-      } else {
-        return false;
-      }
-    }
-    return true;
-  }
 }
 
 class _ConstantVerifier_validateInitializerExpression extends ConstantVisitor {
@@ -739,3 +644,327 @@
     return super.visitSimpleIdentifier(node);
   }
 }
+
+class _ConstLiteralVerifier {
+  final ConstantVerifier verifier;
+  final bool isConst;
+  final Set<DartObject> mapUniqueKeys;
+  final List<Expression> mapDuplicateKeyElements;
+  final ErrorCode errorCode;
+  final DartType listElementType;
+  final DartType mapKeyType;
+  final DartType mapValueType;
+  final DartType setElementType;
+  final Set<DartObject> setUniqueValues;
+  final List<CollectionElement> setDuplicateElements;
+  final bool forList;
+  final bool forMap;
+  final bool forSet;
+
+  _ConstLiteralVerifier(
+    this.verifier, {
+    this.isConst,
+    this.mapUniqueKeys,
+    this.mapDuplicateKeyElements,
+    this.errorCode,
+    this.listElementType,
+    this.mapKeyType,
+    this.mapValueType,
+    this.setElementType,
+    this.setUniqueValues,
+    this.setDuplicateElements,
+    this.forList = false,
+    this.forMap = false,
+    this.forSet = false,
+  });
+
+  bool verify(CollectionElement element) {
+    if (element is Expression) {
+      if (!isConst) return true;
+
+      var value = verifier._validate(element, errorCode);
+      if (value == null) return false;
+
+      if (forList) {
+        return _validateListExpression(element, value);
+      }
+
+      if (forSet) {
+        return _validateSetExpression(element, value);
+      }
+
+      return true;
+    } else if (element is ForElement) {
+      if (!isConst) return true;
+
+      verifier._errorReporter.reportErrorForNode(errorCode, element);
+      return false;
+    } else if (element is IfElement) {
+      if (!isConst) return true;
+
+      var conditionValue = verifier._validate(element.condition, errorCode);
+      var conditionBool = conditionValue?.toBoolValue();
+
+      // The errors have already been reported.
+      if (conditionBool == null) return false;
+
+      var thenValid = true;
+      var elseValid = true;
+      if (conditionBool) {
+        thenValid = verify(element.thenElement);
+        if (element.elseElement != null) {
+          elseValid = _reportNotPotentialConstants(element.elseElement);
+        }
+      } else {
+        thenValid = _reportNotPotentialConstants(element.thenElement);
+        if (element.elseElement != null) {
+          elseValid = verify(element.elseElement);
+        }
+      }
+
+      return thenValid && elseValid;
+    } else if (element is MapLiteralEntry) {
+      return _validateMapLiteralEntry(element);
+    } else if (element is SpreadElement) {
+      if (!isConst) return true;
+
+      var value = verifier._validate(element.expression, errorCode);
+      if (value == null) return false;
+
+      if (forList || forSet) {
+        return _validateListOrSetSpread(element, value);
+      }
+
+      if (forMap) {
+        return _validateMapSpread(element, value);
+      }
+
+      return true;
+    }
+    throw new UnsupportedError(
+      'Unhandled type of collection element: ${element.runtimeType}',
+    );
+  }
+
+  /// Return `true` if the [node] is a potential constant.
+  bool _reportNotPotentialConstants(AstNode node) {
+    var notPotentiallyConstants = getNotPotentiallyConstants(node);
+    if (notPotentiallyConstants.isEmpty) return true;
+
+    for (var notConst in notPotentiallyConstants) {
+      CompileTimeErrorCode errorCode;
+      if (forList) {
+        errorCode = CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT;
+      } else if (forMap) {
+        errorCode = CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT;
+        for (var parent = notConst; parent != null; parent = parent.parent) {
+          if (parent is MapLiteralEntry) {
+            if (parent.key == notConst) {
+              errorCode = CompileTimeErrorCode.NON_CONSTANT_MAP_KEY;
+            } else {
+              errorCode = CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE;
+            }
+            break;
+          }
+        }
+      } else if (forSet) {
+        errorCode = CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT;
+      }
+      verifier._errorReporter.reportErrorForNode(errorCode, notConst);
+    }
+
+    return false;
+  }
+
+  bool _validateListExpression(Expression expression, DartObjectImpl value) {
+    if (!verifier._evaluationEngine.runtimeTypeMatch(value, listElementType)) {
+      verifier._errorReporter.reportErrorForNode(
+        StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE,
+        expression,
+        [value.type, listElementType],
+      );
+      return false;
+    }
+
+    verifier._reportErrorIfFromDeferredLibrary(
+      expression,
+      CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY,
+    );
+
+    return true;
+  }
+
+  bool _validateListOrSetSpread(SpreadElement element, DartObjectImpl value) {
+    var listValue = value.toListValue();
+    var setValue = value.toSetValue();
+
+    if (listValue == null && setValue == null) {
+      if (value.isNull && _isNullableSpread(element)) {
+        return true;
+      }
+      verifier._errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
+        element.expression,
+      );
+      return false;
+    }
+
+    if (listValue != null) {
+      var elementType = value.type.typeArguments[0];
+      if (verifier._implementsEqualsWhenNotAllowed(elementType)) {
+        verifier._errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
+          element,
+          [elementType],
+        );
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  bool _validateMapLiteralEntry(MapLiteralEntry entry) {
+    if (!forMap) return false;
+
+    var keyExpression = entry.key;
+    var valueExpression = entry.value;
+
+    if (isConst) {
+      var keyValue = verifier._validate(
+        keyExpression,
+        CompileTimeErrorCode.NON_CONSTANT_MAP_KEY,
+      );
+      var valueValue = verifier._validate(
+        valueExpression,
+        CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE,
+      );
+
+      if (keyValue != null) {
+        var keyType = keyValue.type;
+
+        if (!verifier._evaluationEngine
+            .runtimeTypeMatch(keyValue, mapKeyType)) {
+          verifier._errorReporter.reportErrorForNode(
+            StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
+            keyExpression,
+            [keyType, mapKeyType],
+          );
+        }
+
+        if (verifier._implementsEqualsWhenNotAllowed(keyType)) {
+          verifier._errorReporter.reportErrorForNode(
+            CompileTimeErrorCode
+                .CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
+            keyExpression,
+            [keyType],
+          );
+        }
+
+        verifier._reportErrorIfFromDeferredLibrary(
+          keyExpression,
+          CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY,
+        );
+
+        if (!mapUniqueKeys.add(keyValue)) {
+          mapDuplicateKeyElements.add(keyExpression);
+        }
+      }
+
+      if (valueValue != null) {
+        if (!verifier._evaluationEngine
+            .runtimeTypeMatch(valueValue, mapValueType)) {
+          verifier._errorReporter.reportErrorForNode(
+            StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
+            valueExpression,
+            [valueValue.type, mapValueType],
+          );
+        }
+
+        verifier._reportErrorIfFromDeferredLibrary(
+          valueExpression,
+          CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY,
+        );
+      }
+    } else {
+      // Note: we throw the errors away because this isn't actually a const.
+      var nullErrorReporter = new ErrorReporter(
+        AnalysisErrorListener.NULL_LISTENER,
+        verifier._errorReporter.source,
+      );
+      var keyValue = keyExpression.accept(
+        new ConstantVisitor(verifier._evaluationEngine, nullErrorReporter),
+      );
+
+      if (keyValue != null) {
+        if (!mapUniqueKeys.add(keyValue)) {
+          mapDuplicateKeyElements.add(keyExpression);
+        }
+      }
+    }
+    return true;
+  }
+
+  bool _validateMapSpread(SpreadElement element, DartObjectImpl value) {
+    if (value.isNull && _isNullableSpread(element)) {
+      return true;
+    }
+    Map<DartObject, DartObject> map = value.toMapValue();
+    if (map != null) {
+      // TODO(brianwilkerson) Figure out how to improve the error messages. They
+      //  currently point to the whole spread expression, but the key and/or
+      //  value being referenced might not be located there (if it's referenced
+      //  through a const variable).
+      for (var entry in map.entries) {
+        DartObjectImpl keyValue = entry.key;
+        if (keyValue != null) {
+          if (!mapUniqueKeys.add(keyValue)) {
+            mapDuplicateKeyElements.add(element.expression);
+          }
+        }
+      }
+      return true;
+    }
+    verifier._errorReporter.reportErrorForNode(
+      CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP,
+      element.expression,
+    );
+    return false;
+  }
+
+  bool _validateSetExpression(Expression expression, DartObjectImpl value) {
+    if (!verifier._evaluationEngine.runtimeTypeMatch(value, setElementType)) {
+      verifier._errorReporter.reportErrorForNode(
+        StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE,
+        expression,
+        [value.type, setElementType],
+      );
+      return false;
+    }
+
+    if (verifier._implementsEqualsWhenNotAllowed(value.type)) {
+      verifier._errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
+        expression,
+        [value.type],
+      );
+      return false;
+    }
+
+    verifier._reportErrorIfFromDeferredLibrary(
+      expression,
+      CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY,
+    );
+
+    if (!setUniqueValues.add(value)) {
+      setDuplicateElements.add(expression);
+    }
+
+    return true;
+  }
+
+  static bool _isNullableSpread(SpreadElement element) {
+    return element.spreadOperator.type ==
+        TokenType.PERIOD_PERIOD_PERIOD_QUESTION;
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 390eea8..c4416ee 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -26,7 +26,7 @@
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:analyzer/src/generated/type_system.dart'
     show Dart2TypeSystem, TypeSystem;
-import 'package:analyzer/src/task/dart.dart';
+import 'package:analyzer/src/task/api/model.dart';
 
 /**
  * Helper class encapsulating the methods for evaluating constants and
@@ -930,6 +930,23 @@
 }
 
 /**
+ * Interface for [AnalysisTarget]s for which constant evaluation can be
+ * performed.
+ */
+abstract class ConstantEvaluationTarget extends AnalysisTarget {
+  /**
+   * Return the [AnalysisContext] which should be used to evaluate this
+   * constant.
+   */
+  AnalysisContext get context;
+
+  /**
+   * Return whether this constant is evaluated.
+   */
+  bool get isConstantEvaluated;
+}
+
+/**
  * Interface used by unit tests to verify correct dependency analysis during
  * constant evaluation.
  */
@@ -993,58 +1010,7 @@
 
 /**
  * A visitor used to evaluate constant expressions to produce their compile-time
- * value. According to the Dart Language Specification: <blockquote> A constant
- * expression is one of the following:
- *
- * * A literal number.
- * * A literal boolean.
- * * A literal string where any interpolated expression is a compile-time
- *   constant that evaluates to a numeric, string or boolean value or to
- *   <b>null</b>.
- * * A literal symbol.
- * * <b>null</b>.
- * * A qualified reference to a static constant variable.
- * * An identifier expression that denotes a constant variable, class or type
- *   alias.
- * * A constant constructor invocation.
- * * A constant list literal.
- * * A constant map literal.
- * * A simple or qualified identifier denoting a top-level function or a static
- *   method.
- * * A parenthesized expression <i>(e)</i> where <i>e</i> is a constant
- *   expression.
- * * An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i>
- *   where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
- *   expressions and <i>identical()</i> is statically bound to the predefined
- *   dart function <i>identical()</i> discussed above.
- * * An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i> or
- *   <i>e<sub>1</sub> != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and
- *   <i>e<sub>2</sub></i> are constant expressions that evaluate to a numeric,
- *   string or boolean value.
- * * An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> &amp;&amp;
- *   e<sub>2</sub></i> or <i>e<sub>1</sub> || e<sub>2</sub></i>, where <i>e</i>,
- *   <i>e1</sub></i> and <i>e2</sub></i> are constant expressions that evaluate
- *   to a boolean value.
- * * An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^
- *   e<sub>2</sub></i>, <i>e<sub>1</sub> &amp; e<sub>2</sub></i>,
- *   <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;&gt;
- *   e<sub>2</sub></i> or <i>e<sub>1</sub> &lt;&lt; e<sub>2</sub></i>, where
- *   <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
- *   expressions that evaluate to an integer value or to <b>null</b>.
- * * An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> +
- *   e<sub>2</sub></i>, <i>e<sub>1</sub> - e<sub>2</sub></i>, <i>e<sub>1</sub> *
- *   e<sub>2</sub></i>, <i>e<sub>1</sub> / e<sub>2</sub></i>, <i>e<sub>1</sub>
- *   ~/ e<sub>2</sub></i>, <i>e<sub>1</sub> &gt; e<sub>2</sub></i>,
- *   <i>e<sub>1</sub> &lt; e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;=
- *   e<sub>2</sub></i>, <i>e<sub>1</sub> &lt;= e<sub>2</sub></i> or
- *   <i>e<sub>1</sub> % e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i>
- *   and <i>e<sub>2</sub></i> are constant expressions that evaluate to a
- *   numeric value or to <b>null</b>.
- * * An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> :
- *   e<sub>3</sub></i> where <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and
- *   <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i>
- *   evaluates to a boolean value.
- * </blockquote>
+ * value.
  */
 class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
   /**
@@ -1467,7 +1433,14 @@
 
   @override
   DartObjectImpl visitSetOrMapLiteral(SetOrMapLiteral node) {
-    if (node.isMap) {
+    // Note: due to dartbug.com/33441, it's possible that a set/map literal
+    // resynthesized from a summary will have neither its `isSet` or `isMap`
+    // boolean set to `true`.  We work around the problem by assuming such
+    // literals are maps.
+    // TODO(paulberry): when dartbug.com/33441 is fixed, add an assertion here
+    // to verify that `node.isSet == !node.isMap`.
+    bool isMap = !node.isSet;
+    if (isMap) {
       if (!node.isConst) {
         _errorReporter.reportErrorForNode(
             CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL, node);
@@ -1494,7 +1467,7 @@
       InterfaceType mapType =
           _typeProvider.mapType.instantiate([keyType, valueType]);
       return new DartObjectImpl(mapType, new MapState(map));
-    } else if (node.isSet) {
+    } else {
       if (!node.isConst) {
         _errorReporter.reportErrorForNode(
             CompileTimeErrorCode.MISSING_CONST_IN_SET_LITERAL, node);
@@ -1516,7 +1489,6 @@
       InterfaceType setType = _typeProvider.setType.instantiate([elementType]);
       return new DartObjectImpl(setType, new SetState(set));
     }
-    return null;
   }
 
   @override
@@ -1580,8 +1552,7 @@
    */
   bool _addElementsToList(List<DartObject> list, CollectionElement element) {
     if (element is IfElement) {
-      DartObjectImpl conditionResult = element.condition.accept(this);
-      bool conditionValue = conditionResult?.toBoolValue();
+      bool conditionValue = _evaluateCondition(element.condition);
       if (conditionValue == null) {
         return true;
       } else if (conditionValue) {
@@ -1618,8 +1589,7 @@
   bool _addElementsToMap(
       Map<DartObjectImpl, DartObjectImpl> map, CollectionElement element) {
     if (element is IfElement) {
-      DartObjectImpl conditionResult = element.condition.accept(this);
-      bool conditionValue = conditionResult?.toBoolValue();
+      bool conditionValue = _evaluateCondition(element.condition);
       if (conditionValue == null) {
         return true;
       } else if (conditionValue) {
@@ -1656,8 +1626,7 @@
    */
   bool _addElementsToSet(Set<DartObject> set, CollectionElement element) {
     if (element is IfElement) {
-      DartObjectImpl conditionResult = element.condition.accept(this);
-      bool conditionValue = conditionResult?.toBoolValue();
+      bool conditionValue = _evaluateCondition(element.condition);
       if (conditionValue == null) {
         return true;
       } else if (conditionValue) {
@@ -1707,6 +1676,27 @@
   }
 
   /**
+   * Evaluate the given [condition] with the assumption that it must be a
+   * `bool`.
+   */
+  bool _evaluateCondition(Expression condition) {
+    DartObjectImpl conditionResult = condition.accept(this);
+    bool conditionValue = conditionResult?.toBoolValue();
+    if (conditionValue == null) {
+      // TODO(brianwilkerson) Figure out why the static type is sometimes null.
+      DartType staticType = condition.staticType;
+      if (staticType == null ||
+          typeSystem.isAssignableTo(staticType, _typeProvider.boolType)) {
+        // If the static type is not assignable, then we will have already
+        // reported this error.
+        _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, condition);
+      }
+    }
+    return conditionValue;
+  }
+
+  /**
    * Return the constant value of the static constant represented by the given
    * [element]. The [node] is the node to be used if an error needs to be
    * reported.
diff --git a/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart b/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
new file mode 100644
index 0000000..5a48513
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
@@ -0,0 +1,330 @@
+// Copyright (c) 2019, 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 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+
+/// Check if the [node] and all its sub-nodes are potentially constant.
+///
+/// Return the list of nodes that are not potentially constant.
+List<AstNode> getNotPotentiallyConstants(AstNode node) {
+  var collector = _Collector();
+  collector.collect(node);
+  return collector.nodes;
+}
+
+/// Return `true` if the [node] is a constant type expression.
+bool isConstantTypeExpression(TypeAnnotation node) {
+  if (node is TypeName) {
+    if (_isConstantTypeName(node.name)) {
+      var arguments = node.typeArguments?.arguments;
+      if (arguments != null) {
+        for (var argument in arguments) {
+          if (!isConstantTypeExpression(argument)) {
+            return false;
+          }
+        }
+      }
+      return true;
+    }
+    if (node.type is DynamicTypeImpl) {
+      return true;
+    }
+    if (node.type is VoidType) {
+      return true;
+    }
+    return false;
+  }
+
+  if (node is GenericFunctionType) {
+    var returnType = node.returnType;
+    if (returnType != null) {
+      if (!isConstantTypeExpression(returnType)) {
+        return false;
+      }
+    }
+
+    var typeParameters = node.typeParameters?.typeParameters;
+    if (typeParameters != null) {
+      for (var parameter in typeParameters) {
+        var bound = parameter.bound;
+        if (bound != null && !isConstantTypeExpression(bound)) {
+          return false;
+        }
+      }
+    }
+
+    var formalParameters = node.parameters?.parameters;
+    if (formalParameters != null) {
+      for (var parameter in formalParameters) {
+        if (parameter is SimpleFormalParameter) {
+          if (!isConstantTypeExpression(parameter.type)) {
+            return false;
+          }
+        }
+      }
+    }
+
+    return true;
+  }
+
+  return false;
+}
+
+bool _isConstantTypeName(Identifier name) {
+  var element = name.staticElement;
+  if (element is ClassElement || element is GenericTypeAliasElement) {
+    if (name is PrefixedIdentifier) {
+      if (name.isDeferred) {
+        return false;
+      }
+    }
+    return true;
+  }
+  return false;
+}
+
+class _Collector {
+  final List<AstNode> nodes = [];
+
+  void collect(AstNode node) {
+    if (node is BooleanLiteral ||
+        node is DoubleLiteral ||
+        node is IntegerLiteral ||
+        node is NullLiteral ||
+        node is SimpleStringLiteral ||
+        node is SymbolLiteral) {
+      return;
+    }
+
+    if (node is StringInterpolation) {
+      for (var component in node.elements) {
+        if (component is InterpolationExpression) {
+          collect(component.expression);
+        }
+      }
+      return;
+    }
+
+    if (node is Identifier) {
+      return _identifier(node);
+    }
+
+    if (node is InstanceCreationExpression) {
+      if (!node.isConst) {
+        nodes.add(node);
+      }
+      return;
+    }
+
+    if (node is TypedLiteral) {
+      return _typeLiteral(node);
+    }
+
+    if (node is ParenthesizedExpression) {
+      collect(node.expression);
+      return;
+    }
+
+    if (node is MethodInvocation) {
+      return _methodInvocation(node);
+    }
+
+    if (node is BinaryExpression) {
+      collect(node.leftOperand);
+      collect(node.rightOperand);
+      return;
+    }
+
+    if (node is PrefixExpression) {
+      var operator = node.operator.type;
+      if (operator == TokenType.BANG ||
+          operator == TokenType.MINUS ||
+          operator == TokenType.TILDE) {
+        collect(node.operand);
+        return;
+      }
+      nodes.add(node);
+      return;
+    }
+
+    if (node is ConditionalExpression) {
+      collect(node.condition);
+      collect(node.thenExpression);
+      collect(node.elseExpression);
+      return;
+    }
+
+    if (node is PropertyAccess) {
+      return _propertyAccess(node);
+    }
+
+    if (node is AsExpression) {
+      if (!isConstantTypeExpression(node.type)) {
+        nodes.add(node.type);
+      }
+      collect(node.expression);
+      return;
+    }
+
+    if (node is IsExpression) {
+      if (!isConstantTypeExpression(node.type)) {
+        nodes.add(node.type);
+      }
+      collect(node.expression);
+      return;
+    }
+
+    if (node is MapLiteralEntry) {
+      collect(node.key);
+      collect(node.value);
+      return;
+    }
+
+    if (node is SpreadElement) {
+      collect(node.expression);
+      return;
+    }
+
+    if (node is IfElement) {
+      collect(node.condition);
+      collect(node.thenElement);
+      if (node.elseElement != null) {
+        collect(node.elseElement);
+      }
+      return;
+    }
+
+    nodes.add(node);
+  }
+
+  void _identifier(Identifier node) {
+    var element = node.staticElement;
+
+    if (node is PrefixedIdentifier) {
+      if (node.isDeferred) {
+        nodes.add(node);
+        return;
+      }
+      if (node.identifier.name == 'length') {
+        collect(node.prefix);
+        return;
+      }
+      if (element is MethodElement && element.isStatic) {
+        if (_isConstantTypeName(node.prefix)) {
+          return;
+        }
+      }
+    }
+
+    if (element is VariableElement) {
+      if (!element.isConst) {
+        nodes.add(node);
+      }
+      return;
+    }
+    if (element is PropertyAccessorElement && element.isGetter) {
+      var variable = element.variable;
+      if (!variable.isConst) {
+        nodes.add(node);
+      }
+      return;
+    }
+    if (_isConstantTypeName(node)) {
+      return;
+    }
+    if (element is FunctionElement) {
+      return;
+    }
+    nodes.add(node);
+  }
+
+  void _methodInvocation(MethodInvocation node) {
+    var arguments = node.argumentList?.arguments;
+    if (arguments?.length == 2 && node.methodName.name == 'identical') {
+      var library = node.methodName?.staticElement?.library;
+      if (library?.isDartCore == true) {
+        collect(arguments[0]);
+        collect(arguments[1]);
+        return;
+      }
+    }
+    nodes.add(node);
+  }
+
+  void _propertyAccess(PropertyAccess node) {
+    if (node.propertyName.name == 'length') {
+      collect(node.target);
+      return;
+    }
+
+    var target = node.target;
+    if (target is PrefixedIdentifier) {
+      if (target.isDeferred) {
+        nodes.add(node);
+        return;
+      }
+
+      var element = node.propertyName.staticElement;
+      if (element is PropertyAccessorElement && element.isGetter) {
+        var variable = element.variable;
+        if (!variable.isConst) {
+          nodes.add(node.propertyName);
+        }
+        return;
+      }
+    }
+
+    nodes.add(node);
+  }
+
+  void _typeLiteral(TypedLiteral node) {
+    if (!node.isConst) {
+      nodes.add(node);
+      return;
+    }
+
+    if (node is ListLiteral) {
+      var typeArguments = node.typeArguments?.arguments;
+      if (typeArguments?.length == 1) {
+        var elementType = typeArguments[0];
+        if (!isConstantTypeExpression(elementType)) {
+          nodes.add(elementType);
+        }
+      }
+
+      for (var element in node.elements2) {
+        collect(element);
+      }
+      return;
+    }
+
+    if (node is SetOrMapLiteral) {
+      var typeArguments = node.typeArguments?.arguments;
+      if (typeArguments?.length == 1) {
+        var elementType = typeArguments[0];
+        if (!isConstantTypeExpression(elementType)) {
+          nodes.add(elementType);
+        }
+      }
+
+      if (typeArguments?.length == 2) {
+        var keyType = typeArguments[0];
+        var valueType = typeArguments[1];
+        if (!isConstantTypeExpression(keyType)) {
+          nodes.add(keyType);
+        }
+        if (!isConstantTypeExpression(valueType)) {
+          nodes.add(valueType);
+        }
+      }
+
+      for (var element in node.elements2) {
+        collect(element);
+      }
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/constant/utilities.dart b/pkg/analyzer/lib/src/dart/constant/utilities.dart
index 3a9b8a7..6e5f535 100644
--- a/pkg/analyzer/lib/src/dart/constant/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/constant/utilities.dart
@@ -12,11 +12,11 @@
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/handle.dart'
     show ConstructorElementHandle;
 import 'package:analyzer/src/dart/element/member.dart';
-import 'package:analyzer/src/task/dart.dart';
 
 ConstructorElementImpl getConstructorImpl(ConstructorElement constructor) {
   while (constructor is ConstructorMember) {
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 1f9c4c1..5cf726d 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/constant/compute.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/handle.dart';
 import 'package:analyzer/src/dart/element/type.dart';
@@ -31,7 +32,6 @@
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary2/linked_unit_context.dart';
 import 'package:analyzer/src/summary2/reference.dart';
-import 'package:analyzer/src/task/dart.dart';
 
 /// Assert that the given [object] is null, which in the places where this
 /// function is called means that the element is not resynthesized.
@@ -60,6 +60,10 @@
   /// given [offset] in the file that contains the declaration of this element.
   AbstractClassElementImpl(String name, int offset) : super(name, offset);
 
+  AbstractClassElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created class element to have the given [name].
   AbstractClassElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -414,9 +418,6 @@
   /// The unlinked representation of the class in the summary.
   final UnlinkedClass _unlinkedClass;
 
-  final Reference reference;
-  final LinkedNode _linkedNode;
-
   /// If this class is resynthesized, whether it has a constant constructor.
   bool _hasConstConstructorCached;
 
@@ -455,31 +456,25 @@
   /// Initialize a newly created class element to have the given [name] at the
   /// given [offset] in the file that contains the declaration of this element.
   ClassElementImpl(String name, int offset)
-      : reference = null,
-        _linkedNode = null,
-        _unlinkedClass = null,
+      : _unlinkedClass = null,
         super(name, offset);
 
-  ClassElementImpl.forLinkedNode(this.reference, this._linkedNode,
-      CompilationUnitElementImpl enclosingUnit)
+  ClassElementImpl.forLinkedNode(CompilationUnitElementImpl enclosing,
+      Reference reference, LinkedNode linkedNode)
       : _unlinkedClass = null,
-        super.forSerialized(enclosingUnit) {
-    reference.element = this;
+        super.forLinkedNode(enclosing, reference, linkedNode) {
+    enclosing.linkedContext.loadClassMemberReferences(reference);
   }
 
   /// Initialize a newly created class element to have the given [name].
   ClassElementImpl.forNode(Identifier name)
-      : reference = null,
-        _linkedNode = null,
-        _unlinkedClass = null,
+      : _unlinkedClass = null,
         super.forNode(name);
 
   /// Initialize using the given serialized information.
   ClassElementImpl.forSerialized(
       this._unlinkedClass, CompilationUnitElementImpl enclosingUnit)
-      : reference = null,
-        _linkedNode = null,
-        super.forSerialized(enclosingUnit);
+      : super.forSerialized(enclosingUnit);
 
   /// Set whether this class is abstract.
   void set abstract(bool isAbstract) {
@@ -489,6 +484,18 @@
 
   @override
   List<PropertyAccessorElement> get accessors {
+    if (linkedNode != null) {
+      if (_accessors != null) return _accessors;
+
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration ||
+          linkedNode.kind == LinkedNodeKind.mixinDeclaration) {
+        _createPropertiesAndAccessors();
+        assert(_accessors != null);
+        return _accessors;
+      } else {
+        return _accessors = const [];
+      }
+    }
     if (_accessors == null) {
       if (_unlinkedClass != null) {
         _resynthesizeFieldsAndPropertyAccessors();
@@ -536,16 +543,18 @@
       return _constructors = _computeMixinAppConstructors();
     }
 
-    if (_linkedNode != null) {
-      var context = enclosingUnit._linkedContext;
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
       var containerRef = reference.getChild('@constructor');
-      _constructors = _linkedNode.classOrMixinDeclaration_members
-          .where((node) => node.kind == LinkedNodeKind.constructorDeclaration)
-          .map((node) {
-        var name = context.getConstructorDeclarationName(node);
-        var reference = containerRef.getChild(name);
-        return ConstructorElementImpl.forLinkedNode(reference, node, this);
-      }).toList();
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration) {
+        _constructors = linkedNode.classOrMixinDeclaration_members
+            .where((node) => node.kind == LinkedNodeKind.constructorDeclaration)
+            .map((node) {
+          var name = context.getConstructorDeclarationName(node);
+          var reference = containerRef.getChild(name);
+          return ConstructorElementImpl.forLinkedNode(reference, node, this);
+        }).toList();
+      }
     }
 
     if (_unlinkedClass != null) {
@@ -601,6 +610,11 @@
 
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.annotatedNode_comment,
+      );
+    }
     if (_unlinkedClass != null) {
       return _unlinkedClass.documentationComment?.text;
     }
@@ -612,6 +626,18 @@
 
   @override
   List<FieldElement> get fields {
+    if (linkedNode != null) {
+      if (_fields != null) return _fields;
+
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration ||
+          linkedNode.kind == LinkedNodeKind.mixinDeclaration) {
+        _createPropertiesAndAccessors();
+        assert(_fields != null);
+        return _fields;
+      } else {
+        _fields = const [];
+      }
+    }
     if (_fields == null) {
       if (_unlinkedClass != null) {
         _resynthesizeFieldsAndPropertyAccessors();
@@ -710,13 +736,13 @@
       return _interfaces;
     }
 
-    if (_linkedNode != null) {
-      var context = enclosingUnit._linkedContext;
-      var implementsClause =
-          _linkedNode.classOrMixinDeclaration_implementsClause;
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var implementsClause = context.getImplementsClause(linkedNode);
       if (implementsClause != null) {
         return _interfaces = implementsClause.implementsClause_interfaces
             .map((node) => context.getInterfaceType(node.typeName_type))
+            .where((type) => type != null)
             .toList();
       }
     } else if (_unlinkedClass != null) {
@@ -757,8 +783,12 @@
 
   @override
   bool get isAbstract {
-    if (_linkedNode != null) {
-      return _linkedNode.classDeclaration_abstractKeyword != 0;
+    if (linkedNode != null) {
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration) {
+        return linkedNode.classDeclaration_abstractKeyword != 0;
+      } else {
+        return linkedNode.classTypeAlias_abstractKeyword != 0;
+      }
     }
     if (_unlinkedClass != null) {
       return _unlinkedClass.isAbstract;
@@ -768,6 +798,9 @@
 
   @override
   bool get isMixinApplication {
+    if (linkedNode != null) {
+      return linkedNode.kind == LinkedNodeKind.classTypeAlias;
+    }
     if (_unlinkedClass != null) {
       return _unlinkedClass.isMixinApplication;
     }
@@ -819,6 +852,24 @@
       return _methods;
     }
 
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var containerRef = reference.getChild('@method');
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration ||
+          linkedNode.kind == LinkedNodeKind.mixinDeclaration) {
+        return _methods = linkedNode.classOrMixinDeclaration_members
+            .where((node) => node.kind == LinkedNodeKind.methodDeclaration)
+            .where((node) => node.methodDeclaration_propertyKeyword == 0)
+            .map((node) {
+          var name = context.getSimpleName(node.methodDeclaration_name);
+          var reference = containerRef.getChild(name);
+          return MethodElementImpl.forLinkedNode(reference, node, this);
+        }).toList();
+      } else {
+        return _methods = const <MethodElement>[];
+      }
+    }
+
     if (_unlinkedClass != null) {
       var unlinkedExecutables = _unlinkedClass.executables;
 
@@ -872,12 +923,18 @@
       return _mixins;
     }
 
-    if (_linkedNode != null) {
-      var context = enclosingUnit._linkedContext;
-      var withClause = _linkedNode.classDeclaration_withClause;
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      LinkedNode withClause;
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration) {
+        withClause = linkedNode.classDeclaration_withClause;
+      } else {
+        withClause = linkedNode.classTypeAlias_withClause;
+      }
       if (withClause != null) {
         return _mixins = withClause.withClause_mixinTypes
             .map((node) => context.getInterfaceType(node.typeName_type))
+            .where((type) => type != null)
             .toList();
       }
     } else if (_unlinkedClass != null) {
@@ -923,7 +980,7 @@
 
   @override
   String get name {
-    if (_linkedNode != null) {
+    if (linkedNode != null) {
       return reference.name;
     }
     if (_unlinkedClass != null) {
@@ -949,13 +1006,19 @@
   @override
   InterfaceType get supertype {
     if (_supertype == null) {
-      if (_linkedNode != null) {
-        var context = enclosingUnit._linkedContext;
-        var extendsClause = _linkedNode.classDeclaration_extendsClause;
-        if (extendsClause != null) {
-          _supertype = context.getInterfaceType(
-            extendsClause.extendsClause_superclass.typeName_type,
-          );
+      if (linkedNode != null) {
+        LinkedNode superclass;
+        if (linkedNode.kind == LinkedNodeKind.classDeclaration) {
+          superclass = linkedNode
+              .classDeclaration_extendsClause?.extendsClause_superclass;
+        } else {
+          superclass = linkedNode.classTypeAlias_superclass;
+        }
+        if (superclass != null) {
+          var context = enclosingUnit.linkedContext;
+          _supertype = context.getInterfaceType(superclass.typeName_type);
+        } else if (!linkedNode.classDeclaration_isDartObject) {
+          _supertype = context.typeProvider.objectType;
         }
       } else if (_unlinkedClass != null) {
         if (_unlinkedClass.supertype != null) {
@@ -991,6 +1054,27 @@
     return _type;
   }
 
+  @override
+  List<TypeParameterElement> get typeParameters {
+    if (_typeParameterElements != null) return _typeParameterElements;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var containerRef = reference.getChild('@typeParameter');
+      var typeParameters = context.getTypeParameters(linkedNode);
+      if (typeParameters == null) {
+        return _typeParameterElements = const [];
+      }
+      return _typeParameterElements = typeParameters.map((node) {
+        var name = context.getSimpleName(node.typeParameter_name);
+        var reference = containerRef.getChild(name);
+        reference.node = node;
+        return TypeParameterElementImpl.forLinkedNode(this, reference, node);
+      }).toList();
+    }
+    return super.typeParameters;
+  }
+
   /// Set the type parameters defined for this class to the given
   /// [typeParameters].
   void set typeParameters(List<TypeParameterElement> typeParameters) {
@@ -1208,6 +1292,75 @@
     }).toList(growable: false);
   }
 
+  void _createPropertiesAndAccessors() {
+    assert(_accessors == null);
+    assert(_fields == null);
+
+    var context = enclosingUnit.linkedContext;
+    var accessorList = <PropertyAccessorElementImpl>[];
+    var fieldList = <FieldElementImpl>[];
+
+    var fields = context.classFields(linkedNode);
+    for (var field in fields) {
+      var name = context.getVariableName(field);
+      var fieldElement = FieldElementImpl.forLinkedNodeFactory(
+        this,
+        reference.getChild('@field').getChild(name),
+        field,
+      );
+      fieldList.add(fieldElement);
+
+      accessorList.add(fieldElement.getter);
+      if (fieldElement.setter != null) {
+        accessorList.add(fieldElement.setter);
+      }
+    }
+
+    for (var node in linkedNode.classOrMixinDeclaration_members) {
+      if (node.kind == LinkedNodeKind.methodDeclaration) {
+        var isGetter = context.isGetterMethod(node);
+        var isSetter = context.isSetterMethod(node);
+        if (!isGetter && !isSetter) continue;
+
+        var name = context.getMethodName(node);
+        var containerRef = isGetter
+            ? reference.getChild('@getter')
+            : reference.getChild('@setter');
+
+        var accessorElement = PropertyAccessorElementImpl.forLinkedNode(
+          this,
+          containerRef.getChild(name),
+          node,
+        );
+        accessorList.add(accessorElement);
+
+        var fieldRef = reference.getChild('@field').getChild(name);
+        FieldElementImpl field = fieldRef.element;
+        if (field == null) {
+          field = new FieldElementImpl(name, -1);
+          fieldRef.element = field;
+          field.enclosingElement = this;
+          field.isSynthetic = true;
+          field.isFinal = isGetter;
+          field.isStatic = accessorElement.isStatic;
+          fieldList.add(field);
+        } else {
+          field.isFinal = false;
+        }
+
+        accessorElement.variable = field;
+        if (isGetter) {
+          field.getter = accessorElement;
+        } else {
+          field.setter = accessorElement;
+        }
+      }
+    }
+
+    _accessors = accessorList;
+    _fields = fieldList;
+  }
+
   /// Return `true` if the given [type] is an [InterfaceType] that can be used
   /// as a class.
   bool _isInterfaceTypeClass(DartType type) {
@@ -1412,9 +1565,7 @@
   /// The unlinked representation of the part in the summary.
   final UnlinkedPart _unlinkedPart;
 
-  final LinkedUnitContext _linkedContext;
-  final Reference reference;
-  final LinkedNode _linkedNode;
+  final LinkedUnitContext linkedContext;
 
   /// The source that corresponds to this compilation unit.
   @override
@@ -1477,27 +1628,20 @@
       : resynthesizerContext = null,
         _unlinkedUnit = null,
         _unlinkedPart = null,
-        _linkedContext = null,
-        reference = null,
-        _linkedNode = null,
+        linkedContext = null,
         super(null, -1);
 
   CompilationUnitElementImpl.forLinkedNode(LibraryElementImpl enclosingLibrary,
-      this._linkedContext, this.reference, this._linkedNode)
+      this.linkedContext, Reference reference, LinkedNode linkedNode)
       : resynthesizerContext = null,
         _unlinkedUnit = null,
         _unlinkedPart = null,
-        super.forSerialized(null) {
-    _enclosingElement = enclosingLibrary;
-    _nameOffset = -1;
-  }
+        super.forLinkedNode(enclosingLibrary, reference, linkedNode);
 
   /// Initialize using the given serialized information.
   CompilationUnitElementImpl.forSerialized(LibraryElementImpl enclosingLibrary,
       this.resynthesizerContext, this._unlinkedUnit, this._unlinkedPart)
-      : _linkedContext = null,
-        reference = null,
-        _linkedNode = null,
+      : linkedContext = null,
         super.forSerialized(null) {
     _enclosingElement = enclosingLibrary;
     _nameOffset = -1;
@@ -1505,6 +1649,12 @@
 
   @override
   List<PropertyAccessorElement> get accessors {
+    if (linkedNode != null) {
+      if (_accessors != null) return _accessors;
+      _createPropertiesAndAccessors(this);
+      assert(_accessors != null);
+      return _accessors;
+    }
     if (_accessors == null) {
       if (_unlinkedUnit != null) {
         _explicitTopLevelAccessors ??=
@@ -1557,6 +1707,19 @@
 
   @override
   List<ClassElement> get enums {
+    if (linkedNode != null) {
+      if (_enums != null) return _enums;
+      var context = enclosingUnit.linkedContext;
+      var containerRef = reference.getChild('@enum');
+      _enums = linkedNode.compilationUnit_declarations
+          .where((node) => node.kind == LinkedNodeKind.enumDeclaration)
+          .map((node) {
+        var name = context.getUnitMemberName(node);
+        var reference = containerRef.getChild(name);
+        reference.node = node;
+        return EnumElementImpl.forLinkedNode(this, reference, node);
+      }).toList();
+    }
     if (_unlinkedUnit != null) {
       _enums ??= _unlinkedUnit.enums
           .map((e) => new EnumElementImpl.forSerialized(e, this))
@@ -1576,8 +1739,23 @@
 
   @override
   List<FunctionElement> get functions {
-    if (_unlinkedUnit != null) {
-      _functions ??= _unlinkedUnit.executables
+    if (_functions != null) return _functions;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var containerRef = reference.getChild('@function');
+      _functions = linkedNode.compilationUnit_declarations
+          .where((node) =>
+              node.kind == LinkedNodeKind.functionDeclaration &&
+              !context.isGetterFunction(node) &&
+              !context.isSetterFunction(node))
+          .map((node) {
+        var name = context.getUnitMemberName(node);
+        var reference = containerRef.getChild(name);
+        return FunctionElementImpl.forLinkedNode(this, reference, node);
+      }).toList();
+    } else if (_unlinkedUnit != null) {
+      _functions = _unlinkedUnit.executables
           .where((e) => e.kind == UnlinkedExecutableKind.functionOrMethod)
           .map((e) => new FunctionElementImpl.forSerialized(e, this))
           .toList(growable: false);
@@ -1596,8 +1774,22 @@
 
   @override
   List<FunctionTypeAliasElement> get functionTypeAliases {
+    if (_typeAliases != null) return _typeAliases;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var containerRef = reference.getChild('@typeAlias');
+      _typeAliases = linkedNode.compilationUnit_declarations
+          .where((node) => node.kind == LinkedNodeKind.functionTypeAlias)
+          .map((node) {
+        var name = context.getUnitMemberName(node);
+        var reference = containerRef.getChild(name);
+        return GenericTypeAliasElementImpl.forLinkedNode(this, reference, node);
+      }).toList();
+    }
+
     if (_unlinkedUnit != null) {
-      _typeAliases ??= _unlinkedUnit.typedefs.map((t) {
+      _typeAliases = _unlinkedUnit.typedefs.map((t) {
         return new GenericTypeAliasElementImpl.forSerialized(t, this);
       }).toList(growable: false);
     }
@@ -1657,6 +1849,12 @@
 
   @override
   List<TopLevelVariableElement> get topLevelVariables {
+    if (linkedNode != null) {
+      if (_variables != null) return _variables;
+      _createPropertiesAndAccessors(this);
+      assert(_variables != null);
+      return _variables;
+    }
     if (_variables == null) {
       if (_unlinkedUnit != null) {
         _explicitTopLevelAccessors ??=
@@ -1711,15 +1909,18 @@
 
   @override
   List<ClassElement> get types {
-    if (_linkedNode != null) {
-      var context = enclosingUnit._linkedContext;
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
       var containerRef = reference.getChild('@class');
-      _types = _linkedNode.compilationUnit_declarations
-          .where((node) => node.kind == LinkedNodeKind.classDeclaration)
+      _types = linkedNode.compilationUnit_declarations
+          .where((node) =>
+              node.kind == LinkedNodeKind.classDeclaration ||
+              node.kind == LinkedNodeKind.classTypeAlias)
           .map((node) {
         var name = context.getUnitMemberName(node);
         var reference = containerRef.getChild(name);
-        return ClassElementImpl.forLinkedNode(reference, node, this);
+        reference.node = node;
+        return ClassElementImpl.forLinkedNode(this, reference, node);
       }).toList();
     } else if (_unlinkedUnit != null) {
       _types ??= _unlinkedUnit.classes
@@ -1880,6 +2081,89 @@
     }
     return null;
   }
+
+  static void _createPropertiesAndAccessors(CompilationUnitElementImpl unit) {
+    if (unit._variables != null) return;
+    assert(unit._accessors == null);
+
+    var accessorMap =
+        <CompilationUnitElementImpl, List<PropertyAccessorElementImpl>>{};
+    var variableMap =
+        <CompilationUnitElementImpl, List<TopLevelVariableElementImpl>>{};
+
+    var units = unit.library.units;
+    for (CompilationUnitElementImpl unit in units) {
+      var context = unit.linkedContext;
+
+      var accessorList = <PropertyAccessorElementImpl>[];
+      accessorMap[unit] = accessorList;
+
+      var variableList = <TopLevelVariableElementImpl>[];
+      variableMap[unit] = variableList;
+
+      var variables = context.topLevelVariables(unit.linkedNode);
+      for (var variable in variables) {
+        var name = context.getVariableName(variable);
+        var reference = unit.reference.getChild('@variable').getChild(name);
+        var variableElement = TopLevelVariableElementImpl.forLinkedNodeFactory(
+          unit,
+          reference,
+          variable,
+        );
+        variableList.add(variableElement);
+
+        accessorList.add(variableElement.getter);
+        if (variableElement.setter != null) {
+          accessorList.add(variableElement.setter);
+        }
+      }
+
+      for (var node in unit.linkedNode.compilationUnit_declarations) {
+        if (node.kind == LinkedNodeKind.functionDeclaration) {
+          var isGetter = context.isGetterFunction(node);
+          var isSetter = context.isSetterFunction(node);
+          if (!isGetter && !isSetter) continue;
+
+          var name = context.getUnitMemberName(node);
+          var containerRef = isGetter
+              ? unit.reference.getChild('@getter')
+              : unit.reference.getChild('@setter');
+
+          var accessorElement = PropertyAccessorElementImpl.forLinkedNode(
+            unit,
+            containerRef.getChild(name),
+            node,
+          );
+          accessorList.add(accessorElement);
+
+          var fieldRef = unit.reference.getChild('@field').getChild(name);
+          TopLevelVariableElementImpl field = fieldRef.element;
+          if (field == null) {
+            field = new TopLevelVariableElementImpl(name, -1);
+            fieldRef.element = field;
+            field.enclosingElement = unit;
+            field.isSynthetic = true;
+            field.isFinal = isGetter;
+            variableList.add(field);
+          } else {
+            field.isFinal = false;
+          }
+
+          accessorElement.variable = field;
+          if (isGetter) {
+            field.getter = accessorElement;
+          } else {
+            field.setter = accessorElement;
+          }
+        }
+      }
+    }
+
+    for (CompilationUnitElementImpl unit in units) {
+      unit._accessors = accessorMap[unit];
+      unit._variables = variableMap[unit];
+    }
+  }
 }
 
 /// A [FieldElement] for a 'const' or 'final' field that has an initializer.
@@ -1895,6 +2179,10 @@
   /// [name] and [offset].
   ConstFieldElementImpl(String name, int offset) : super(name, offset);
 
+  ConstFieldElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created field element to have the given [name].
   ConstFieldElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -1913,8 +2201,21 @@
       EnumElementImpl enumElement, this._unlinkedEnumValue, this._index)
       : super(enumElement);
 
+  ConstFieldElementImpl_EnumValue.forLinkedNode(EnumElementImpl enumElement,
+      Reference reference, LinkedNode linkedNode, this._index)
+      : _unlinkedEnumValue = null,
+        super.forLinkedNode(enumElement, reference, linkedNode);
+
+  @override
+  Expression get constantInitializer => null;
+
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.annotatedNode_comment,
+      );
+    }
     if (_unlinkedEnumValue != null) {
       return _unlinkedEnumValue.documentationComment?.text;
     }
@@ -1946,6 +2247,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (_unlinkedEnumValue != null) {
       return _unlinkedEnumValue.name;
     }
@@ -1954,9 +2258,16 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getSimpleOffset(
+        linkedNode.enumConstantDeclaration_name,
+      );
+    }
     int offset = super.nameOffset;
-    if (offset == -1 && _unlinkedEnumValue != null) {
-      return _unlinkedEnumValue.nameOffset;
+    if (offset == -1) {
+      if (_unlinkedEnumValue != null) {
+        return _unlinkedEnumValue.nameOffset;
+      }
     }
     return offset;
   }
@@ -2008,6 +2319,10 @@
     enclosingElement = _enum;
   }
 
+  ConstFieldElementImpl_ofEnum.forLinkedNode(
+      this._enum, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(_enum, reference, linkedNode);
+
   @override
   void set evaluationResult(_) {
     assert(false);
@@ -2080,34 +2395,21 @@
   @override
   bool isConstantEvaluated = false;
 
-  final Reference reference;
-  final LinkedNode _linkedNode;
+  /// Initialize a newly created constructor element to have the given [name]
+  /// and [offset].
+  ConstructorElementImpl(String name, int offset) : super(name, offset);
 
-  /// Initialize a newly created constructor element to have the given [name
-  /// ] and[offset].
-  ConstructorElementImpl(String name, int offset)
-      : reference = null,
-        _linkedNode = null,
-        super(name, offset);
-
-  ConstructorElementImpl.forLinkedNode(
-      this.reference, this._linkedNode, ClassElementImpl enclosingClass)
-      : super.forLinkedNode(enclosingClass) {
-    reference.element = this;
-  }
+  ConstructorElementImpl.forLinkedNode(Reference reference,
+      LinkedNode linkedNode, ClassElementImpl enclosingClass)
+      : super.forLinkedNode(enclosingClass, reference, linkedNode);
 
   /// Initialize a newly created constructor element to have the given [name].
-  ConstructorElementImpl.forNode(Identifier name)
-      : reference = null,
-        _linkedNode = null,
-        super.forNode(name);
+  ConstructorElementImpl.forNode(Identifier name) : super.forNode(name);
 
   /// Initialize using the given serialized information.
   ConstructorElementImpl.forSerialized(
       UnlinkedExecutable serializedExecutable, ClassElementImpl enclosingClass)
-      : reference = null,
-        _linkedNode = null,
-        super.forSerialized(serializedExecutable, enclosingClass);
+      : super.forSerialized(serializedExecutable, enclosingClass);
 
   /// Return the constant initializers for this element, which will be empty if
   /// there are no initializers, or `null` if there was an error in the source.
@@ -2130,7 +2432,7 @@
 
   @override
   String get displayName {
-    if (_linkedNode != null) {
+    if (linkedNode != null) {
       return reference.name;
     }
     return super.displayName;
@@ -2152,8 +2454,8 @@
 
   @override
   bool get isConst {
-    if (_linkedNode != null) {
-      return _linkedNode.constructorDeclaration_constKeyword != 0;
+    if (linkedNode != null) {
+      return linkedNode.constructorDeclaration_constKeyword != 0;
     }
     if (serializedExecutable != null) {
       return serializedExecutable.isConst;
@@ -2200,17 +2502,9 @@
   }
 
   @override
-  bool get isExternal {
-    if (_linkedNode != null) {
-      return _linkedNode.constructorDeclaration_externalKeyword != 0;
-    }
-    return super.isExternal;
-  }
-
-  @override
   bool get isFactory {
-    if (_linkedNode != null) {
-      return _linkedNode.constructorDeclaration_factoryKeyword != 0;
+    if (linkedNode != null) {
+      return linkedNode.constructorDeclaration_factoryKeyword != 0;
     }
     if (serializedExecutable != null) {
       return serializedExecutable.isFactory;
@@ -2222,19 +2516,11 @@
   bool get isStatic => false;
 
   @override
-  bool get isSynthetic {
-    if (_linkedNode != null) {
-      return _linkedNode.isSynthetic;
-    }
-    return super.isSynthetic;
-  }
-
-  @override
   ElementKind get kind => ElementKind.CONSTRUCTOR;
 
   @override
   String get name {
-    if (_linkedNode != null) {
+    if (linkedNode != null) {
       return reference.name;
     }
     return super.name;
@@ -2415,6 +2701,10 @@
   ConstTopLevelVariableElementImpl(String name, int offset)
       : super(name, offset);
 
+  ConstTopLevelVariableElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created top-level variable element to have the given
   /// [name].
   ConstTopLevelVariableElementImpl.forNode(Identifier name)
@@ -2448,11 +2738,16 @@
   EvaluationResultImpl _evaluationResult;
 
   Expression get constantInitializer {
-    if (_constantInitializer == null) {
-      if (_unlinkedConst != null) {
-        _constantInitializer = enclosingUnit.resynthesizerContext
-            .buildExpression(this, _unlinkedConst);
-      }
+    if (_constantInitializer != null) return _constantInitializer;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      return _constantInitializer = context.readInitializer(linkedNode);
+    }
+
+    if (_unlinkedConst != null) {
+      _constantInitializer = enclosingUnit.resynthesizerContext
+          .buildExpression(this, _unlinkedConst);
     }
     return _constantInitializer;
   }
@@ -2515,6 +2810,10 @@
   DefaultParameterElementImpl(String name, int nameOffset)
       : super(name, nameOffset);
 
+  DefaultParameterElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created parameter element to have the given [name].
   DefaultParameterElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -2807,6 +3106,9 @@
   /// root of the element structure.
   ElementImpl _enclosingElement;
 
+  Reference reference;
+  final LinkedNode linkedNode;
+
   /// The name of this element.
   String _name;
 
@@ -2838,19 +3140,26 @@
 
   /// Initialize a newly created element to have the given [name] at the given
   /// [_nameOffset].
-  ElementImpl(String name, this._nameOffset) {
+  ElementImpl(String name, this._nameOffset, {this.reference})
+      : linkedNode = null {
     this._name = StringUtilities.intern(name);
+    this.reference?.element = this;
   }
 
   /// Initialize from linked node.
-  ElementImpl.forLinkedNode(this._enclosingElement);
+  ElementImpl.forLinkedNode(
+      this._enclosingElement, this.reference, this.linkedNode) {
+    reference?.element = this;
+  }
 
   /// Initialize a newly created element to have the given [name].
   ElementImpl.forNode(Identifier name)
       : this(name == null ? "" : name.name, name == null ? -1 : name.offset);
 
   /// Initialize from serialized information.
-  ElementImpl.forSerialized(this._enclosingElement);
+  ElementImpl.forSerialized(this._enclosingElement)
+      : reference = null,
+        linkedNode = null;
 
   /// The length of the element's code, or `null` if the element is synthetic.
   int get codeLength => _codeLength;
@@ -3100,7 +3409,12 @@
   bool get isResynthesized => enclosingUnit?.resynthesizerContext != null;
 
   @override
-  bool get isSynthetic => hasModifier(Modifier.SYNTHETIC);
+  bool get isSynthetic {
+    if (linkedNode != null) {
+      return linkedNode.isSynthetic;
+    }
+    return hasModifier(Modifier.SYNTHETIC);
+  }
 
   /// Set whether this element is synthetic.
   void set isSynthetic(bool isSynthetic) {
@@ -3129,6 +3443,11 @@
   }
 
   List<ElementAnnotation> get metadata {
+    if (linkedNode != null) {
+      if (_metadata != null) return _metadata;
+      var metadata = enclosingUnit.linkedContext.getMetadataOrEmpty(linkedNode);
+      return _metadata = _buildAnnotations2(enclosingUnit, metadata);
+    }
     return _metadata ?? const <ElementAnnotation>[];
   }
 
@@ -3157,8 +3476,6 @@
     _nameOffset = offset;
   }
 
-  Reference get reference => null;
-
   @override
   AnalysisSession get session {
     return _enclosingElement?.session;
@@ -3340,6 +3657,23 @@
     }
   }
 
+  /// Return annotations for the given [nodeList] in the [unit].
+  List<ElementAnnotation> _buildAnnotations2(
+      CompilationUnitElementImpl unit, List<LinkedNode> nodeList) {
+    var length = nodeList.length;
+    if (length == 0) {
+      return const <ElementAnnotation>[];
+    }
+
+    var annotations = new List<ElementAnnotation>(length);
+    for (int i = 0; i < length; i++) {
+      var ast = unit.linkedContext.readNode(nodeList[i]);
+      annotations[i] = ElementAnnotationImpl(enclosingUnit)
+        ..annotationAst = ast;
+    }
+    return annotations;
+  }
+
   /// If the element associated with the given [type] is a generic function type
   /// element, then make it a child of this element. Return the [type] as a
   /// convenience.
@@ -3526,6 +3860,11 @@
       : _unlinkedEnum = null,
         super(name, offset);
 
+  EnumElementImpl.forLinkedNode(CompilationUnitElementImpl enclosing,
+      Reference reference, LinkedNode linkedNode)
+      : _unlinkedEnum = null,
+        super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created class element to have the given [name].
   EnumElementImpl.forNode(Identifier name)
       : _unlinkedEnum = null,
@@ -3544,6 +3883,9 @@
   @override
   List<PropertyAccessorElement> get accessors {
     if (_accessors == null) {
+      if (linkedNode != null) {
+        _resynthesizeMembers2();
+      }
       if (_unlinkedEnum != null) {
         _resynthesizeMembers();
       }
@@ -3587,6 +3929,11 @@
 
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.annotatedNode_comment,
+      );
+    }
     if (_unlinkedEnum != null) {
       return _unlinkedEnum.documentationComment?.text;
     }
@@ -3596,6 +3943,9 @@
   @override
   List<FieldElement> get fields {
     if (_fields == null) {
+      if (linkedNode != null) {
+        _resynthesizeMembers2();
+      }
       if (_unlinkedEnum != null) {
         _resynthesizeMembers();
       }
@@ -3654,6 +4004,9 @@
   @override
   List<MethodElement> get methods {
     if (_methods == null) {
+      if (linkedNode != null) {
+        _resynthesizeMembers2();
+      }
       if (_unlinkedEnum != null) {
         _resynthesizeMembers();
       }
@@ -3666,6 +4019,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (_unlinkedEnum != null) {
       return _unlinkedEnum.name;
     }
@@ -3716,11 +4072,14 @@
   void createToStringMethodElement() {
     var method = new MethodElementImpl('toString', -1);
     method.isSynthetic = true;
-    if (_unlinkedEnum != null) {
+    if (linkedNode != null || _unlinkedEnum != null) {
       method.returnType = context.typeProvider.stringType;
       method.type = new FunctionTypeImpl(method);
     }
     method.enclosingElement = this;
+    if (linkedNode != null) {
+      method.reference = reference.getChild('@method').getChild('toString');
+    }
     _methods = <MethodElement>[method];
   }
 
@@ -3755,6 +4114,51 @@
         .toList(growable: false);
     createToStringMethodElement();
   }
+
+  void _resynthesizeMembers2() {
+    var fields = <FieldElementImpl>[];
+    var getters = <PropertyAccessorElementImpl>[];
+
+    // Build the 'index' field.
+    {
+      var field = FieldElementImpl('index', -1)
+        ..enclosingElement = this
+        ..isSynthetic = true
+        ..isFinal = true
+        ..type = context.typeProvider.intType;
+      fields.add(field);
+      getters.add(PropertyAccessorElementImpl_ImplicitGetter(field,
+          reference: reference.getChild('@getter').getChild('index'))
+        ..enclosingElement = this);
+    }
+
+    // Build the 'values' field.
+    {
+      var field = ConstFieldElementImpl_EnumValues(this);
+      fields.add(field);
+      getters.add(PropertyAccessorElementImpl_ImplicitGetter(field,
+          reference: reference.getChild('@getter').getChild('values'))
+        ..enclosingElement = this);
+    }
+
+    // Build fields for all enum constants.
+    var constants = linkedNode.enumDeclaration_constants;
+    for (var i = 0; i < constants.length; ++i) {
+      var constant = constants[i];
+      var name = enclosingUnit.linkedContext.getSimpleName(
+        constant.enumConstantDeclaration_name,
+      );
+      var reference = this.reference.getChild('@constant').getChild(name);
+      var field = new ConstFieldElementImpl_EnumValue.forLinkedNode(
+          this, reference, constant, i);
+      fields.add(field);
+      getters.add(field.getter);
+    }
+
+    _fields = fields;
+    _accessors = getters;
+    createToStringMethodElement();
+  }
 }
 
 /// A base class for concrete implementations of an [ExecutableElement].
@@ -3779,14 +4183,17 @@
 
   /// Initialize a newly created executable element to have the given [name] and
   /// [offset].
-  ExecutableElementImpl(String name, int offset)
+  ExecutableElementImpl(String name, int offset, {Reference reference})
       : serializedExecutable = null,
-        super(name, offset);
+        super(name, offset, reference: reference);
 
   /// Initialize using the given linked node.
-  ExecutableElementImpl.forLinkedNode(ElementImpl enclosingElement)
+  ExecutableElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
       : serializedExecutable = null,
-        super.forLinkedNode(enclosingElement);
+        super.forLinkedNode(enclosing, reference, linkedNode) {
+    reference.element = this;
+  }
 
   /// Initialize a newly created executable element to have the given [name].
   ExecutableElementImpl.forNode(Identifier name)
@@ -3827,6 +4234,9 @@
 
   @override
   String get displayName {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.name;
     }
@@ -3835,6 +4245,11 @@
 
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.annotatedNode_comment,
+      );
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.documentationComment?.text;
     }
@@ -3878,6 +4293,9 @@
 
   @override
   bool get isAsynchronous {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isAsynchronous(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.isAsynchronous;
     }
@@ -3886,6 +4304,9 @@
 
   @override
   bool get isExternal {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isExternal(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.isExternal;
     }
@@ -3894,6 +4315,9 @@
 
   @override
   bool get isGenerator {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isGenerator(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.isGenerator;
     }
@@ -3917,6 +4341,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.name;
     }
@@ -3925,6 +4352,12 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getSimpleOffset(
+        linkedNode.namedCompilationUnitMember_name,
+      );
+    }
+
     int offset = super.nameOffset;
     if (offset == 0 && serializedExecutable != null) {
       return serializedExecutable.nameOffset;
@@ -3935,6 +4368,37 @@
   @override
   List<ParameterElement> get parameters {
     if (_parameters == null) {
+      if (linkedNode != null) {
+        var context = enclosingUnit.linkedContext;
+        var containerRef = reference.getChild('@parameter');
+        var formalParameters = context.getFormalParameters(linkedNode);
+        if (formalParameters != null) {
+          _parameters = formalParameters.map((node) {
+            if (node.kind == LinkedNodeKind.defaultFormalParameter) {
+              var parameterNode = node.defaultFormalParameter_parameter;
+              var name = context.getFormalParameterName(parameterNode);
+              var reference = containerRef.getChild(name);
+              reference.node = node;
+              return DefaultParameterElementImpl.forLinkedNode(
+                this,
+                reference,
+                node,
+              );
+            } else {
+              var name = context.getFormalParameterName(node);
+              var reference = containerRef.getChild(name);
+              reference.node = node;
+              return ParameterElementImpl.forLinkedNodeFactory(
+                this,
+                reference,
+                node,
+              );
+            }
+          }).toList();
+        } else {
+          _parameters = const [];
+        }
+      }
       if (serializedExecutable != null) {
         _parameters = ParameterElementImpl.resynthesizeList(
             serializedExecutable.parameters, this);
@@ -3955,6 +4419,10 @@
 
   @override
   DartType get returnType {
+    if (linkedNode != null) {
+      return _returnType ??=
+          enclosingUnit.linkedContext.getReturnType(linkedNode);
+    }
     if (serializedExecutable != null &&
         _declaredReturnType == null &&
         _returnType == null) {
@@ -3976,8 +4444,11 @@
 
   @override
   FunctionType get type {
+    if (linkedNode != null) {
+      return _type ??= new FunctionTypeImpl(this);
+    }
     if (serializedExecutable != null) {
-      _type ??= new FunctionTypeImpl(this);
+      return _type ??= new FunctionTypeImpl(this);
     }
     return _type;
   }
@@ -4228,6 +4699,38 @@
   /// [name] at the given [offset].
   FieldElementImpl(String name, int offset) : super(name, offset);
 
+  FieldElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode) {
+    if (!linkedNode.isSynthetic) {
+      var enclosingRef = enclosing.reference;
+
+      this.getter = PropertyAccessorElementImpl_ImplicitGetter(
+        this,
+        reference: enclosingRef.getChild('@getter').getChild(name),
+      );
+
+      if (!isConst && !isFinal) {
+        this.setter = PropertyAccessorElementImpl_ImplicitSetter(
+          this,
+          reference: enclosingRef.getChild('@setter').getChild(name),
+        );
+      }
+    }
+  }
+
+  factory FieldElementImpl.forLinkedNodeFactory(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode) {
+    if (enclosing.enclosingUnit.linkedContext.isConst(linkedNode)) {
+      return ConstFieldElementImpl.forLinkedNode(
+        enclosing,
+        reference,
+        linkedNode,
+      );
+    }
+    return FieldElementImpl.forLinkedNode(enclosing, reference, linkedNode);
+  }
+
   /// Initialize a newly created field element to have the given [name].
   FieldElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -4275,6 +4778,9 @@
 
   @override
   bool get isStatic {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isStatic(linkedNode);
+    }
     if (_unlinkedVariable != null) {
       return _unlinkedVariable.isStatic;
     }
@@ -4320,6 +4826,10 @@
   FieldFormalParameterElementImpl(String name, int nameOffset)
       : super(name, nameOffset);
 
+  FieldFormalParameterElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created parameter element to have the given [name].
   FieldFormalParameterElementImpl.forNode(Identifier name)
       : super.forNode(name);
@@ -4362,6 +4872,11 @@
 
   @override
   DartType get type {
+    if (linkedNode != null) {
+      return _type ??= enclosingUnit.linkedContext.getType(
+        linkedNode.fieldFormalParameter_type2,
+      );
+    }
     if (unlinkedParam != null &&
         unlinkedParam.type == null &&
         !unlinkedParam.isFunctionTyped &&
@@ -4396,6 +4911,10 @@
   /// [offset].
   FunctionElementImpl(String name, int offset) : super(name, offset);
 
+  FunctionElementImpl.forLinkedNode(CompilationUnitElementImpl enclosingUnit,
+      Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosingUnit, reference, linkedNode);
+
   /// Initialize a newly created function element to have the given [name].
   FunctionElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -4447,6 +4966,16 @@
   ElementKind get kind => ElementKind.FUNCTION;
 
   @override
+  DartType get returnType {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getType(
+        linkedNode.functionDeclaration_returnType2,
+      );
+    }
+    return super.returnType;
+  }
+
+  @override
   SourceRange get visibleRange {
     if (serializedExecutable != null) {
       if (serializedExecutable.visibleLength == 0) {
@@ -4768,6 +5297,13 @@
       : _unlinkedTypedef = null,
         super(name, offset);
 
+  GenericTypeAliasElementImpl.forLinkedNode(
+      CompilationUnitElementImpl enclosingUnit,
+      Reference reference,
+      LinkedNode linkedNode)
+      : _unlinkedTypedef = null,
+        super.forLinkedNode(enclosingUnit, reference, linkedNode);
+
   /// Initialize a newly created type alias element to have the given [name].
   GenericTypeAliasElementImpl.forNode(Identifier name)
       : _unlinkedTypedef = null,
@@ -4799,6 +5335,11 @@
 
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.annotatedNode_comment,
+      );
+    }
     if (_unlinkedTypedef != null) {
       return _unlinkedTypedef.documentationComment?.text;
     }
@@ -4818,31 +5359,53 @@
 
   @override
   GenericFunctionTypeElementImpl get function {
-    if (_function == null) {
-      if (_unlinkedTypedef != null) {
-        if (_unlinkedTypedef.style == TypedefStyle.genericFunctionType) {
-          DartType type = enclosingUnit.resynthesizerContext.resolveTypeRef(
-              this, _unlinkedTypedef.returnType,
-              declaredType: true);
-          if (type is FunctionType) {
-            Element element = type.element;
-            if (element is GenericFunctionTypeElement) {
-              (element as GenericFunctionTypeElementImpl).enclosingElement =
-                  this;
-              _function = element;
-            }
+    if (_function != null) return _function;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      _function = new GenericFunctionTypeElementImpl.forOffset(-1);
+      _function.enclosingElement = this;
+      _function.returnType = context.getType(
+        linkedNode.functionTypeAlias_returnType2,
+      );
+      var containerRef = reference.getChild('@parameter');
+      var formalParameters = context.getFormalParameters(linkedNode);
+      _function.parameters = formalParameters.map((node) {
+        var name = context.getFormalParameterName(node);
+        var reference = containerRef.getChild(name);
+        reference.node = node;
+        return ParameterElementImpl.forLinkedNodeFactory(
+          this,
+          reference,
+          node,
+        );
+      }).toList();
+      return _function;
+    }
+
+    if (_unlinkedTypedef != null) {
+      if (_unlinkedTypedef.style == TypedefStyle.genericFunctionType) {
+        DartType type = enclosingUnit.resynthesizerContext.resolveTypeRef(
+            this, _unlinkedTypedef.returnType,
+            declaredType: true);
+        if (type is FunctionType) {
+          Element element = type.element;
+          if (element is GenericFunctionTypeElement) {
+            (element as GenericFunctionTypeElementImpl).enclosingElement = this;
+            _function = element;
           }
-        } else {
-          _function = new GenericFunctionTypeElementImpl.forOffset(-1);
-          _function.enclosingElement = this;
-          _function.returnType = enclosingUnit.resynthesizerContext
-              .resolveTypeRef(_function, _unlinkedTypedef.returnType,
-                  declaredType: true);
-          _function.parameters = ParameterElementImpl.resynthesizeList(
-              _unlinkedTypedef.parameters, _function);
         }
+      } else {
+        _function = new GenericFunctionTypeElementImpl.forOffset(-1);
+        _function.enclosingElement = this;
+        _function.returnType = enclosingUnit.resynthesizerContext
+            .resolveTypeRef(_function, _unlinkedTypedef.returnType,
+                declaredType: true);
+        _function.parameters = ParameterElementImpl.resynthesizeList(
+            _unlinkedTypedef.parameters, _function);
       }
     }
+
     return _function;
   }
 
@@ -4870,6 +5433,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (_unlinkedTypedef != null) {
       return _unlinkedTypedef.name;
     }
@@ -5087,6 +5653,12 @@
         _linkedDependency = null,
         super(null, offset);
 
+  ImportElementImpl.forLinkedNode(
+      LibraryElementImpl enclosing, LinkedNode linkedNode)
+      : _unlinkedImport = null,
+        _linkedDependency = null,
+        super.forLinkedNode(enclosing, null, linkedNode);
+
   /// Initialize using the given serialized information.
   ImportElementImpl.forSerialized(this._unlinkedImport, this._linkedDependency,
       LibraryElementImpl enclosingLibrary)
@@ -5114,10 +5686,28 @@
   }
 
   @override
+  CompilationUnitElementImpl get enclosingUnit {
+    LibraryElementImpl enclosingLibrary = enclosingElement;
+    return enclosingLibrary._definingCompilationUnit;
+  }
+
+  @override
   String get identifier => "${importedLibrary.identifier}@$nameOffset";
 
   @override
   LibraryElement get importedLibrary {
+    if (_importedLibrary != null) return _importedLibrary;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var relativeUriStr = context.getStringContent(
+        linkedNode.uriBasedDirective_uri,
+      );
+      var relativeUri = Uri.parse(relativeUriStr);
+      var uri = resolveRelativeUri(librarySource.uri, relativeUri);
+      var elementFactory = context.bundleContext.elementFactory;
+      return _importedLibrary = elementFactory.libraryOfUri('$uri');
+    }
     if (_linkedDependency != null) {
       if (_importedLibrary == null) {
         LibraryElementImpl library = enclosingElement as LibraryElementImpl;
@@ -5158,6 +5748,11 @@
 
   @override
   List<ElementAnnotation> get metadata {
+    if (linkedNode != null) {
+      if (_metadata != null) return _metadata;
+      var metadata = enclosingUnit.linkedContext.getMetadataOrEmpty(linkedNode);
+      return _metadata = _buildAnnotations2(enclosingUnit, metadata);
+    }
     if (_metadata == null) {
       if (_unlinkedImport != null) {
         return _metadata = _buildAnnotations(
@@ -5365,6 +5960,9 @@
 
   final UnlinkedUnit unlinkedDefiningUnit;
 
+  /// The context of the defining unit.
+  final LinkedUnitContext linkedContext;
+
   /// The compilation unit that defines this library.
   CompilationUnitElement _definingCompilationUnit;
 
@@ -5419,14 +6017,32 @@
       this.context, this.session, String name, int offset, this.nameLength)
       : resynthesizerContext = null,
         unlinkedDefiningUnit = null,
+        linkedContext = null,
         super(name, offset);
 
+  LibraryElementImpl.forLinkedNode(
+      this.context,
+      this.session,
+      String name,
+      int offset,
+      this.nameLength,
+      this.linkedContext,
+      Reference reference,
+      LinkedNode linkedNode)
+      : resynthesizerContext = null,
+        unlinkedDefiningUnit = null,
+        super.forLinkedNode(null, reference, linkedNode) {
+    _name = name;
+    _nameOffset = offset;
+  }
+
   /// Initialize a newly created library element in the given [context] to have
   /// the given [name].
   LibraryElementImpl.forNode(this.context, this.session, LibraryIdentifier name)
       : nameLength = name != null ? name.length : 0,
         resynthesizerContext = null,
         unlinkedDefiningUnit = null,
+        linkedContext = null,
         super.forNode(name);
 
   /// Initialize using the given serialized information.
@@ -5438,7 +6054,8 @@
       this.nameLength,
       this.resynthesizerContext,
       this.unlinkedDefiningUnit)
-      : super.forSerialized(null) {
+      : linkedContext = null,
+        super.forSerialized(null) {
     _name = name;
     _nameOffset = offset;
     setResolutionCapability(
@@ -5612,6 +6229,13 @@
   @override
   List<ImportElement> get imports {
     if (_imports == null) {
+      if (linkedNode != null) {
+        return _imports = linkedNode.compilationUnit_directives
+            .where((node) => node.kind == LinkedNodeKind.importDirective)
+            .map((node) {
+          return ImportElementImpl.forLinkedNode(this, node);
+        }).toList();
+      }
       if (unlinkedDefiningUnit != null) {
         _imports = buildImportsFromSummary(this, unlinkedDefiningUnit.imports,
             resynthesizerContext.linkedLibrary.importDependencies);
@@ -5779,6 +6403,13 @@
 
   @override
   List<ElementAnnotation> get metadata {
+    if (linkedNode != null) {
+      if (_metadata != null) return _metadata;
+      CompilationUnitElementImpl enclosingUnit = _definingCompilationUnit;
+      var context = enclosingUnit.linkedContext;
+      var metadata = context.getMetadataOrEmpty(linkedNode);
+      return _metadata = _buildAnnotations2(enclosingUnit, metadata);
+    }
     if (_metadata == null) {
       if (unlinkedDefiningUnit != null) {
         _metadata = _buildAnnotations(
@@ -6163,6 +6794,10 @@
   /// given [offset].
   MethodElementImpl(String name, int offset) : super(name, offset);
 
+  MethodElementImpl.forLinkedNode(Reference reference, LinkedNode linkedNode,
+      ClassElementImpl enclosingClass)
+      : super.forLinkedNode(enclosingClass, reference, linkedNode);
+
   /// Initialize a newly created method element to have the given [name].
   MethodElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -6194,6 +6829,14 @@
       super.enclosingElement as ClassElementImpl;
 
   @override
+  bool get isAbstract {
+    if (linkedNode != null) {
+      return !isExternal && enclosingUnit.linkedContext.isAbstract(linkedNode);
+    }
+    return super.isAbstract;
+  }
+
+  @override
   bool get isOperator {
     String name = displayName;
     if (name.isEmpty) {
@@ -6208,6 +6851,9 @@
 
   @override
   bool get isStatic {
+    if (linkedNode != null) {
+      return linkedNode.methodDeclaration_modifierKeyword != 0;
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.isStatic;
     }
@@ -6233,6 +6879,16 @@
   }
 
   @override
+  DartType get returnType {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getType(
+        linkedNode.methodDeclaration_returnType2,
+      );
+    }
+    return super.returnType;
+  }
+
+  @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitMethodElement(this);
 
   @override
@@ -6772,6 +7428,11 @@
       : _unlinkedVariable = null,
         super(name, offset);
 
+  NonParameterVariableElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : _unlinkedVariable = null,
+        super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created variable element to have the given [name].
   NonParameterVariableElementImpl.forNode(Identifier name)
       : _unlinkedVariable = null,
@@ -6800,6 +7461,11 @@
 
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.variableDeclaration_declaration.comment,
+      );
+    }
     if (_unlinkedVariable != null) {
       return _unlinkedVariable.documentationComment?.text;
     }
@@ -6883,6 +7549,11 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getSimpleName(
+        linkedNode.variableDeclaration_name,
+      );
+    }
     if (_unlinkedVariable != null) {
       return _unlinkedVariable.name;
     }
@@ -6891,6 +7562,11 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getSimpleOffset(
+        linkedNode.variableDeclaration_name,
+      );
+    }
     int offset = super.nameOffset;
     if (offset == 0) {
       if (_unlinkedVariable != null) {
@@ -6959,6 +7635,31 @@
       : unlinkedParam = null,
         super(name, nameOffset);
 
+  ParameterElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : unlinkedParam = null,
+        super.forLinkedNode(enclosing, reference, linkedNode);
+
+  factory ParameterElementImpl.forLinkedNodeFactory(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode) {
+    var kind = linkedNode.kind;
+    if (kind == LinkedNodeKind.fieldFormalParameter) {
+      return FieldFormalParameterElementImpl.forLinkedNode(
+        enclosing,
+        reference,
+        linkedNode,
+      );
+    } else if (kind == LinkedNodeKind.simpleFormalParameter) {
+      return ParameterElementImpl.forLinkedNode(
+        enclosing,
+        reference,
+        linkedNode,
+      );
+    } else {
+      throw UnimplementedError('$kind');
+    }
+  }
+
   /// Initialize a newly created parameter element to have the given [name].
   ParameterElementImpl.forNode(Identifier name)
       : unlinkedParam = null,
@@ -7110,6 +7811,13 @@
 
   @override
   bool get isCovariant {
+    if (linkedNode != null) {
+      if (linkedNode.kind == LinkedNodeKind.defaultFormalParameter) {
+        var parameter = linkedNode.defaultFormalParameter_parameter;
+        return parameter.normalFormalParameter_isCovariant;
+      }
+      return linkedNode.normalFormalParameter_isCovariant;
+    }
     if (isExplicitlyCovariant || inheritsCovariant) {
       return true;
     }
@@ -7133,6 +7841,16 @@
 
   @override
   bool get isFinal {
+    if (linkedNode != null) {
+      if (linkedNode.kind == LinkedNodeKind.defaultFormalParameter) {
+        var parameter = linkedNode.defaultFormalParameter_parameter;
+        return parameter.simpleFormalParameter_keyword != 0;
+      }
+      if (linkedNode.kind == LinkedNodeKind.fieldFormalParameter) {
+        return false;
+      }
+      return linkedNode.simpleFormalParameter_keyword != 0;
+    }
     if (unlinkedParam != null) {
       return unlinkedParam.isFinal;
     }
@@ -7168,6 +7886,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (unlinkedParam != null) {
       return unlinkedParam.name;
     }
@@ -7176,6 +7897,12 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getSimpleOffset(
+        linkedNode.normalFormalParameter_identifier,
+      );
+    }
+
     int offset = super.nameOffset;
     if (offset == 0) {
       if (unlinkedParam != null) {
@@ -7193,7 +7920,19 @@
 
   @override
   ParameterKind get parameterKind {
-    if (unlinkedParam != null && _parameterKind == null) {
+    if (_parameterKind != null) return _parameterKind;
+
+    if (linkedNode != null) {
+      if (linkedNode.kind == LinkedNodeKind.defaultFormalParameter) {
+        if (linkedNode.defaultFormalParameter_isNamed) {
+          return _parameterKind = ParameterKind.NAMED;
+        } else {
+          return _parameterKind = ParameterKind.POSITIONAL;
+        }
+      }
+      return _parameterKind = ParameterKind.REQUIRED;
+    }
+    if (unlinkedParam != null) {
       switch (unlinkedParam.kind) {
         case UnlinkedParamKind.named:
           _parameterKind = ParameterKind.NAMED;
@@ -7221,6 +7960,18 @@
 
   @override
   DartType get type {
+    if (linkedNode != null) {
+      if (_type != null) return _type;
+      if (linkedNode.kind == LinkedNodeKind.defaultFormalParameter) {
+        var parameter = linkedNode.defaultFormalParameter_parameter;
+        return _type = enclosingUnit.linkedContext.getType(
+          parameter.simpleFormalParameter_type2,
+        );
+      }
+      return _type = enclosingUnit.linkedContext.getType(
+        linkedNode.simpleFormalParameter_type2,
+      );
+    }
     _resynthesizeTypeAndParameters();
     return super.type;
   }
@@ -7518,6 +8269,10 @@
   /// [name] and [offset].
   PropertyAccessorElementImpl(String name, int offset) : super(name, offset);
 
+  PropertyAccessorElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created property accessor element to have the given
   /// [name].
   PropertyAccessorElementImpl.forNode(Identifier name) : super.forNode(name);
@@ -7529,8 +8284,9 @@
 
   /// Initialize a newly created synthetic property accessor element to be
   /// associated with the given [variable].
-  PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable)
-      : super(variable.name, variable.nameOffset) {
+  PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable,
+      {Reference reference})
+      : super(variable.name, variable.nameOffset, reference: reference) {
     this.variable = variable;
     isStatic = variable.isStatic;
     isSynthetic = true;
@@ -7587,7 +8343,18 @@
   }
 
   @override
+  bool get isAbstract {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isAbstract(linkedNode);
+    }
+    return super.isAbstract;
+  }
+
+  @override
   bool get isGetter {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isGetter(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.kind == UnlinkedExecutableKind.getter;
     }
@@ -7596,6 +8363,9 @@
 
   @override
   bool get isSetter {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isSetter(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.kind == UnlinkedExecutableKind.setter;
     }
@@ -7604,6 +8374,9 @@
 
   @override
   bool get isStatic {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isStatic(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.isStatic ||
           variable is TopLevelVariableElement;
@@ -7627,6 +8400,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.name;
     }
@@ -7673,8 +8449,9 @@
     extends PropertyAccessorElementImpl {
   /// Create the implicit getter and bind it to the [property].
   PropertyAccessorElementImpl_ImplicitGetter(
-      PropertyInducingElementImpl property)
-      : super.forVariable(property) {
+      PropertyInducingElementImpl property,
+      {Reference reference})
+      : super.forVariable(property, reference: reference) {
     property.getter = this;
     enclosingElement = property.enclosingElement;
   }
@@ -7709,8 +8486,9 @@
     extends PropertyAccessorElementImpl {
   /// Create the implicit setter and bind it to the [property].
   PropertyAccessorElementImpl_ImplicitSetter(
-      PropertyInducingElementImpl property)
-      : super.forVariable(property) {
+      PropertyInducingElementImpl property,
+      {Reference reference})
+      : super.forVariable(property, reference: reference) {
     property.setter = this;
     enclosingElement = property.enclosingElement;
   }
@@ -7759,6 +8537,10 @@
   /// [offset].
   PropertyInducingElementImpl(String name, int offset) : super(name, offset);
 
+  PropertyInducingElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created element to have the given [name].
   PropertyInducingElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -7779,6 +8561,12 @@
 
   @override
   DartType get type {
+    if (linkedNode != null) {
+      if (_type != null) return _type;
+      return _type = enclosingUnit.linkedContext.getType(
+        linkedNode.variableDeclaration_type2,
+      );
+    }
     if (isSynthetic && _type == null) {
       if (getter != null) {
         _type = getter.returnType;
@@ -7950,6 +8738,42 @@
   /// the given [name] and [offset].
   TopLevelVariableElementImpl(String name, int offset) : super(name, offset);
 
+  TopLevelVariableElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode) {
+    if (!linkedNode.isSynthetic) {
+      var enclosingRef = enclosing.reference;
+
+      this.getter = PropertyAccessorElementImpl_ImplicitGetter(
+        this,
+        reference: enclosingRef.getChild('@getter').getChild(name),
+      );
+
+      if (!isConst && !isFinal) {
+        this.setter = PropertyAccessorElementImpl_ImplicitSetter(
+          this,
+          reference: enclosingRef.getChild('@setter').getChild(name),
+        );
+      }
+    }
+  }
+
+  factory TopLevelVariableElementImpl.forLinkedNodeFactory(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode) {
+    if (enclosing.enclosingUnit.linkedContext.isConst(linkedNode)) {
+      return ConstTopLevelVariableElementImpl.forLinkedNode(
+        enclosing,
+        reference,
+        linkedNode,
+      );
+    }
+    return TopLevelVariableElementImpl.forLinkedNode(
+      enclosing,
+      reference,
+      linkedNode,
+    );
+  }
+
   /// Initialize a newly created top-level variable element to have the given
   /// [name].
   TopLevelVariableElementImpl.forNode(Identifier name) : super.forNode(name);
@@ -7996,6 +8820,13 @@
       : _unlinkedTypeParam = null,
         super(name, offset);
 
+  TypeParameterElementImpl.forLinkedNode(
+      TypeParameterizedElementMixin enclosing,
+      Reference reference,
+      LinkedNode linkedNode)
+      : _unlinkedTypeParam = null,
+        super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created type parameter element to have the given
   /// [name].
   TypeParameterElementImpl.forNode(Identifier name)
@@ -8016,16 +8847,27 @@
   }
 
   DartType get bound {
-    if (_bound == null) {
-      if (_unlinkedTypeParam != null) {
-        if (_unlinkedTypeParam.bound == null) {
-          return null;
-        }
-        _bound = enclosingUnit.resynthesizerContext.resolveTypeRef(
-            this, _unlinkedTypeParam.bound,
-            instantiateToBoundsAllowed: false, declaredType: true);
+    if (_bound != null) return _bound;
+
+    if (linkedNode != null) {
+      var bound = linkedNode.typeParameter_bound;
+      if (bound != null) {
+        var context = enclosingUnit.linkedContext;
+        return _bound = context.getTypeAnnotationType(bound);
+      } else {
+        return null;
       }
     }
+
+    if (_unlinkedTypeParam != null) {
+      if (_unlinkedTypeParam.bound == null) {
+        return null;
+      }
+      return _bound = enclosingUnit.resynthesizerContext.resolveTypeRef(
+          this, _unlinkedTypeParam.bound,
+          instantiateToBoundsAllowed: false, declaredType: true);
+    }
+
     return _bound;
   }
 
@@ -8067,6 +8909,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (_unlinkedTypeParam != null) {
       return _unlinkedTypeParam.name;
     }
@@ -8083,6 +8928,9 @@
   }
 
   TypeParameterType get type {
+    if (linkedNode != null) {
+      _type ??= new TypeParameterTypeImpl(this);
+    }
     if (_unlinkedTypeParam != null) {
       _type ??= new TypeParameterTypeImpl(this);
     }
@@ -8133,19 +8981,34 @@
 
   @override
   List<TypeParameterElement> get typeParameters {
-    if (_typeParameterElements == null) {
-      List<UnlinkedTypeParam> unlinkedParams = unlinkedTypeParams;
-      if (unlinkedParams != null) {
-        int numTypeParameters = unlinkedParams.length;
-        _typeParameterElements =
-            new List<TypeParameterElement>(numTypeParameters);
-        for (int i = 0; i < numTypeParameters; i++) {
-          _typeParameterElements[i] =
-              new TypeParameterElementImpl.forSerialized(
-                  unlinkedParams[i], this);
-        }
+    if (_typeParameterElements != null) return _typeParameterElements;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var containerRef = reference.getChild('@typeParameter');
+      var typeParameters = context.getTypeParameters(linkedNode);
+      if (typeParameters == null) {
+        return _typeParameterElements = const [];
+      }
+      return _typeParameterElements = typeParameters.map((node) {
+        var name = context.getSimpleName(node.typeParameter_name);
+        var reference = containerRef.getChild(name);
+        reference.node = node;
+        return TypeParameterElementImpl.forLinkedNode(this, reference, node);
+      }).toList();
+    }
+
+    List<UnlinkedTypeParam> unlinkedParams = unlinkedTypeParams;
+    if (unlinkedParams != null) {
+      int numTypeParameters = unlinkedParams.length;
+      _typeParameterElements =
+          new List<TypeParameterElement>(numTypeParameters);
+      for (int i = 0; i < numTypeParameters; i++) {
+        _typeParameterElements[i] =
+            new TypeParameterElementImpl.forSerialized(unlinkedParams[i], this);
       }
     }
+
     return _typeParameterElements ?? const <TypeParameterElement>[];
   }
 
@@ -8243,6 +9106,10 @@
   /// [offset]. The offset may be `-1` if the element is synthetic.
   UriReferencedElementImpl(String name, int offset) : super(name, offset);
 
+  UriReferencedElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize using the given serialized information.
   UriReferencedElementImpl.forSerialized(ElementImpl enclosingElement)
       : super.forSerialized(enclosingElement);
@@ -8303,6 +9170,10 @@
   /// [offset].
   VariableElementImpl(String name, int offset) : super(name, offset);
 
+  VariableElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created variable element to have the given [name].
   VariableElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -8366,6 +9237,9 @@
 
   @override
   bool get isConst {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isConst(linkedNode);
+    }
     return hasModifier(Modifier.CONST);
   }
 
@@ -8379,6 +9253,9 @@
 
   @override
   bool get isFinal {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isFinal(linkedNode);
+    }
     return hasModifier(Modifier.FINAL);
   }
 
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
index 1d45edd..62e8d17 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -163,6 +163,8 @@
       'EXPECTED_CLASS_MEMBER', "Expected a class member.",
       correction: "Try placing this code inside a class member.");
 
+  static const ParserErrorCode EXPECTED_ELSE_OR_COMMA = _EXPECTED_ELSE_OR_COMMA;
+
   static const ParserErrorCode EXPECTED_EXECUTABLE = const ParserErrorCode(
       'EXPECTED_EXECUTABLE',
       "Expected a method, getter, setter or operator declaration.",
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
index c4a7f45..fd3008b 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -101,6 +101,7 @@
   _STACK_OVERFLOW,
   _MISSING_CATCH_OR_FINALLY,
   _EXPERIMENT_NOT_ENABLED,
+  _EXPECTED_ELSE_OR_COMMA,
 ];
 
 const ParserErrorCode _ABSTRACT_CLASS_MEMBER = const ParserErrorCode(
@@ -239,6 +240,9 @@
     r"An equality expression can't be an operand of another equality expression.",
     correction: "Try re-writing the expression.");
 
+const ParserErrorCode _EXPECTED_ELSE_OR_COMMA = const ParserErrorCode(
+    'EXPECTED_ELSE_OR_COMMA', r"Expected 'else' or comma.");
+
 const ParserErrorCode _EXPECTED_INSTEAD = const ParserErrorCode(
     'EXPECTED_INSTEAD', r"Expected '#string' instead of this.");
 
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index adb3a99..b1161d4 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -213,6 +213,26 @@
           correction: "Try removing the export of one of the libraries, or "
               "explicitly hiding the name in one of the export directives.");
 
+  static const CompileTimeErrorCode AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH =
+      const CompileTimeErrorCode(
+          'AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH',
+          "This literal must be both a map and a set, because some elements "
+          "spread a 'Map' and others spread an 'Iterable', but that isn't "
+          "allowed.",
+          correction:
+              "Try removing or changing some of the elements so that all of "
+              "the elements are consistent.");
+
+  static const CompileTimeErrorCode AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER =
+      const CompileTimeErrorCode(
+          'AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER',
+          "This literal must be either a map or a set, but none of the "
+          "elements have enough type information to know which, and that isn't "
+          "allowed.",
+          correction:
+              "Try adding type arguments to the literal (one for sets, two "
+              "for maps).");
+
   /**
    * 15 Metadata: The constant expression given in an annotation is type checked
    * and evaluated in the scope surrounding the declaration being annotated.
@@ -634,6 +654,14 @@
           correction:
               "Try declaring the field as final, or adding the keyword 'static'.");
 
+  static const CompileTimeErrorCode CONST_SPREAD_EXPECTED_LIST_OR_SET =
+      const CompileTimeErrorCode('CONST_SPREAD_EXPECTED_LIST_OR_SET',
+          "A list or a set is expected in this spread.");
+
+  static const CompileTimeErrorCode CONST_SPREAD_EXPECTED_MAP =
+      const CompileTimeErrorCode(
+          'CONST_SPREAD_EXPECTED_MAP', "A map is expected in this spread.");
+
   /**
    * 12.8 Maps: It is a compile-time error if the key of an entry in a constant
    * map literal is an instance of a class that implements the operator
@@ -973,6 +1001,12 @@
           "The exported library '{0}' can't have a part-of directive.",
           correction: "Try exporting the library that the part is a part of.");
 
+  static const CompileTimeErrorCode EXPRESSION_IN_MAP =
+      const CompileTimeErrorCode(
+          'EXPRESSION_IN_MAP', "Expressions cannot be used in a map literal.",
+          correction:
+              "Try removing the expression or converting it to be a map entry.");
+
   /**
    * 7.9 Superclasses: It is a compile-time error if the extends clause of a
    * class <i>C</i> includes a type expression that does not denote a class
@@ -1691,6 +1725,12 @@
           correction: "Try defining the label, or "
               "correcting the name to match an existing label.");
 
+  static const CompileTimeErrorCode MAP_ENTRY_NOT_IN_MAP =
+      const CompileTimeErrorCode('MAP_ENTRY_NOT_IN_MAP',
+          "Map entries can only be used in a map literal.",
+          correction:
+              "Try converting the collection to a map or removing the map entry.");
+
   /**
    * 7 Classes: It is a compile time error if a class <i>C</i> declares a member
    * with the same name as <i>C</i>.
@@ -2239,6 +2279,14 @@
           "{0} required argument(s) expected, but {1} found.",
           correction: "Try adding the missing arguments.");
 
+  static const CompileTimeErrorCode NOT_ITERABLE_SPREAD =
+      const CompileTimeErrorCode('NOT_ITERABLE_SPREAD',
+          "Spread elements in list or set literals must implement 'Iterable'.");
+
+  static const CompileTimeErrorCode NOT_MAP_SPREAD = const CompileTimeErrorCode(
+      'NOT_MAP_SPREAD',
+      "Spread elements in map literals must implement 'Map'.");
+
   /**
    * 7.6.1 Generative Constructors: Let <i>C</i> be the class in which the
    * superinitializer appears and let <i>S</i> be the superclass of <i>C</i>.
diff --git a/pkg/analyzer/lib/src/error/literal_element_verifier.dart b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
new file mode 100644
index 0000000..29b65b9
--- /dev/null
+++ b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
@@ -0,0 +1,203 @@
+// Copyright (c) 2019, 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 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+/// Verifier for [CollectionElement]s in list, set, or map literals.
+class LiteralElementVerifier {
+  final TypeProvider typeProvider;
+  final TypeSystem typeSystem;
+  final ErrorReporter errorReporter;
+  final bool Function(Expression) checkForUseOfVoidResult;
+
+  final bool forList;
+  final bool forSet;
+  final DartType elementType;
+
+  final bool forMap;
+  final DartType mapKeyType;
+  final DartType mapValueType;
+
+  LiteralElementVerifier(
+    this.typeProvider,
+    this.typeSystem,
+    this.errorReporter,
+    this.checkForUseOfVoidResult, {
+    this.forList = false,
+    this.forSet = false,
+    this.elementType,
+    this.forMap = false,
+    this.mapKeyType,
+    this.mapValueType,
+  });
+
+  void verify(CollectionElement element) {
+    _verifyElement(element);
+  }
+
+  /// Check that the given [type] is assignable to the [elementType], otherwise
+  /// report the list or set error on the [errorNode].
+  void _checkAssignableToElementType(DartType type, AstNode errorNode) {
+    if (!typeSystem.isAssignableTo(type, elementType)) {
+      var errorCode = forList
+          ? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+          : StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
+      errorReporter.reportTypeErrorForNode(
+        errorCode,
+        errorNode,
+        [type, elementType],
+      );
+    }
+  }
+
+  /// Verify that the given [element] can be assigned to the [elementType] of
+  /// the enclosing list, set, of map literal.
+  void _verifyElement(CollectionElement element) {
+    if (element is Expression) {
+      if (forList || forSet) {
+        if (!elementType.isVoid && checkForUseOfVoidResult(element)) {
+          return;
+        }
+        _checkAssignableToElementType(element.staticType, element);
+      } else {
+        errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.EXPRESSION_IN_MAP, element);
+      }
+    } else if (element is ForElement) {
+      _verifyElement(element.body);
+    } else if (element is IfElement) {
+      _verifyElement(element.thenElement);
+      _verifyElement(element.elseElement);
+    } else if (element is MapLiteralEntry) {
+      if (forMap) {
+        _verifyMapLiteralEntry(element);
+      } else {
+        errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP, element);
+      }
+    } else if (element is SpreadElement) {
+      Expression expression = element.expression;
+      if (forList || forSet) {
+        _verifySpreadForListOrSet(expression);
+      } else if (forMap) {
+        _verifySpreadForMap(expression);
+      }
+    }
+  }
+
+  /// Verify that the [entry]'s key and value are assignable to [mapKeyType]
+  /// and [mapValueType].
+  void _verifyMapLiteralEntry(MapLiteralEntry entry) {
+    if (!mapKeyType.isVoid && checkForUseOfVoidResult(entry.key)) {
+      return;
+    }
+
+    if (!mapValueType.isVoid && checkForUseOfVoidResult(entry.value)) {
+      return;
+    }
+
+    var keyType = entry.key.staticType;
+    if (!typeSystem.isAssignableTo(keyType, mapKeyType)) {
+      errorReporter.reportTypeErrorForNode(
+        StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
+        entry.key,
+        [keyType, mapKeyType],
+      );
+    }
+
+    var valueType = entry.value.staticType;
+    if (!typeSystem.isAssignableTo(valueType, mapValueType)) {
+      errorReporter.reportTypeErrorForNode(
+        StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
+        entry.value,
+        [valueType, mapValueType],
+      );
+    }
+  }
+
+  /// Verify that the type of the elements of the given [expression] can be
+  /// assigned to the [elementType] of the enclosing collection.
+  void _verifySpreadForListOrSet(Expression expression) {
+    var expressionType = expression.staticType;
+    if (expressionType.isDynamic) return;
+
+    // TODO(scheglov) Check for non-null-aware spread?
+    if (expressionType.isDartCoreNull) return;
+
+    InterfaceType iterableType;
+    var iterableObjectType = typeProvider.iterableObjectType;
+    if (expressionType is InterfaceTypeImpl &&
+        typeSystem.isSubtypeOf(expressionType, iterableObjectType)) {
+      iterableType = expressionType.asInstanceOf(
+        iterableObjectType.element,
+      );
+    }
+
+    if (iterableType == null) {
+      return errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.NOT_ITERABLE_SPREAD,
+        expression,
+      );
+    }
+
+    var iterableElementType = iterableType.typeArguments[0];
+    if (!typeSystem.isAssignableTo(iterableElementType, elementType)) {
+      var errorCode = forList
+          ? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+          : StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
+      errorReporter.reportTypeErrorForNode(
+        errorCode,
+        expression,
+        [iterableElementType, elementType],
+      );
+    }
+  }
+
+  /// Verify that the [expression] is a subtype of `Map<Object, Object>`, and
+  /// its key and values are assignable to [mapKeyType] and [mapValueType].
+  void _verifySpreadForMap(Expression expression) {
+    var expressionType = expression.staticType;
+    if (expressionType.isDynamic) return;
+
+    // TODO(scheglov) Check for non-null-aware spread?
+    if (expressionType.isDartCoreNull) return;
+
+    InterfaceType mapType;
+    var mapObjectObjectType = typeProvider.mapObjectObjectType;
+    if (expressionType is InterfaceTypeImpl &&
+        typeSystem.isSubtypeOf(expressionType, mapObjectObjectType)) {
+      mapType = expressionType.asInstanceOf(mapObjectObjectType.element);
+    }
+
+    if (mapType == null) {
+      return errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.NOT_MAP_SPREAD,
+        expression,
+      );
+    }
+
+    var keyType = mapType.typeArguments[0];
+    if (!typeSystem.isAssignableTo(keyType, mapKeyType)) {
+      errorReporter.reportTypeErrorForNode(
+        StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
+        expression,
+        [keyType, mapKeyType],
+      );
+    }
+
+    var valueType = mapType.typeArguments[1];
+    if (!typeSystem.isAssignableTo(valueType, mapValueType)) {
+      errorReporter.reportTypeErrorForNode(
+        StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
+        expression,
+        [valueType, mapValueType],
+      );
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 808478c..55671cc 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -25,7 +25,6 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/timestamped_data.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
-import 'package:analyzer/src/plugin/engine_plugin.dart';
 import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:analyzer/src/services/lint.dart';
 import 'package:analyzer/src/summary/api_signature.dart';
@@ -34,8 +33,6 @@
 import 'package:analyzer/src/task/manager.dart';
 import 'package:front_end/src/fasta/scanner/token.dart';
 import 'package:path/path.dart' as pathos;
-import 'package:plugin/manager.dart';
-import 'package:plugin/plugin.dart';
 import 'package:pub_semver/pub_semver.dart';
 
 export 'package:analyzer/error/listener.dart' show RecordingErrorListener;
@@ -747,12 +744,6 @@
   Logger _logger = Logger.NULL;
 
   /**
-   * The plugin that defines the extension points and extensions that are
-   * inherently defined by the analysis engine.
-   */
-  final EnginePlugin enginePlugin = new EnginePlugin();
-
-  /**
    * The instrumentation service that is to be used by this analysis engine.
    */
   InstrumentationService _instrumentationService =
@@ -803,13 +794,6 @@
   }
 
   /**
-   * Return the list of plugins that clients are required to process, either by
-   * creating an [ExtensionManager] or by using the method
-   * [processRequiredPlugins].
-   */
-  List<Plugin> get requiredPlugins => <Plugin>[enginePlugin];
-
-  /**
    * Return the task manager used to manage the tasks used to analyze code.
    */
   TaskManager get taskManager {
@@ -841,12 +825,8 @@
    * plugins. This method can only be used by clients that do not need to
    * process any other plugins.
    */
-  void processRequiredPlugins() {
-    if (enginePlugin.workManagerFactoryExtensionPoint == null) {
-      ExtensionManager manager = new ExtensionManager();
-      manager.processPlugins(requiredPlugins);
-    }
-  }
+  @deprecated
+  void processRequiredPlugins() {}
 
   /**
    * Return `true` if the given [fileName] is an analysis options file.
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 48f58c6..50697a0 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -15,11 +15,13 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/error/literal_element_verifier.dart';
 import 'package:analyzer/src/error/pending_error.dart';
 import 'package:analyzer/src/generated/element_resolver.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -28,7 +30,6 @@
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk, SdkLibrary;
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/task/dart.dart';
 
 /**
  * A visitor used to traverse an AST structure looking for additional errors and
@@ -740,13 +741,6 @@
   }
 
   @override
-  @deprecated
-  void visitForEachStatement(ForEachStatement node) {
-    _checkForInIterable(node);
-    super.visitForEachStatement(node);
-  }
-
-  @override
   void visitFormalParameterList(FormalParameterList node) {
     _checkDuplicateDefinitionInParameterList(node);
     _checkUseOfCovariantInParameters(node);
@@ -773,18 +767,6 @@
   }
 
   @override
-  @deprecated
-  void visitForStatement(ForStatement node) {
-    if (node.condition != null) {
-      _checkForNonBoolCondition(node.condition);
-    }
-    if (node.variables != null) {
-      _checkDuplicateVariables(node.variables);
-    }
-    super.visitForStatement(node);
-  }
-
-  @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
     ExecutableElement functionElement = node.declaredElement;
     if (functionElement != null &&
@@ -913,6 +895,12 @@
   }
 
   @override
+  void visitIfElement(IfElement node) {
+    _checkForNonBoolCondition(node.condition);
+    super.visitIfElement(node);
+  }
+
+  @override
   void visitIfStatement(IfStatement node) {
     _checkForNonBoolCondition(node.condition);
     super.visitIfStatement(node);
@@ -1014,28 +1002,6 @@
   }
 
   @override
-  @deprecated
-  void visitMapLiteral(MapLiteral node) {
-    TypeArgumentList typeArguments = node.typeArguments;
-    if (typeArguments != null) {
-      NodeList<TypeAnnotation> arguments = typeArguments.arguments;
-      if (arguments.isNotEmpty) {
-        if (node.isConst) {
-          _checkForInvalidTypeArgumentInConstTypedLiteral(arguments,
-              CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP);
-        }
-      }
-      _checkTypeArgumentCount(typeArguments, 2,
-          StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS);
-    }
-    _checkForRawTypedLiteral(node);
-    _checkForImplicitDynamicTypedLiteral(node);
-    _checkForMapTypeNotAssignable(node);
-    _checkForNonConstMapAsExpressionStatement(node);
-    super.visitMapLiteral(node);
-  }
-
-  @override
   void visitMethodDeclaration(MethodDeclaration node) {
     ExecutableElement previousFunction = _enclosingFunction;
     try {
@@ -1221,28 +1187,6 @@
   }
 
   @override
-  @deprecated
-  void visitSetLiteral(SetLiteral node) {
-    TypeArgumentList typeArguments = node.typeArguments;
-    if (typeArguments != null) {
-      if (node.isConst) {
-        NodeList<TypeAnnotation> arguments = typeArguments.arguments;
-        if (arguments.isNotEmpty) {
-          _checkForInvalidTypeArgumentInConstTypedLiteral(arguments,
-              CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET);
-        }
-      }
-      _checkTypeArgumentCount(typeArguments, 1,
-          StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS);
-    }
-    _checkForRawTypedLiteral(node);
-    _checkForImplicitDynamicTypedLiteral(node);
-    _checkForSetElementTypeNotAssignable(node);
-
-    super.visitSetLiteral(node);
-  }
-
-  @override
   void visitSetOrMapLiteral(SetOrMapLiteral node) {
     TypeArgumentList typeArguments = node.typeArguments;
     if (node.isMap) {
@@ -1259,7 +1203,7 @@
       }
       _checkForRawTypedLiteral(node);
       _checkForImplicitDynamicTypedLiteral(node);
-      _checkForMapTypeNotAssignable3(node);
+      _checkForMapTypeNotAssignable(node);
       _checkForNonConstMapAsExpressionStatement3(node);
     } else if (node.isSet) {
       if (typeArguments != null) {
@@ -2284,63 +2228,6 @@
   }
 
   /**
-   * Verify that the type of the elements of the given [spreadExpression] (the
-   * [spreadExpressionType]) can be assigned to the element type of the
-   * enclosing collection (the [elementType]). If not, report an error with the
-   * given [errorCode].
-   */
-  void _checkForArgumentTypeNotAssignableInSpread(
-      Expression spreadExpression,
-      DartType spreadExpressionType,
-      DartType elementType,
-      ErrorCode errorCode) {
-    if (spreadExpressionType != null && elementType != null) {
-      if (!elementType.isVoid && _checkForUseOfVoidResult(spreadExpression)) {
-        return;
-      }
-      if (spreadExpressionType is InterfaceType) {
-        if (_typeSystem.isSubtypeOf(
-            spreadExpressionType, _typeProvider.iterableObjectType)) {
-          InterfaceType iterableType =
-              (spreadExpressionType as InterfaceTypeImpl)
-                  .asInstanceOf(_typeProvider.iterableType.element);
-          if (iterableType != null) {
-            // The `iterableType` will be `null` when `spreadExpressionType` is
-            // `Null`. Fall through in that case to perform the default type
-            // check.
-            List<DartType> typeArguments = iterableType.typeArguments;
-            if (typeArguments.length == 1) {
-              _checkForAssignableExpressionAtType(
-                  spreadExpression, typeArguments[0], elementType, errorCode);
-              return;
-            }
-          }
-        } else if (_typeSystem.isSubtypeOf(
-            spreadExpressionType, _typeProvider.mapObjectObjectType)) {
-          // TODO(brianwilkerson) Handle spreads involving maps? This method
-          //  isn't currently called for maps, but might be if it's reworked as
-          //  expected.
-//          InterfaceType mapType =
-//              (spreadExpressionType as InterfaceTypeImpl)
-//                  .asInstanceOf(_typeProvider.mapType.element);
-//          if (mapType != null) {
-//            List<DartType> typeArguments = mapType.typeArguments;
-//            if (typeArguments.length == 2) {
-//              _checkForAssignableExpressionAtType(
-//                  spreadExpression, typeArguments[0], keyType, errorCode);
-//              _checkForAssignableExpressionAtType(
-//                  spreadExpression, typeArguments[1], valueType, errorCode);
-//              return;
-//            }
-//          }
-        }
-      }
-      _checkForAssignableExpressionAtType(
-          spreadExpression, spreadExpressionType, elementType, errorCode);
-    }
-  }
-
-  /**
    * Verify that the given [expression] can be assigned to its corresponding
    * parameters. The [expectedStaticType] is the expected static type.
    *
@@ -2599,34 +2486,6 @@
   }
 
   /**
-   * Verify that the given [element] can be assigned to the [elementType] of the
-   * enclosing list or set literal. Report an error with the given [errorCode]
-   * if not.
-   *
-   * This method corresponds to
-   * [BestPracticesVerifier.checkForArgumentTypeNotAssignableWithExpectedTypes].
-   */
-  void _checkForCollectionElementTypeNotAssignableWithElementType(
-      CollectionElement element, DartType elementType, ErrorCode errorCode) {
-    if (element is ForElement) {
-      _checkForCollectionElementTypeNotAssignableWithElementType(
-          element.body, elementType, errorCode);
-    } else if (element is IfElement) {
-      _checkForCollectionElementTypeNotAssignableWithElementType(
-          element.thenElement, elementType, errorCode);
-      _checkForCollectionElementTypeNotAssignableWithElementType(
-          element.elseElement, elementType, errorCode);
-    } else if (element is Expression) {
-      _checkForArgumentTypeNotAssignable(
-          element, elementType, getStaticType(element), errorCode);
-    } else if (element is SpreadElement) {
-      Expression expression = element.expression;
-      _checkForArgumentTypeNotAssignableInSpread(
-          expression, getStaticType(expression), elementType, errorCode);
-    }
-  }
-
-  /**
    * Verify that the [_enclosingClass] does not have a method and getter pair
    * with the same name on, via inheritance.
    *
@@ -3808,84 +3667,6 @@
   }
 
   /**
-   * Check for a type mis-match between the iterable expression and the
-   * assigned variable in a for-in statement.
-   */
-  @deprecated
-  void _checkForInIterable(ForEachStatement node) {
-    DeclaredIdentifier loopVariable = node.loopVariable;
-
-    // Ignore malformed for statements.
-    if (node.identifier == null && loopVariable == null) {
-      return;
-    }
-
-    if (_checkForNullableDereference(node.iterable)) {
-      return;
-    }
-
-    if (_checkForUseOfVoidResult(node.iterable)) {
-      return;
-    }
-
-    DartType iterableType = getStaticType(node.iterable);
-    if (iterableType.isDynamic) {
-      return;
-    }
-
-    // The type of the loop variable.
-    SimpleIdentifier variable = node.identifier ?? loopVariable.identifier;
-    DartType variableType = getStaticType(variable);
-
-    DartType loopType = node.awaitKeyword != null
-        ? _typeProvider.streamType
-        : _typeProvider.iterableType;
-
-    // Use an explicit string instead of [loopType] to remove the "<E>".
-    String loopTypeName = node.awaitKeyword != null ? "Stream" : "Iterable";
-
-    // The object being iterated has to implement Iterable<T> for some T that
-    // is assignable to the variable's type.
-    // TODO(rnystrom): Move this into mostSpecificTypeArgument()?
-    iterableType = iterableType.resolveToBound(_typeProvider.objectType);
-    DartType bestIterableType =
-        _typeSystem.mostSpecificTypeArgument(iterableType, loopType);
-
-    // Allow it to be a supertype of Iterable<T> (basically just Object) and do
-    // an implicit downcast to Iterable<dynamic>.
-    if (bestIterableType == null) {
-      if (_typeSystem.isSubtypeOf(loopType, iterableType)) {
-        bestIterableType = DynamicTypeImpl.instance;
-      }
-    }
-
-    if (loopVariable != null) {
-      if (loopVariable.isConst) {
-        _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, loopVariable);
-      }
-    } else if (node.identifier != null) {
-      Element variableElement = node.identifier.staticElement;
-      if (variableElement is VariableElement && variableElement.isConst) {
-        _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, node.identifier);
-      }
-    }
-
-    if (bestIterableType == null) {
-      _errorReporter.reportTypeErrorForNode(
-          StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE,
-          node.iterable,
-          [iterableType, loopTypeName]);
-    } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType)) {
-      _errorReporter.reportTypeErrorForNode(
-          StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE,
-          node.iterable,
-          [iterableType, loopTypeName, variableType]);
-    }
-  }
-
-  /**
    * Check that the given [typeReference] is not a type reference and that then
    * the [name] is reference to an instance member.
    *
@@ -4082,131 +3863,20 @@
     DartType listElementType = typeArguments[0];
 
     // Check every list element.
-    bool isConst = literal.isConst;
+    var verifier = LiteralElementVerifier(
+      _typeProvider,
+      _typeSystem,
+      _errorReporter,
+      _checkForUseOfVoidResult,
+      forList: true,
+      elementType: listElementType,
+    );
     for (CollectionElement element in literal.elements2) {
-      if (isConst) {
-        // TODO(paulberry): this error should be based on the actual type of the
-        // list element, not the static type.  See dartbug.com/21119.
-        _checkForCollectionElementTypeNotAssignableWithElementType(
-            element,
-            listElementType,
-            CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE);
-      } else {
-        _checkForCollectionElementTypeNotAssignableWithElementType(
-            element,
-            listElementType,
-            StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE);
-      }
+      verifier.verify(element);
     }
   }
 
-  /**
-   * Verify that the given [element] can be assigned to the [elementType] of the
-   * enclosing list or set literal. Report an error with the given [errorCode]
-   * if not.
-   *
-   * This method corresponds to
-   * [BestPracticesVerifier.checkForArgumentTypeNotAssignableWithExpectedTypes].
-   */
-  void _checkForMapElementTypeNotAssignableWithKeyOrValueType(
-      CollectionElement element,
-      DartType keyType,
-      DartType valueType,
-      ErrorCode keyErrorCode,
-      ErrorCode valueErrorCode) {
-    if (element is ForElement) {
-      _checkForMapElementTypeNotAssignableWithKeyOrValueType(
-          element.body, keyType, valueType, keyErrorCode, valueErrorCode);
-    } else if (element is IfElement) {
-      _checkForMapElementTypeNotAssignableWithKeyOrValueType(
-          element.thenElement,
-          keyType,
-          valueType,
-          keyErrorCode,
-          valueErrorCode);
-      _checkForMapElementTypeNotAssignableWithKeyOrValueType(
-          element.elseElement,
-          keyType,
-          valueType,
-          keyErrorCode,
-          valueErrorCode);
-    } else if (element is MapLiteralEntry) {
-      _checkForArgumentTypeNotAssignableWithExpectedTypes(
-          element.key, keyType, keyErrorCode);
-      _checkForArgumentTypeNotAssignableWithExpectedTypes(
-          element.value, valueType, valueErrorCode);
-    } else if (element is SpreadElement) {
-      Expression expression = element.expression;
-      DartType expressionType = getStaticType(expression);
-      if (expressionType is ParameterizedType) {
-        List<DartType> typeArguments = expressionType.typeArguments;
-        if (typeArguments.length == 2) {
-          _checkForArgumentTypeNotAssignable(
-              expression, keyType, typeArguments[0], keyErrorCode);
-          _checkForArgumentTypeNotAssignable(
-              expression, valueType, typeArguments[1], valueErrorCode);
-        }
-      }
-    }
-  }
-
-  /**
-   * Verify that the key/value of entries of the given map [literal] are
-   * subtypes of the map's static type.
-   *
-   * See [CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE],
-   * [CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE],
-   * [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and
-   * [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE].
-   */
-  @deprecated
-  void _checkForMapTypeNotAssignable(MapLiteral literal) {
-    // Determine the map's key and value types. We base this on the static type
-    // and not the literal's type arguments because in strong mode, the type
-    // arguments may be inferred.
-    DartType mapType = literal.staticType;
-    if (mapType == null) {
-      // This is known to happen when the literal is the default value in an
-      // optional parameter in a generic function type alias.
-      return;
-    }
-    assert(mapType is InterfaceTypeImpl);
-
-    List<DartType> typeArguments = (mapType as InterfaceTypeImpl).typeArguments;
-    assert(typeArguments.length == 2);
-    DartType keyType = typeArguments[0];
-    DartType valueType = typeArguments[1];
-
-    bool isConst = literal.isConst;
-    NodeList<MapLiteralEntry> entries = literal.entries;
-    for (MapLiteralEntry entry in entries) {
-      Expression key = entry.key;
-      Expression value = entry.value;
-      if (isConst) {
-        // TODO(paulberry): this error should be based on the actual type of the
-        // list element, not the static type.  See dartbug.com/21119.
-        _checkForArgumentTypeNotAssignableWithExpectedTypes(key, keyType,
-            CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE);
-        _checkForArgumentTypeNotAssignableWithExpectedTypes(value, valueType,
-            CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE);
-      }
-      _checkForArgumentTypeNotAssignableWithExpectedTypes(
-          key, keyType, StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE);
-      _checkForArgumentTypeNotAssignableWithExpectedTypes(
-          value, valueType, StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE);
-    }
-  }
-
-  /**
-   * Verify that the key/value of entries of the given map [literal] are
-   * subtypes of the map's static type.
-   *
-   * See [CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE],
-   * [CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE],
-   * [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and
-   * [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE].
-   */
-  void _checkForMapTypeNotAssignable3(SetOrMapLiteral literal) {
+  void _checkForMapTypeNotAssignable(SetOrMapLiteral literal) {
     // Determine the map's key and value types. We base this on the static type
     // and not the literal's type arguments because in strong mode, the type
     // arguments may be inferred.
@@ -4227,26 +3897,17 @@
       DartType keyType = typeArguments[0];
       DartType valueType = typeArguments[1];
 
-      bool isConst = literal.isConst;
-      NodeList<CollectionElement> entries = literal.elements2;
-      for (CollectionElement entry in entries) {
-        if (isConst) {
-          // TODO(paulberry): this error should be based on the actual type of
-          //  the map entries, not the static type.  See dartbug.com/21119.
-          _checkForMapElementTypeNotAssignableWithKeyOrValueType(
-              entry,
-              keyType,
-              valueType,
-              CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
-              CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE);
-        } else {
-          _checkForMapElementTypeNotAssignableWithKeyOrValueType(
-              entry,
-              keyType,
-              valueType,
-              StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
-              StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE);
-        }
+      var verifier = LiteralElementVerifier(
+        _typeProvider,
+        _typeSystem,
+        _errorReporter,
+        _checkForUseOfVoidResult,
+        forMap: true,
+        mapKeyType: keyType,
+        mapValueType: valueType,
+      );
+      for (CollectionElement element in literal.elements2) {
+        verifier.verify(element);
       }
     }
   }
@@ -4815,38 +4476,6 @@
    *
    * See [CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT].
    */
-  @deprecated
-  void _checkForNonConstMapAsExpressionStatement(MapLiteral literal) {
-    // "const"
-    if (literal.constKeyword != null) {
-      return;
-    }
-    // has type arguments
-    if (literal.typeArguments != null) {
-      return;
-    }
-    // prepare statement
-    Statement statement = literal.thisOrAncestorOfType<ExpressionStatement>();
-    if (statement == null) {
-      return;
-    }
-    // OK, statement does not start with map
-    if (!identical(statement.beginToken, literal.beginToken)) {
-      return;
-    }
-
-    _errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT, literal);
-  }
-
-  /**
-   * Verify the given map [literal] either:
-   * * has `const modifier`
-   * * has explicit type arguments
-   * * is not start of the statement
-   *
-   * See [CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT].
-   */
   void _checkForNonConstMapAsExpressionStatement3(SetOrMapLiteral literal) {
     // "const"
     if (literal.constKeyword != null) {
@@ -5475,42 +5104,6 @@
    * See [CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE], and
    * [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE].
    */
-  @deprecated
-  void _checkForSetElementTypeNotAssignable(SetLiteral literal) {
-    // Determine the list's element type. We base this on the static type and
-    // not the literal's type arguments because in strong mode, the type
-    // arguments may be inferred.
-    DartType setType = literal.staticType;
-    assert(setType is InterfaceTypeImpl);
-
-    List<DartType> typeArguments = (setType as InterfaceTypeImpl).typeArguments;
-    assert(typeArguments.length == 1);
-
-    DartType setElementType = typeArguments[0];
-
-    // Check every set element.
-    bool isConst = literal.isConst;
-    for (Expression element in literal.elements) {
-      if (isConst) {
-        // TODO(paulberry): this error should be based on the actual type of the
-        // element, not the static type.  See dartbug.com/21119.
-        _checkForArgumentTypeNotAssignableWithExpectedTypes(
-            element,
-            setElementType,
-            CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE);
-      }
-      _checkForArgumentTypeNotAssignableWithExpectedTypes(element,
-          setElementType, StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE);
-    }
-  }
-
-  /**
-   * Verify that the elements in the given set [literal] are subtypes of the
-   * set's static type.
-   *
-   * See [CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE], and
-   * [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE].
-   */
   void _checkForSetElementTypeNotAssignable3(SetOrMapLiteral literal) {
     // Determine the set's element type. We base this on the static type and
     // not the literal's type arguments because in strong mode, the type
@@ -5527,21 +5120,16 @@
       DartType setElementType = typeArguments[0];
 
       // Check every set element.
-      bool isConst = literal.isConst;
+      var verifier = LiteralElementVerifier(
+        _typeProvider,
+        _typeSystem,
+        _errorReporter,
+        _checkForUseOfVoidResult,
+        forSet: true,
+        elementType: setElementType,
+      );
       for (CollectionElement element in literal.elements2) {
-        if (isConst) {
-          // TODO(paulberry): this error should be based on the actual type of
-          //  the element, not the static type.  See dartbug.com/21119.
-          _checkForCollectionElementTypeNotAssignableWithElementType(
-              element,
-              setElementType,
-              CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE);
-        } else {
-          _checkForCollectionElementTypeNotAssignableWithElementType(
-              element,
-              setElementType,
-              StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE);
-        }
+        verifier.verify(element);
       }
     }
   }
@@ -6918,6 +6506,7 @@
  */
 class _UninstantiatedBoundChecker extends RecursiveAstVisitor {
   final ErrorReporter _errorReporter;
+
   _UninstantiatedBoundChecker(this._errorReporter);
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 5ecd8d4..cd39326 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -3675,8 +3675,8 @@
   ///
   ///     mapLiteral ::=
   ///         'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
-  MapLiteral // ignore: deprecated_member_use_from_same_package
-      parseMapLiteral(Token modifier, TypeArgumentList typeArguments) {
+  SetOrMapLiteral parseMapLiteral(
+      Token modifier, TypeArgumentList typeArguments) {
     Token leftBracket = getAndAdvance();
     if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
       // ignore: deprecated_member_use_from_same_package
@@ -4032,8 +4032,7 @@
         _tokenMatchesKeyword(_peek(), Keyword.FOR)) {
       Token awaitToken = _currentToken;
       Statement statement = parseForStatement();
-      // ignore: deprecated_member_use_from_same_package
-      if (statement is! ForStatement) {
+      if (!(statement is ForStatement2 && statement.forLoopParts is ForParts)) {
         _reportErrorForToken(
             CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT, awaitToken);
       }
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 7891289..88fce5b 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -1135,8 +1135,6 @@
     if (parent is IfStatement && parent.condition == childOfParent ||
         parent is ForPartsWithDeclarations &&
             parent.condition == childOfParent ||
-        // ignore: deprecated_member_use_from_same_package
-        parent is ForStatement && parent.condition == childOfParent ||
         parent is DoStatement && parent.condition == childOfParent ||
         parent is WhileStatement && parent.condition == childOfParent ||
         parent is ConditionalExpression && parent.condition == childOfParent ||
@@ -3540,11 +3538,6 @@
   }
 
   @override
-  void visitNode(AstNode node) {
-    super.visitNode(node);
-  }
-
-  @override
   void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
     _addStaticVariables(node.variables.variables);
     super.visitTopLevelVariableDeclaration(node);
@@ -3670,6 +3663,8 @@
    */
   final InheritanceManager2 inheritance;
 
+  final AnalysisOptionsImpl _analysisOptions;
+
   /// The object used to resolve the element associated with the current node.
   ElementResolver elementResolver;
 
@@ -3736,13 +3731,14 @@
       {Scope nameScope,
       bool propagateTypes: true,
       reportConstEvaluationErrors: true})
-      : super(definingLibrary, source, typeProvider, errorListener,
+      : _analysisOptions = definingLibrary.context.analysisOptions,
+        super(definingLibrary, source, typeProvider, errorListener,
             nameScope: nameScope) {
-    AnalysisOptions options = definingLibrary.context.analysisOptions;
     this.elementResolver = new ElementResolver(this,
         reportConstEvaluationErrors: reportConstEvaluationErrors);
     this.typeSystem = definingLibrary.context.typeSystem;
     bool strongModeHints = false;
+    AnalysisOptions options = _analysisOptions;
     if (options is AnalysisOptionsImpl) {
       strongModeHints = options.strongModeHints;
     }
@@ -4250,6 +4246,7 @@
         resolutionMap.elementDeclaredByFormalParameter(node.parameter)?.type);
     super.visitDefaultFormalParameter(node);
     ParameterElement element = node.declaredElement;
+
     if (element.initializer != null && node.defaultValue != null) {
       (element.initializer as FunctionElementImpl).returnType =
           node.defaultValue.staticType;
@@ -4328,52 +4325,7 @@
   }
 
   @override
-  @deprecated
-  void visitForEachStatementInScope(ForEachStatement node) {
-    Expression iterable = node.iterable;
-    DeclaredIdentifier loopVariable = node.loopVariable;
-    SimpleIdentifier identifier = node.identifier;
-
-    identifier?.accept(this);
-
-    DartType valueType;
-    if (loopVariable != null) {
-      TypeAnnotation typeAnnotation = loopVariable.type;
-      valueType = typeAnnotation?.type ?? UnknownInferredType.instance;
-    }
-    if (identifier != null) {
-      Element element = identifier.staticElement;
-      if (element is VariableElement) {
-        valueType = element.type;
-      } else if (element is PropertyAccessorElement) {
-        if (element.parameters.isNotEmpty) {
-          valueType = element.parameters[0].type;
-        }
-      }
-    }
-    if (valueType != null) {
-      InterfaceType targetType = (node.awaitKeyword == null)
-          ? typeProvider.iterableType
-          : typeProvider.streamType;
-      InferenceContext.setType(iterable, targetType.instantiate([valueType]));
-    }
-
-    //
-    // We visit the iterator before the loop variable because the loop variable
-    // cannot be in scope while visiting the iterator.
-    //
-    iterable?.accept(this);
-    loopVariable?.accept(this);
-    Statement body = node.body;
-    if (body != null) {
-      visitStatementInScope(body);
-    }
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
-  }
-
-  @override
-  void visitForElement(ForElement node) {
+  void visitForElementInScope(ForElement node) {
     ForLoopParts forLoopParts = node.forLoopParts;
     if (forLoopParts is ForParts) {
       if (forLoopParts is ForPartsWithDeclarations) {
@@ -4485,17 +4437,6 @@
   }
 
   @override
-  @deprecated
-  void visitForStatementInScope(ForStatement node) {
-    node.variables?.accept(this);
-    node.initialization?.accept(this);
-    InferenceContext.setType(node.condition, typeProvider.boolType);
-    node.condition?.accept(this);
-    visitStatementInScope(node.body);
-    node.updaters.accept(this);
-  }
-
-  @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
     ExecutableElement outerFunction = _enclosingFunction;
     FunctionBody outerFunctionBody = _currentFunctionBody;
@@ -4573,9 +4514,6 @@
   }
 
   @override
-  void visitGenericFunctionType(GenericFunctionType node) {}
-
-  @override
   void visitGenericTypeAliasInFunctionScope(GenericTypeAlias node) {
     super.visitGenericTypeAliasInFunctionScope(node);
     safelyVisitComment(node.documentationComment);
@@ -4695,40 +4633,6 @@
   }
 
   @override
-  @deprecated
-  void visitMapLiteral(MapLiteral node) {
-    InterfaceType mapT;
-    if (node.typeArguments != null) {
-      var targs = node.typeArguments.arguments.map((t) => t.type).toList();
-      if (targs.length == 2 && targs.any((t) => !t.isDynamic)) {
-        mapT = typeProvider.mapType.instantiate([targs[0], targs[1]]);
-      }
-    } else {
-      mapT = typeAnalyzer.inferMapType(node, downwards: true);
-      if (mapT != null &&
-          node.typeArguments == null &&
-          node.entries.isEmpty &&
-          typeSystem.isAssignableTo(typeProvider.iterableObjectType, mapT) &&
-          !typeSystem.isAssignableTo(typeProvider.mapObjectObjectType, mapT)) {
-        // The node is really an empty set literal with no type arguments, so
-        // don't try to visit the replaced map literal.
-        return;
-      }
-    }
-    if (mapT != null) {
-      DartType kType = mapT.typeArguments[0];
-      DartType vType = mapT.typeArguments[1];
-      for (MapLiteralEntry entry in node.entries) {
-        InferenceContext.setType(entry.key, kType);
-        InferenceContext.setType(entry.value, vType);
-      }
-      InferenceContext.setType(node, mapT);
-    } else {
-      InferenceContext.clearType(node);
-    }
-    visitNode(node);
-  }
-
   @override
   void visitMethodDeclaration(MethodDeclaration node) {
     ExecutableElement outerFunction = _enclosingFunction;
@@ -4863,38 +4767,31 @@
   }
 
   @override
-  @deprecated
-  void visitSetLiteral(SetLiteral node) {
-    InterfaceType setT;
-
-    TypeArgumentList typeArguments = node.typeArguments;
-    if (typeArguments != null) {
-      if (typeArguments.length == 1) {
-        DartType elementType = typeArguments.arguments[0].type;
-        if (!elementType.isDynamic) {
-          setT = typeProvider.setType.instantiate([elementType]);
-        }
-      }
-    } else {
-      setT = typeAnalyzer.inferSetType(node, downwards: true);
-    }
-    if (setT != null) {
-      DartType eType = setT.typeArguments[0];
-      for (Expression child in node.elements) {
-        InferenceContext.setType(child, eType);
-      }
-      InferenceContext.setType(node, setT);
-    } else {
-      InferenceContext.clearType(node);
-    }
-    visitNode(node);
-  }
-
-  @override
   void visitSetOrMapLiteral(SetOrMapLiteral node) {
-    DartType literalType = _computeContextType(node);
-    // TODO(brianwilkerson) Determine whether we need special handling for type
-    // parameter types. (E-mail sent.)
+    var typeArguments = node.typeArguments?.arguments;
+    InterfaceType literalType;
+    var literalResolution = _computeSetOrMapResolution(node);
+    if (literalResolution.kind == _LiteralResolutionKind.set) {
+      if (typeArguments != null && typeArguments.length == 1) {
+        var elementType = typeArguments[0].type;
+        literalType = typeProvider.setType.instantiate([elementType]);
+      } else {
+        literalType = typeAnalyzer.inferSetTypeDownwards(
+            node, literalResolution.contextType);
+      }
+    } else if (literalResolution.kind == _LiteralResolutionKind.map) {
+      if (typeArguments != null && typeArguments.length == 2) {
+        var keyType = typeArguments[0].type;
+        var valueType = typeArguments[1].type;
+        literalType = typeProvider.mapType.instantiate([keyType, valueType]);
+      } else {
+        literalType = typeAnalyzer.inferMapTypeDownwards(
+            node, literalResolution.contextType);
+      }
+    } else {
+      assert(literalResolution.kind == _LiteralResolutionKind.ambiguous);
+      literalType = null;
+    }
     if (literalType is InterfaceType) {
       List<DartType> typeArguments = literalType.typeArguments;
       if (typeArguments.length == 1) {
@@ -4903,15 +4800,34 @@
             typeProvider.iterableType.instantiate([elementType]);
         _pushCollectionTypesDownToAll(node.elements2,
             elementType: elementType, iterableType: iterableType);
+        if (!_analysisOptions.experimentStatus.spread_collections &&
+            !_analysisOptions.experimentStatus.control_flow_collections &&
+            node.elements2.isEmpty &&
+            node.typeArguments == null &&
+            node.isMap) {
+          // The node is really an empty set literal with no type arguments.
+          // Rewrite the AST.
+          // ignore: deprecated_member_use_from_same_package
+          SetOrMapLiteral setLiteral = new AstFactoryImpl().setLiteral(
+              node.constKeyword,
+              null,
+              node.leftBracket,
+              null,
+              node.rightBracket);
+          InferenceContext.setType(
+              setLiteral, InferenceContext.getContext(node));
+          NodeReplacer.replace(node, setLiteral);
+          node = setLiteral;
+        }
       } else if (typeArguments.length == 2) {
         DartType keyType = typeArguments[0];
         DartType valueType = typeArguments[1];
         _pushCollectionTypesDownToAll(node.elements2,
             iterableType: literalType, keyType: keyType, valueType: valueType);
       }
-      InferenceContext.setType(node, literalType);
+      (node as SetOrMapLiteralImpl).contextType = literalType;
     } else {
-      InferenceContext.clearType(node);
+      (node as SetOrMapLiteralImpl).contextType = null;
     }
     super.visitSetOrMapLiteral(node);
   }
@@ -5076,59 +4992,6 @@
     }
   }
 
-  /// Compute the context type for the given set or map [literal].
-  DartType _computeContextType(SetOrMapLiteral literal) {
-    _LiteralResolution typeArgumentsResolution =
-        _fromTypeArguments(literal.typeArguments);
-    DartType contextType = InferenceContext.getContext(literal);
-    _LiteralResolution contextResolution = _fromContextType(contextType);
-    _LeafElements elementCounts = new _LeafElements(literal.elements2);
-    _LiteralResolution elementResolution = elementCounts.resolution;
-
-    List<_LiteralResolution> unambiguousResolutions = [];
-    Set<_LiteralResolutionKind> kinds = new Set<_LiteralResolutionKind>();
-    if (typeArgumentsResolution.kind != _LiteralResolutionKind.ambiguous) {
-      unambiguousResolutions.add(typeArgumentsResolution);
-      kinds.add(typeArgumentsResolution.kind);
-    }
-    if (contextResolution.kind != _LiteralResolutionKind.ambiguous) {
-      unambiguousResolutions.add(contextResolution);
-      kinds.add(contextResolution.kind);
-    }
-    if (elementResolution.kind != _LiteralResolutionKind.ambiguous) {
-      unambiguousResolutions.add(elementResolution);
-      kinds.add(elementResolution.kind);
-    }
-
-    if (kinds.length == 2) {
-      // It looks like it needs to be both a map and a set. Attempt to recover.
-      if (elementResolution.kind == _LiteralResolutionKind.ambiguous &&
-          elementResolution.contextType != null) {
-        return elementResolution.contextType;
-      } else if (typeArgumentsResolution.kind !=
-              _LiteralResolutionKind.ambiguous &&
-          typeArgumentsResolution.contextType != null) {
-        return typeArgumentsResolution.contextType;
-      } else if (contextResolution.kind != _LiteralResolutionKind.ambiguous &&
-          contextResolution.contextType != null) {
-        return contextResolution.contextType;
-      }
-    } else if (unambiguousResolutions.length >= 2) {
-      // If there are three resolutions, the last resolution is guaranteed to be
-      // from the elements, which always has a context type of `null` (when it
-      // is not ambiguous). So, whether there are 2 or 3 resolutions only the
-      // first two are potentially interesting.
-      return unambiguousResolutions[0].contextType ??
-          unambiguousResolutions[1].contextType;
-    } else if (unambiguousResolutions.length == 1) {
-      return unambiguousResolutions[0].contextType;
-    } else if (literal.elements2.isEmpty) {
-      return typeProvider.mapType
-          .instantiate([typeProvider.dynamicType, typeProvider.dynamicType]);
-    }
-    return null;
-  }
-
   /// Given the declared return type of a function, compute the type of the
   /// values which should be returned or yielded as appropriate.  If a type
   /// cannot be computed from the declared return type, return null.
@@ -5160,6 +5023,62 @@
     return declaredType;
   }
 
+  /// Compute the context type for the given set or map [literal].
+  _LiteralResolution _computeSetOrMapResolution(SetOrMapLiteral literal) {
+    _LiteralResolution typeArgumentsResolution =
+        _fromTypeArguments(literal.typeArguments);
+    DartType contextType = InferenceContext.getContext(literal);
+    _LiteralResolution contextResolution = _fromContextType(contextType);
+    _LeafElements elementCounts = new _LeafElements(literal.elements2);
+    _LiteralResolution elementResolution = elementCounts.resolution;
+
+    List<_LiteralResolution> unambiguousResolutions = [];
+    Set<_LiteralResolutionKind> kinds = new Set<_LiteralResolutionKind>();
+    if (typeArgumentsResolution.kind != _LiteralResolutionKind.ambiguous) {
+      unambiguousResolutions.add(typeArgumentsResolution);
+      kinds.add(typeArgumentsResolution.kind);
+    }
+    if (contextResolution.kind != _LiteralResolutionKind.ambiguous) {
+      unambiguousResolutions.add(contextResolution);
+      kinds.add(contextResolution.kind);
+    }
+    if (elementResolution.kind != _LiteralResolutionKind.ambiguous) {
+      unambiguousResolutions.add(elementResolution);
+      kinds.add(elementResolution.kind);
+    }
+
+    if (kinds.length == 2) {
+      // It looks like it needs to be both a map and a set. Attempt to recover.
+      if (elementResolution.kind == _LiteralResolutionKind.ambiguous &&
+          elementResolution.contextType != null) {
+        return elementResolution;
+      } else if (typeArgumentsResolution.kind !=
+              _LiteralResolutionKind.ambiguous &&
+          typeArgumentsResolution.contextType != null) {
+        return typeArgumentsResolution;
+      } else if (contextResolution.kind != _LiteralResolutionKind.ambiguous &&
+          contextResolution.contextType != null) {
+        return contextResolution;
+      }
+    } else if (unambiguousResolutions.length >= 2) {
+      // If there are three resolutions, the last resolution is guaranteed to be
+      // from the elements, which always has a context type of `null` (when it
+      // is not ambiguous). So, whether there are 2 or 3 resolutions only the
+      // first two are potentially interesting.
+      return unambiguousResolutions[0].contextType == null
+          ? unambiguousResolutions[1]
+          : unambiguousResolutions[0];
+    } else if (unambiguousResolutions.length == 1) {
+      return unambiguousResolutions[0];
+    } else if (literal.elements2.isEmpty) {
+      return _LiteralResolution(
+          _LiteralResolutionKind.map,
+          typeProvider.mapType.instantiate(
+              [typeProvider.dynamicType, typeProvider.dynamicType]));
+    }
+    return _LiteralResolution(_LiteralResolutionKind.ambiguous, null);
+  }
+
   /// Return a newly created cloner that can be used to clone constant
   /// expressions.
   ConstantAstCloner _createCloner() {
@@ -5196,16 +5115,14 @@
       DartType unwrappedContextType = unwrap(contextType);
       // TODO(brianwilkerson) Find out what the "greatest closure" is and use that
       // where [unwrappedContextType] is used below.
-      if (typeSystem.isAssignableTo(
-              typeProvider.iterableObjectType, unwrappedContextType) &&
-          !typeSystem.isAssignableTo(
-              typeProvider.mapObjectObjectType, unwrappedContextType)) {
+      bool isIterable = typeSystem.isSubtypeOf(
+          unwrappedContextType, typeProvider.iterableObjectType);
+      bool isMap = typeSystem.isSubtypeOf(
+          unwrappedContextType, typeProvider.mapObjectObjectType);
+      if (isIterable && !isMap) {
         return _LiteralResolution(
             _LiteralResolutionKind.set, unwrappedContextType);
-      } else if (typeSystem.isAssignableTo(
-              typeProvider.mapObjectObjectType, unwrappedContextType) &&
-          !typeSystem.isAssignableTo(
-              typeProvider.iterableObjectType, unwrappedContextType)) {
+      } else if (isMap && !isIterable) {
         return _LiteralResolution(
             _LiteralResolutionKind.map, unwrappedContextType);
       }
@@ -5871,35 +5788,34 @@
   }
 
   @override
-  @deprecated
-  void visitForEachStatement(ForEachStatement node) {
-    Scope outerNameScope = nameScope;
-    ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
-    try {
-      nameScope = new EnclosedScope(nameScope);
-      _implicitLabelScope = _implicitLabelScope.nest(node);
-      visitForEachStatementInScope(node);
-    } finally {
-      nameScope = outerNameScope;
-      _implicitLabelScope = outerImplicitScope;
-    }
-  }
-
-  /// Visit the given statement after it's scope has been created. This replaces
-  /// the normal call to the inherited visit method so that ResolverVisitor can
-  /// intervene when type propagation is enabled.
-  ///
-  /// @param node the statement to be visited
-  @deprecated
-  void visitForEachStatementInScope(ForEachStatement node) {
+  void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
     //
     // We visit the iterator before the loop variable because the loop variable
     // cannot be in scope while visiting the iterator.
     //
-    node.identifier?.accept(this);
     node.iterable?.accept(this);
     node.loopVariable?.accept(this);
-    visitStatementInScope(node.body);
+  }
+
+  @override
+  void visitForElement(ForElement node) {
+    Scope outerNameScope = nameScope;
+    try {
+      nameScope = new EnclosedScope(nameScope);
+      visitForElementInScope(node);
+    } finally {
+      nameScope = outerNameScope;
+    }
+  }
+
+  /// Visit the given [node] after it's scope has been created. This replaces
+  /// the normal call to the inherited visit method so that ResolverVisitor can
+  /// intervene when type propagation is enabled.
+  void visitForElementInScope(ForElement node) {
+    // TODO(brianwilkerson) Investigate the possibility of removing the
+    //  visit...InScope methods now that type propagation is no longer done.
+    node.forLoopParts?.accept(this);
+    node.body?.accept(this);
   }
 
   @override
@@ -5919,21 +5835,6 @@
   }
 
   @override
-  @deprecated
-  void visitForStatement(ForStatement node) {
-    Scope outerNameScope = nameScope;
-    ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
-    try {
-      nameScope = new EnclosedScope(nameScope);
-      _implicitLabelScope = _implicitLabelScope.nest(node);
-      visitForStatementInScope(node);
-    } finally {
-      nameScope = outerNameScope;
-      _implicitLabelScope = outerImplicitScope;
-    }
-  }
-
-  @override
   void visitForStatement2(ForStatement2 node) {
     Scope outerNameScope = nameScope;
     ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
@@ -5957,20 +5858,6 @@
     visitStatementInScope(node.body);
   }
 
-  /// Visit the given statement after it's scope has been created. This replaces
-  /// the normal call to the inherited visit method so that ResolverVisitor can
-  /// intervene when type propagation is enabled.
-  ///
-  /// @param node the statement to be visited
-  @deprecated
-  void visitForStatementInScope(ForStatement node) {
-    node.variables?.accept(this);
-    node.initialization?.accept(this);
-    node.condition?.accept(this);
-    node.updaters.accept(this);
-    visitStatementInScope(node.body);
-  }
-
   @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
     ExecutableElement functionElement = node.declaredElement;
@@ -9063,15 +8950,20 @@
   /// Return `true` if the given collection [element] does not contain any
   /// synthetic tokens.
   bool _isComplete(CollectionElement element) {
-    Token token = element.beginToken;
-    int endOffset = element.endToken.offset;
-    while (token != null && token.offset <= endOffset) {
-      if (token.isSynthetic) {
-        return false;
-      }
-      token = token.next;
-    }
+    // TODO(paulberry,brianwilkerson): the code below doesn't work because it
+    // assumes access to token offsets, which aren't available when working with
+    // expressions resynthesized from summaries.  For now we just assume the
+    // collection element is complete.
     return true;
+//    Token token = element.beginToken;
+//    int endOffset = element.endToken.offset;
+//    while (token != null && token.offset <= endOffset) {
+//      if (token.isSynthetic) {
+//        return false;
+//      }
+//      token = token.next;
+//    }
+//    return true;
   }
 }
 
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 66fe369..377affe 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -10,10 +10,7 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/ast_factory.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
 import 'package:analyzer/src/dart/element/type.dart';
@@ -55,11 +52,6 @@
   DartType _dynamicType;
 
   /**
-   * The status of the active experiments of the current context.
-   */
-  ExperimentStatus _experimentStatus;
-
-  /**
    * True if inference failures should be reported, otherwise false.
    */
   bool _strictInference;
@@ -87,7 +79,6 @@
     _promoteManager = _resolver.promoteManager;
     AnalysisOptionsImpl analysisOptions =
         _resolver.definingLibrary.context.analysisOptions;
-    _experimentStatus = analysisOptions.experimentStatus;
     _strictInference = analysisOptions.strictInference;
   }
 
@@ -189,101 +180,30 @@
     return inferred;
   }
 
-  @deprecated
-  ParameterizedType inferMapType(MapLiteral node, {bool downwards: false}) {
-    DartType contextType = InferenceContext.getContext(node);
-    if (contextType != null && _experimentStatus.set_literals) {
-      DartType unwrap(DartType type) {
-        if (type is InterfaceType &&
-            type.isDartAsyncFutureOr &&
-            type.typeArguments.length == 1) {
-          return unwrap(type.typeArguments[0]);
-        }
-        return type;
-      }
-
-      DartType unwrappedContextType = unwrap(contextType);
-      if (node.typeArguments == null &&
-          node.entries.isEmpty &&
-          _typeSystem.isAssignableTo(
-              _typeProvider.iterableObjectType, unwrappedContextType) &&
-          !_typeSystem.isAssignableTo(
-              _typeProvider.mapObjectObjectType, unwrappedContextType)) {
-        // The node is really an empty set literal with no type arguments.
-        // Rewrite the AST and infer the type of the set as appropriate.
-        SetLiteral setLiteral = new AstFactoryImpl().setLiteral(
-            node.constKeyword, null, node.leftBracket, null, node.rightBracket);
-        InferenceContext.setType(setLiteral, contextType);
-        NodeReplacer.replace(node, setLiteral);
-        DartType type = inferSetType(setLiteral, downwards: downwards);
-        setLiteral.staticType = type;
-        return type;
-      }
-    }
-    List<DartType> elementTypes;
-    List<ParameterElement> parameters;
-    if (downwards) {
-      if (contextType == null) {
-        return null;
-      }
-      elementTypes = [];
-      parameters = [];
-    } else {
-      var keyTypes =
-          node.entries.map((e) => e.key.staticType).where((t) => t != null);
-      var valueTypes =
-          node.entries.map((e) => e.value.staticType).where((t) => t != null);
-      var keyTypeParam = _typeProvider.mapType.typeParameters[0].type;
-      var valueTypeParam = _typeProvider.mapType.typeParameters[1].type;
-      var syntheticKeyParameter = new ParameterElementImpl.synthetic(
-          'key', keyTypeParam, ParameterKind.POSITIONAL);
-      var syntheticValueParameter = new ParameterElementImpl.synthetic(
-          'value', valueTypeParam, ParameterKind.POSITIONAL);
-      parameters = new List.filled(keyTypes.length, syntheticKeyParameter,
-          growable: true)
-        ..addAll(new List.filled(valueTypes.length, syntheticValueParameter));
-      elementTypes = new List<DartType>.from(keyTypes)..addAll(valueTypes);
+  ParameterizedType inferMapTypeDownwards(
+      SetOrMapLiteral node, DartType contextType) {
+    if (contextType == null) {
+      return null;
     }
 
-    // Use both downwards and upwards information to infer the type.
     var ts = _typeSystem as Dart2TypeSystem;
     ParameterizedType inferred = ts.inferGenericFunctionOrType(
-        _typeProvider.mapType, parameters, elementTypes, contextType,
-        downwards: downwards,
+        _typeProvider.mapType, [], [], contextType,
+        downwards: true,
         errorReporter: _resolver.errorReporter,
         errorNode: node);
     return inferred;
   }
 
-  @deprecated
-  DartType inferSetType(SetLiteral node, {bool downwards: false}) {
-    DartType contextType = InferenceContext.getContext(node);
+  DartType inferSetTypeDownwards(SetOrMapLiteral node, DartType contextType) {
+    if (contextType == null) {
+      return null;
+    }
 
     var ts = _typeSystem as Dart2TypeSystem;
-    List<DartType> elementTypes;
-    List<ParameterElement> parameters;
-
-    if (downwards) {
-      if (contextType == null) {
-        return null;
-      }
-
-      elementTypes = [];
-      parameters = [];
-    } else {
-      // Also use upwards information to infer the type.
-      elementTypes = node.elements
-          .map((e) => e.staticType)
-          .where((t) => t != null)
-          .toList();
-      var setTypeParam = _typeProvider.setType.typeParameters[0].type;
-      var syntheticParamElement = new ParameterElementImpl.synthetic(
-          'element', setTypeParam, ParameterKind.POSITIONAL);
-      parameters = new List.filled(elementTypes.length, syntheticParamElement);
-    }
     DartType inferred = ts.inferGenericFunctionOrType<InterfaceType>(
-        _typeProvider.setType, parameters, elementTypes, contextType,
-        downwards: downwards,
+        _typeProvider.setType, [], [], contextType,
+        downwards: true,
         errorReporter: _resolver.errorReporter,
         errorNode: node);
     return inferred;
@@ -704,65 +624,6 @@
   }
 
   /**
-   * The Dart Language Specification, 12.7: <blockquote>The static type of a map literal of the form
-   * <i><b>const</b> &lt;K, V&gt; {k<sub>1</sub>:e<sub>1</sub>, &hellip;,
-   * k<sub>n</sub>:e<sub>n</sub>}</i> or the form <i>&lt;K, V&gt; {k<sub>1</sub>:e<sub>1</sub>,
-   * &hellip;, k<sub>n</sub>:e<sub>n</sub>}</i> is `Map&lt;K, V&gt;`. The static type a map
-   * literal of the form <i><b>const</b> {k<sub>1</sub>:e<sub>1</sub>, &hellip;,
-   * k<sub>n</sub>:e<sub>n</sub>}</i> or the form <i>{k<sub>1</sub>:e<sub>1</sub>, &hellip;,
-   * k<sub>n</sub>:e<sub>n</sub>}</i> is `Map&lt;dynamic, dynamic&gt;`.
-   *
-   * It is a compile-time error if the first type argument to a map literal is not
-   * <i>String</i>.</blockquote>
-   */
-  @override
-  @deprecated
-  void visitMapLiteral(MapLiteral node) {
-    TypeArgumentList typeArguments = node.typeArguments;
-
-    // If we have type arguments, use them
-    if (typeArguments != null) {
-      DartType staticKeyType = _dynamicType;
-      DartType staticValueType = _dynamicType;
-      NodeList<TypeAnnotation> arguments = typeArguments.arguments;
-      if (arguments != null && arguments.length == 2) {
-        DartType entryKeyType = _getType(arguments[0]);
-        if (entryKeyType != null) {
-          staticKeyType = entryKeyType;
-        }
-        DartType entryValueType = _getType(arguments[1]);
-        if (entryValueType != null) {
-          staticValueType = entryValueType;
-        }
-      }
-      _recordStaticType(
-          node,
-          _typeProvider.mapType
-              .instantiate(<DartType>[staticKeyType, staticValueType]));
-      return;
-    }
-
-    DartType mapDynamicType = _typeProvider.mapType
-        .instantiate(<DartType>[_dynamicType, _dynamicType]);
-
-    // If we have no explicit type arguments, try to infer type arguments.
-    ParameterizedType inferred = inferMapType(node);
-
-    if (inferred != mapDynamicType) {
-      // TODO(jmesserly): this results in an "inferred" message even when we
-      // in fact had an error above, because it will still attempt to return
-      // a type. Perhaps we should record inference from TypeSystem if
-      // everything was successful?
-      _resolver.inferenceContext.recordInference(node, inferred);
-      _recordStaticType(node, inferred);
-      return;
-    }
-
-    // If no type arguments and no inference, use dynamic
-    _recordStaticType(node, mapDynamicType);
-  }
-
-  /**
    * The Dart Language Specification, 12.15.1: <blockquote>An ordinary method invocation <i>i</i>
    * has the form <i>o.m(a<sub>1</sub>, &hellip;, a<sub>n</sub>, x<sub>n+1</sub>: a<sub>n+1</sub>,
    * &hellip;, x<sub>n+k</sub>: a<sub>n+k</sub>)</i>.
@@ -1010,66 +871,42 @@
   }
 
   @override
-  @deprecated
-  void visitSetLiteral(SetLiteral node) {
-    TypeArgumentList typeArguments = node.typeArguments;
-
-    // If we have type arguments, use them
-    if (typeArguments != null) {
-      DartType elementType = _dynamicType;
-      NodeList<TypeAnnotation> arguments = typeArguments.arguments;
-      if (arguments != null && arguments.length == 1) {
-        DartType type = _getType(arguments[0]);
-        if (type != null) {
-          elementType = type;
-        }
-      }
-      _recordStaticType(
-          node, _typeProvider.setType.instantiate(<DartType>[elementType]));
-      return;
-    }
-
-    DartType setDynamicType =
-        _typeProvider.setType.instantiate(<DartType>[_dynamicType]);
-
-    // If we have no explicit type arguments, try to infer type arguments.
-    ParameterizedType inferred = inferSetType(node);
-
-    if (inferred != setDynamicType) {
-      // TODO(jmesserly): this results in an "inferred" message even when we
-      // in fact had an error above, because it will still attempt to return
-      // a type. Perhaps we should record inference from TypeSystem if
-      // everything was successful?
-      _resolver.inferenceContext.recordInference(node, inferred);
-      _recordStaticType(node, inferred);
-      return;
-    }
-
-    // If no type arguments and no inference, use dynamic
-    _recordStaticType(node, setDynamicType);
-  }
-
-  @override
   void visitSetOrMapLiteral(SetOrMapLiteral node) {
-    DartType staticType = node.staticType;
-    if (staticType == null) {
-      DartType literalType = _inferSetOrMapLiteralType(node);
-      if (literalType.element == _typeProvider.mapType.element) {
-        (node as SetOrMapLiteralImpl).becomeMap();
-      } else {
-        assert(literalType.element == _typeProvider.setType.element);
-        (node as SetOrMapLiteralImpl).becomeSet();
-      }
-      _resolver.inferenceContext.recordInference(node, literalType);
-      _recordStaticType(node, literalType);
-    } else if (staticType is InterfaceType) {
-      List<DartType> typeArguments = staticType.typeArguments;
+    var typeArguments = node.typeArguments?.arguments;
+
+    // If we have type arguments, use them.
+    // TODO(paulberry): this logic seems redundant with
+    //  ResolverVisitor._fromTypeArguments
+    if (typeArguments != null) {
       if (typeArguments.length == 1) {
         (node as SetOrMapLiteralImpl).becomeSet();
+        var elementType = _getType(typeArguments[0]) ?? _dynamicType;
+        _recordStaticType(
+            node, _typeProvider.setType.instantiate(<DartType>[elementType]));
+        return;
       } else if (typeArguments.length == 2) {
         (node as SetOrMapLiteralImpl).becomeMap();
+        var keyType = _getType(typeArguments[0]) ?? _dynamicType;
+        var valueType = _getType(typeArguments[1]) ?? _dynamicType;
+        _recordStaticType(node,
+            _typeProvider.mapType.instantiate(<DartType>[keyType, valueType]));
+        return;
       }
+      // If we get here, then a nonsense number of type arguments were provided,
+      // so treat it as though no type arguments were provided.
     }
+    DartType literalType = _inferSetOrMapLiteralType(node);
+    if (literalType.isDynamic) {
+      // The literal is ambiguous, and further analysis won't resolve the
+      // ambiguity.  Leave it as neither a set nor a map.
+    } else if (literalType.element == _typeProvider.mapType.element) {
+      (node as SetOrMapLiteralImpl).becomeMap();
+    } else {
+      assert(literalType.element == _typeProvider.setType.element);
+      (node as SetOrMapLiteralImpl).becomeSet();
+    }
+    _resolver.inferenceContext.recordInference(node, literalType);
+    _recordStaticType(node, literalType);
   }
 
   /**
@@ -1283,16 +1120,30 @@
       return _typeSystem.leastUpperBound(thenType, elseType);
     } else if (element is Expression) {
       return element.staticType;
+    } else if (element is MapLiteralEntry) {
+      // This error will be reported elsewhere.
+      return _typeProvider.dynamicType;
     } else if (element is SpreadElement) {
-      DartType collectionType = element.expression.staticType;
-      if (collectionType is ParameterizedType) {
-        List<DartType> typeArguments = collectionType.typeArguments;
-        if (typeArguments.length == 1) {
-          return typeArguments[0];
+      DartType expressionType = element.expression.staticType;
+      bool isNull = expressionType.isDartCoreNull;
+      if (!isNull && expressionType is InterfaceType) {
+        if (_typeSystem.isSubtypeOf(
+            expressionType, _typeProvider.iterableObjectType)) {
+          InterfaceType iterableType = (expressionType as InterfaceTypeImpl)
+              .asInstanceOf(_typeProvider.iterableType.element);
+          return iterableType.typeArguments[0];
         }
+      } else if (expressionType.isDynamic) {
+        return expressionType;
+      } else if (isNull &&
+          element.spreadOperator.type ==
+              TokenType.PERIOD_PERIOD_PERIOD_QUESTION) {
+        return expressionType;
       }
+      // TODO(brianwilkerson) Report this as an error.
+      return _typeProvider.dynamicType;
     }
-    return null;
+    throw StateError('Unhandled element type ${element.runtimeType}');
   }
 
   /**
@@ -1551,7 +1402,7 @@
       }
       _InferredCollectionElementTypeInformation elseType =
           _inferCollectionElementType(element.elseElement);
-      return _InferredCollectionElementTypeInformation.leastUpperBound(
+      return _InferredCollectionElementTypeInformation.forIfElement(
           _typeSystem, thenType, elseType);
     } else if (element is Expression) {
       return _InferredCollectionElementTypeInformation(
@@ -1569,41 +1420,19 @@
             expressionType, _typeProvider.iterableObjectType)) {
           InterfaceType iterableType = (expressionType as InterfaceTypeImpl)
               .asInstanceOf(_typeProvider.iterableType.element);
-          if (iterableType != null) {
-            // The `iterableType` will be `null` when `expressionType` is
-            // `Null`. Fall through in that case to perform the default type
-            // check.
-            List<DartType> typeArguments = iterableType.typeArguments;
-            if (typeArguments.length == 1) {
-              return _InferredCollectionElementTypeInformation(
-                  elementType: typeArguments[0],
-                  keyType: null,
-                  valueType: null);
-            }
-          }
           return _InferredCollectionElementTypeInformation(
-              elementType: _typeProvider.dynamicType,
+              elementType: iterableType.typeArguments[0],
               keyType: null,
               valueType: null);
         } else if (_typeSystem.isSubtypeOf(
             expressionType, _typeProvider.mapObjectObjectType)) {
           InterfaceType mapType = (expressionType as InterfaceTypeImpl)
               .asInstanceOf(_typeProvider.mapType.element);
-          if (mapType != null) {
-            // The `iterableType` will be `null` when `expressionType` is
-            // `Null`. Fall through in that case to perform the default type
-            // check.
-            List<DartType> typeArguments = mapType.typeArguments;
-            if (typeArguments.length == 2) {
-              return _InferredCollectionElementTypeInformation(
-                  elementType: null,
-                  keyType: typeArguments[0],
-                  valueType: typeArguments[1]);
-            }
-          }
-          DartType dynamicType = _typeProvider.dynamicType;
+          List<DartType> typeArguments = mapType.typeArguments;
           return _InferredCollectionElementTypeInformation(
-              elementType: null, keyType: dynamicType, valueType: dynamicType);
+              elementType: null,
+              keyType: typeArguments[0],
+              valueType: typeArguments[1]);
         }
       } else if (expressionType.isDynamic) {
         return _InferredCollectionElementTypeInformation(
@@ -1636,11 +1465,7 @@
       AstNode parent = loopVariable.parent;
       Token awaitKeyword;
       Expression iterable;
-      // ignore: deprecated_member_use_from_same_package
-      if (parent is ForEachStatement) {
-        awaitKeyword = parent.awaitKeyword;
-        iterable = parent.iterable;
-      } else if (parent is ForEachPartsWithDeclaration) {
+      if (parent is ForEachPartsWithDeclaration) {
         AstNode parentParent = parent.parent;
         if (parentParent is ForStatement2Impl) {
           awaitKeyword = parentParent.awaitKeyword;
@@ -1952,11 +1777,10 @@
   }
 
   DartType _inferSetOrMapLiteralType(SetOrMapLiteral literal) {
-    DartType contextType = InferenceContext.getContext(literal);
+    var literalImpl = literal as SetOrMapLiteralImpl;
+    DartType contextType = literalImpl.contextType;
+    literalImpl.contextType = null; // Not needed anymore.
     NodeList<CollectionElement> elements = literal.elements2;
-    if (elements.length < 2 && contextType != null) {
-      return contextType;
-    }
     List<_InferredCollectionElementTypeInformation> inferredTypes = [];
     bool canBeAMap = true;
     bool mustBeAMap = false;
@@ -1976,11 +1800,36 @@
     } else if (canBeAMap && mustBeAMap) {
       return _toMapType(literal, contextType, inferredTypes);
     }
-    if (contextType == null) {
-      DartType dynamicType = _typeProvider.dynamicType;
-      return _typeProvider.mapType.instantiate([dynamicType, dynamicType]);
+    // Note: according to the spec, the following computations should be based
+    // on the greatest closure of the context type (unless the context type is
+    // `?`).  In practice, we can just use the context type directly, because
+    // the only way the greatest closure of the context type could possibly have
+    // a different subtype relationship to `Iterable<Object>` and
+    // `Map<Object, Object>` is if the context type is `?`.
+    bool contextProvidesAmbiguityResolutionClues =
+        contextType != null && contextType is! UnknownInferredType;
+    bool contextIsIterable = contextProvidesAmbiguityResolutionClues &&
+        _typeSystem.isSubtypeOf(contextType, _typeProvider.iterableObjectType);
+    bool contextIsMap = contextProvidesAmbiguityResolutionClues &&
+        _typeSystem.isSubtypeOf(contextType, _typeProvider.mapObjectObjectType);
+    if (contextIsIterable && !contextIsMap) {
+      return _toSetType(literal, contextType, inferredTypes);
+    } else if ((contextIsMap && !contextIsIterable) || elements.isEmpty) {
+      return _toMapType(literal, contextType, inferredTypes);
+    } else {
+      // Ambiguous.  We're not going to get any more information to resolve the
+      // ambiguity.  We don't want to make an arbitrary decision at this point
+      // because it will interfere with future type inference (see
+      // dartbug.com/36210), so we return a type of `dynamic`.
+      if (mustBeAMap && mustBeASet) {
+        _resolver.errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH, literal);
+      } else {
+        _resolver.errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER, literal);
+      }
+      return _typeProvider.dynamicType;
     }
-    return contextType;
   }
 
   /**
@@ -2106,22 +1955,44 @@
   _InferredCollectionElementTypeInformation(
       {this.elementType, this.keyType, this.valueType});
 
-  factory _InferredCollectionElementTypeInformation.leastUpperBound(
-          TypeSystem typeSystem,
-          _InferredCollectionElementTypeInformation first,
-          _InferredCollectionElementTypeInformation second) =>
-      _InferredCollectionElementTypeInformation(
-          elementType: _leastUpperBoundOfTypes(
-              typeSystem, first.elementType, second.elementType),
-          keyType: _leastUpperBoundOfTypes(
-              typeSystem, first.keyType, second.keyType),
-          valueType: _leastUpperBoundOfTypes(
-              typeSystem, first.valueType, second.valueType));
+  factory _InferredCollectionElementTypeInformation.forIfElement(
+      TypeSystem typeSystem,
+      _InferredCollectionElementTypeInformation thenInfo,
+      _InferredCollectionElementTypeInformation elseInfo) {
+    if (thenInfo.isDynamic) {
+      DartType dynamic = thenInfo.elementType;
+      return _InferredCollectionElementTypeInformation(
+          elementType: _dynamicOrNull(elseInfo.elementType, dynamic),
+          keyType: _dynamicOrNull(elseInfo.keyType, dynamic),
+          valueType: _dynamicOrNull(elseInfo.valueType, dynamic));
+    } else if (elseInfo.isDynamic) {
+      DartType dynamic = elseInfo.elementType;
+      return _InferredCollectionElementTypeInformation(
+          elementType: _dynamicOrNull(thenInfo.elementType, dynamic),
+          keyType: _dynamicOrNull(thenInfo.keyType, dynamic),
+          valueType: _dynamicOrNull(thenInfo.valueType, dynamic));
+    }
+    return _InferredCollectionElementTypeInformation(
+        elementType: _leastUpperBoundOfTypes(
+            typeSystem, thenInfo.elementType, elseInfo.elementType),
+        keyType: _leastUpperBoundOfTypes(
+            typeSystem, thenInfo.keyType, elseInfo.keyType),
+        valueType: _leastUpperBoundOfTypes(
+            typeSystem, thenInfo.valueType, elseInfo.valueType));
+  }
 
   bool get canBeAMap => keyType != null || valueType != null;
 
   bool get canBeASet => elementType != null;
 
+  bool get isDynamic =>
+      elementType != null &&
+      elementType.isDynamic &&
+      keyType != null &&
+      keyType.isDynamic &&
+      valueType != null &&
+      valueType.isDynamic;
+
   bool get mustBeAMap => canBeAMap && elementType == null;
 
   bool get mustBeASet => canBeASet && keyType == null && valueType == null;
@@ -2131,6 +2002,13 @@
     return '($elementType, $keyType, $valueType)';
   }
 
+  static DartType _dynamicOrNull(DartType type, DartType dynamic) {
+    if (type == null) {
+      return null;
+    }
+    return dynamic;
+  }
+
   static DartType _leastUpperBoundOfTypes(
       TypeSystem typeSystem, DartType first, DartType second) {
     if (first == null) {
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
index 296457a..a2e6994 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
@@ -495,7 +495,7 @@
       fieldFormalParameter(null, null, identifier);
 
   @Deprecated('Use forStatement2')
-  static ForEachStatement forEachStatement(DeclaredIdentifier loopVariable,
+  static ForStatement2 forEachStatement(DeclaredIdentifier loopVariable,
           Expression iterator, Statement body) =>
       astFactory.forStatement2(
           forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
@@ -508,7 +508,7 @@
           body: body);
 
   @Deprecated('Use forStatement2')
-  static ForEachStatement forEachStatement2(
+  static ForStatement2 forEachStatement2(
           SimpleIdentifier identifier, Expression iterator, Statement body) =>
       astFactory.forStatement2(
           forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
@@ -530,7 +530,7 @@
           TokenFactory.tokenFromType(TokenType.CLOSE_PAREN));
 
   @Deprecated('Use forStatement2')
-  static ForStatement forStatement(Expression initialization,
+  static ForStatement2 forStatement(Expression initialization,
           Expression condition, List<Expression> updaters, Statement body) =>
       astFactory.forStatement2(
           forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
@@ -544,27 +544,19 @@
           rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
           body: body);
 
-  static
-      // ignore: deprecated_member_use_from_same_package
-      ForStatement forStatement2(
-              VariableDeclarationList variableList,
-              Expression condition,
-              List<Expression> updaters,
-              Statement body) =>
-          astFactory.forStatement2(
-              forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
-              leftParenthesis: TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
-              forLoopParts: astFactory.forPartsWithDeclarations(
-                  variables: variableList,
-                  leftSeparator:
-                      TokenFactory.tokenFromType(TokenType.SEMICOLON),
-                  condition: condition,
-                  rightSeparator:
-                      TokenFactory.tokenFromType(TokenType.SEMICOLON),
-                  updaters: updaters),
-              rightParenthesis:
-                  TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
-              body: body);
+  static ForStatement2 forStatement2(VariableDeclarationList variableList,
+          Expression condition, List<Expression> updaters, Statement body) =>
+      astFactory.forStatement2(
+          forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
+          leftParenthesis: TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
+          forLoopParts: astFactory.forPartsWithDeclarations(
+              variables: variableList,
+              leftSeparator: TokenFactory.tokenFromType(TokenType.SEMICOLON),
+              condition: condition,
+              rightSeparator: TokenFactory.tokenFromType(TokenType.SEMICOLON),
+              updaters: updaters),
+          rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
+          body: body);
 
   static FunctionDeclaration functionDeclaration(
           TypeAnnotation type,
@@ -678,6 +670,20 @@
         .toList();
   }
 
+  static IfElement ifElement(
+          Expression condition, CollectionElement thenElement,
+          [CollectionElement elseElement]) =>
+      astFactory.ifElement(
+          ifKeyword: TokenFactory.tokenFromKeyword(Keyword.IF),
+          leftParenthesis: TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
+          condition: condition,
+          rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
+          thenElement: thenElement,
+          elseKeyword: elseElement == null
+              ? null
+              : TokenFactory.tokenFromKeyword(Keyword.ELSE),
+          elseElement: elseElement);
+
   static IfStatement ifStatement(
           Expression condition, Statement thenStatement) =>
       ifStatement2(condition, thenStatement, null);
@@ -825,7 +831,7 @@
 
   static ListLiteral listLiteral2(
           Keyword keyword, TypeArgumentList typeArguments,
-          [List<Expression> elements]) =>
+          [List<CollectionElement> elements]) =>
       astFactory.listLiteral(
           keyword == null ? null : TokenFactory.tokenFromKeyword(keyword),
           typeArguments,
@@ -834,7 +840,8 @@
           TokenFactory.tokenFromType(TokenType.CLOSE_SQUARE_BRACKET));
 
   @Deprecated('Use setOrMapLiteral')
-  static MapLiteral mapLiteral(Keyword keyword, TypeArgumentList typeArguments,
+  static SetOrMapLiteral mapLiteral(
+          Keyword keyword, TypeArgumentList typeArguments,
           [List<MapLiteralEntry> entries]) =>
       astFactory.mapLiteral(
           keyword == null ? null : TokenFactory.tokenFromKeyword(keyword),
@@ -844,7 +851,7 @@
           TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET));
 
   @Deprecated('Use setOrMapLiteral')
-  static MapLiteral mapLiteral2([List<MapLiteralEntry> entries]) =>
+  static SetOrMapLiteral mapLiteral2([List<MapLiteralEntry> entries]) =>
       mapLiteral(null, null, entries);
 
   static MapLiteralEntry mapLiteralEntry(String key, Expression value) =>
@@ -1087,8 +1094,8 @@
       astFactory.scriptTag(TokenFactory.tokenFromString(scriptTag));
 
   @Deprecated('Use setOrMapLiteral')
-  static SetLiteral setLiteral(Keyword keyword, TypeArgumentList typeArguments,
-          List<Expression> elements) =>
+  static SetOrMapLiteral setLiteral(Keyword keyword,
+          TypeArgumentList typeArguments, List<Expression> elements) =>
       astFactory.setLiteral(
           keyword == null ? null : TokenFactory.tokenFromKeyword(keyword),
           typeArguments,
@@ -1133,6 +1140,12 @@
           TypeAnnotation type, String parameterName) =>
       simpleFormalParameter2(null, type, parameterName);
 
+  static SpreadElement spreadElement(
+          TokenType operator, Expression expression) =>
+      astFactory.spreadElement(
+          spreadOperator: TokenFactory.tokenFromType(operator),
+          expression: expression);
+
   static StringInterpolation string([List<InterpolationElement> elements]) =>
       astFactory.stringInterpolation(elements);
 
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 30b2925..6e978a6 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -577,6 +577,9 @@
   ///
   /// In practice this will always replace `?` with either bottom or top
   /// (dynamic), depending on the position of `?`.
+  ///
+  /// This implements the operation the spec calls "least closure", or
+  /// sometimes "least closure with respect to `?`".
   DartType lowerBoundForType(DartType type) {
     return _substituteForUnknownType(type, lowerBound: true);
   }
@@ -641,6 +644,9 @@
   ///
   /// In practice this will always replace `?` with either bottom or top
   /// (dynamic), depending on the position of `?`.
+  ///
+  /// This implements the operation the spec calls "greatest closure", or
+  /// sometimes "greatest closure with respect to `?`".
   DartType upperBoundForType(DartType type) {
     return _substituteForUnknownType(type);
   }
diff --git a/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart b/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart
new file mode 100644
index 0000000..2596ac9
--- /dev/null
+++ b/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart
@@ -0,0 +1,105 @@
+// Copyright (c) 2015, 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';
+
+import 'package:analyzer/source/line_info.dart';
+import 'package:analyzer/src/generated/source.dart';
+
+/// Information about analysis `//ignore:` and `//ignore_for_file` comments
+/// within a source file.
+class IgnoreInfo {
+  ///  Instance shared by all cases without matches.
+  static final IgnoreInfo _EMPTY_INFO = new IgnoreInfo();
+
+  /// A regular expression for matching 'ignore' comments.  Produces matches
+  /// containing 2 groups.  For example:
+  ///
+  ///     * ['//ignore: error_code', 'error_code']
+  ///
+  /// Resulting codes may be in a list ('error_code_1,error_code2').
+  static final RegExp _IGNORE_MATCHER =
+      new RegExp(r'//+[ ]*ignore:(.*)$', multiLine: true);
+
+  /// A regular expression for matching 'ignore_for_file' comments.  Produces
+  /// matches containing 2 groups.  For example:
+  ///
+  ///     * ['//ignore_for_file: error_code', 'error_code']
+  ///
+  /// Resulting codes may be in a list ('error_code_1,error_code2').
+  static final RegExp _IGNORE_FOR_FILE_MATCHER =
+      new RegExp(r'//[ ]*ignore_for_file:(.*)$', multiLine: true);
+
+  final Map<int, List<String>> _ignoreMap = new HashMap<int, List<String>>();
+
+  final Set<String> _ignoreForFileSet = new HashSet<String>();
+
+  /// Whether this info object defines any ignores.
+  bool get hasIgnores => ignores.isNotEmpty || _ignoreForFileSet.isNotEmpty;
+
+  /// Iterable of error codes ignored for the whole file.
+  Iterable<String> get ignoreForFiles => _ignoreForFileSet;
+
+  /// Map of line numbers to associated ignored error codes.
+  Map<int, Iterable<String>> get ignores => _ignoreMap;
+
+  /// Ignore this [errorCode] at [line].
+  void add(int line, String errorCode) {
+    _ignoreMap.putIfAbsent(line, () => new List<String>()).add(errorCode);
+  }
+
+  /// Ignore these [errorCodes] at [line].
+  void addAll(int line, Iterable<String> errorCodes) {
+    _ignoreMap.putIfAbsent(line, () => new List<String>()).addAll(errorCodes);
+  }
+
+  /// Ignore these [errorCodes] in the whole file.
+  void addAllForFile(Iterable<String> errorCodes) {
+    _ignoreForFileSet.addAll(errorCodes);
+  }
+
+  /// Test whether this [errorCode] is ignored at the given [line].
+  bool ignoredAt(String errorCode, int line) =>
+      _ignoreForFileSet.contains(errorCode) ||
+      _ignoreMap[line]?.contains(errorCode) == true;
+
+  /// Calculate ignores for the given [content] with line [info].
+  static IgnoreInfo calculateIgnores(String content, LineInfo info) {
+    Iterable<Match> matches = _IGNORE_MATCHER.allMatches(content);
+    Iterable<Match> fileMatches = _IGNORE_FOR_FILE_MATCHER.allMatches(content);
+    if (matches.isEmpty && fileMatches.isEmpty) {
+      return _EMPTY_INFO;
+    }
+
+    IgnoreInfo ignoreInfo = new IgnoreInfo();
+    for (Match match in matches) {
+      // See _IGNORE_MATCHER for format --- note the possibility of error lists.
+      Iterable<String> codes = match
+          .group(1)
+          .split(',')
+          .map((String code) => code.trim().toLowerCase());
+      CharacterLocation location = info.getLocation(match.start);
+      int lineNumber = location.lineNumber;
+      String beforeMatch = content.substring(
+          info.getOffsetOfLine(lineNumber - 1),
+          info.getOffsetOfLine(lineNumber - 1) + location.columnNumber - 1);
+
+      if (beforeMatch.trim().isEmpty) {
+        // The comment is on its own line, so it refers to the next line.
+        ignoreInfo.addAll(lineNumber + 1, codes);
+      } else {
+        // The comment sits next to code, so it refers to its own line.
+        ignoreInfo.addAll(lineNumber, codes);
+      }
+    }
+    for (Match match in fileMatches) {
+      Iterable<String> codes = match
+          .group(1)
+          .split(',')
+          .map((String code) => code.trim().toLowerCase());
+      ignoreInfo.addAllForFile(codes);
+    }
+    return ignoreInfo;
+  }
+}
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index c9abd60..d62aaa0 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -34,8 +34,6 @@
 import 'package:package_config/packages_file.dart' as pkgfile show parse;
 import 'package:package_config/src/packages_impl.dart' show MapPackages;
 import 'package:path/path.dart' as p;
-import 'package:plugin/manager.dart';
-import 'package:plugin/plugin.dart';
 import 'package:yaml/yaml.dart';
 
 AnalysisOptionsProvider _optionsProvider = new AnalysisOptionsProvider();
@@ -125,9 +123,7 @@
 
   final LinterOptions options;
 
-  LintDriver(this.options) {
-    _processPlugins();
-  }
+  LintDriver(this.options);
 
   /// Return the number of sources that have been analyzed so far.
   int get numSourcesAnalyzed => _sourcesAnalyzed.length;
@@ -252,13 +248,6 @@
     }
     return null;
   }
-
-  void _processPlugins() {
-    List<Plugin> plugins = <Plugin>[];
-    plugins.addAll(AnalysisEngine.instance.requiredPlugins);
-    ExtensionManager manager = new ExtensionManager();
-    manager.processPlugins(plugins);
-  }
 }
 
 /// Prints logging information comments to the [outSink] and error messages to
diff --git a/pkg/analyzer/lib/src/plugin/engine_plugin.dart b/pkg/analyzer/lib/src/plugin/engine_plugin.dart
deleted file mode 100644
index 6f97315..0000000
--- a/pkg/analyzer/lib/src/plugin/engine_plugin.dart
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright (c) 2015, 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 'package:analyzer/error/error.dart' show AnalysisError;
-import 'package:analyzer/src/generated/engine.dart'
-    show InternalAnalysisContext;
-import 'package:analyzer/src/plugin/task.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/dart.dart';
-import 'package:analyzer/src/task/dart_work_manager.dart';
-import 'package:analyzer/src/task/options_work_manager.dart';
-import 'package:plugin/plugin.dart';
-
-/**
- * A plugin that defines the extension points and extensions that are inherently
- * defined by the analysis engine.
- */
-class EnginePlugin implements Plugin {
-  /**
-   * The simple identifier of the extension point that allows plugins to
-   * register new analysis error results to compute for a Dart source.
-   */
-  static const String DART_ERRORS_FOR_SOURCE_EXTENSION_POINT =
-      'dartErrorsForSource';
-
-  /**
-   * The simple identifier of the extension point that allows plugins to
-   * register new analysis error results to compute for a Dart library
-   * specific unit.
-   */
-  static const String DART_ERRORS_FOR_UNIT_EXTENSION_POINT =
-      'dartErrorsForUnit';
-
-  /**
-   * The simple identifier of the extension point that allows plugins to
-   * register new analysis error results to compute for an HTML source.
-   */
-  static const String HTML_ERRORS_EXTENSION_POINT = 'htmlErrors';
-
-  /**
-   * The simple identifier of the extension point that allows plugins to
-   * register new work manager factories with the analysis engine.
-   */
-  static const String WORK_MANAGER_FACTORY_EXTENSION_POINT =
-      'workManagerFactory';
-
-  /**
-   * The unique identifier of this plugin.
-   */
-  static const String UNIQUE_IDENTIFIER = 'analysis_engine.core';
-
-  /**
-   * The extension point that allows plugins to register new analysis error
-   * results for a Dart source.
-   */
-  ExtensionPoint<ListResultDescriptor<AnalysisError>>
-      dartErrorsForSourceExtensionPoint;
-
-  /**
-   * The extension point that allows plugins to register new analysis error
-   * results for a Dart library specific unit.
-   */
-  ExtensionPoint<ListResultDescriptor<AnalysisError>>
-      dartErrorsForUnitExtensionPoint;
-
-  /**
-   * The extension point that allows plugins to register new analysis error
-   * results for an HTML source.
-   */
-  ExtensionPoint<ListResultDescriptor<AnalysisError>> htmlErrorsExtensionPoint;
-
-  /**
-   * The extension point that allows plugins to register new work manager
-   * factories with the analysis engine.
-   */
-  ExtensionPoint<WorkManagerFactory> workManagerFactoryExtensionPoint;
-
-  /**
-   * Initialize a newly created plugin.
-   */
-  EnginePlugin();
-
-  /**
-   * Return a list containing all of the contributed analysis error result
-   * descriptors for Dart sources.
-   */
-  @ExtensionPointId('DART_ERRORS_FOR_SOURCE_EXTENSION_POINT_ID')
-  List<ListResultDescriptor<AnalysisError>> get dartErrorsForSource =>
-      dartErrorsForSourceExtensionPoint.extensions;
-
-  /**
-   * Return a list containing all of the contributed analysis error result
-   * descriptors for Dart library specific units.
-   */
-  @ExtensionPointId('DART_ERRORS_FOR_UNIT_EXTENSION_POINT_ID')
-  List<ListResultDescriptor<AnalysisError>> get dartErrorsForUnit =>
-      dartErrorsForUnitExtensionPoint.extensions;
-
-  /**
-   * Return a list containing all of the contributed analysis error result
-   * descriptors for HTML sources.
-   */
-  @ExtensionPointId('HTML_ERRORS_EXTENSION_POINT_ID')
-  List<ListResultDescriptor<AnalysisError>> get htmlErrors =>
-      htmlErrorsExtensionPoint.extensions;
-
-  @override
-  String get uniqueIdentifier => UNIQUE_IDENTIFIER;
-
-  /**
-   * Return a list containing all of the work manager factories that were
-   * contributed.
-   */
-  List<WorkManagerFactory> get workManagerFactories =>
-      workManagerFactoryExtensionPoint.extensions;
-
-  @override
-  void registerExtensionPoints(RegisterExtensionPoint registerExtensionPoint) {
-    dartErrorsForSourceExtensionPoint =
-        new ExtensionPoint<ListResultDescriptor<AnalysisError>>(
-            this, DART_ERRORS_FOR_SOURCE_EXTENSION_POINT, null);
-    registerExtensionPoint(dartErrorsForSourceExtensionPoint);
-    dartErrorsForUnitExtensionPoint =
-        new ExtensionPoint<ListResultDescriptor<AnalysisError>>(
-            this, DART_ERRORS_FOR_UNIT_EXTENSION_POINT, null);
-    registerExtensionPoint(dartErrorsForUnitExtensionPoint);
-    htmlErrorsExtensionPoint =
-        new ExtensionPoint<ListResultDescriptor<AnalysisError>>(
-            this, HTML_ERRORS_EXTENSION_POINT, null);
-    registerExtensionPoint(htmlErrorsExtensionPoint);
-    workManagerFactoryExtensionPoint = new ExtensionPoint<WorkManagerFactory>(
-        this, WORK_MANAGER_FACTORY_EXTENSION_POINT, null);
-    registerExtensionPoint(workManagerFactoryExtensionPoint);
-  }
-
-  @override
-  void registerExtensions(RegisterExtension registerExtension) {
-    _registerWorkManagerFactoryExtensions(registerExtension);
-    _registerDartErrorsForSource(registerExtension);
-    _registerDartErrorsForUnit(registerExtension);
-  }
-
-  void _registerDartErrorsForSource(RegisterExtension registerExtension) {
-    registerExtension(DART_ERRORS_FOR_SOURCE_EXTENSION_POINT_ID, PARSE_ERRORS);
-    registerExtension(DART_ERRORS_FOR_SOURCE_EXTENSION_POINT_ID, SCAN_ERRORS);
-  }
-
-  void _registerDartErrorsForUnit(RegisterExtension registerExtension) {
-    registerExtension(
-        DART_ERRORS_FOR_UNIT_EXTENSION_POINT_ID, LIBRARY_UNIT_ERRORS);
-  }
-
-  void _registerWorkManagerFactoryExtensions(
-      RegisterExtension registerExtension) {
-    String taskId = WORK_MANAGER_EXTENSION_POINT_ID;
-    registerExtension(taskId,
-        (InternalAnalysisContext context) => new DartWorkManager(context));
-    registerExtension(taskId,
-        (InternalAnalysisContext context) => new OptionsWorkManager(context));
-  }
-}
-
-/**
- * Annotation describing the relationship between a getter in [EnginePlugin]
- * and the associated identifier (in 'task.dart') which can be passed to the
- * extension manager to populate it.
- *
- * This annotation is not used at runtime; it is used to aid in static analysis
- * of the task model during development.
- */
-class ExtensionPointId {
-  final String extensionPointId;
-
-  const ExtensionPointId(this.extensionPointId);
-}
diff --git a/pkg/analyzer/lib/src/plugin/task.dart b/pkg/analyzer/lib/src/plugin/task.dart
index 8292485..fec6844 100644
--- a/pkg/analyzer/lib/src/plugin/task.dart
+++ b/pkg/analyzer/lib/src/plugin/task.dart
@@ -7,44 +7,7 @@
  * analysis tasks.
  */
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/plugin/engine_plugin.dart';
 import 'package:analyzer/src/task/api/model.dart';
-import 'package:plugin/plugin.dart';
-
-/**
- * The identifier of the extension point that allows plugins to register new
- * analysis error results to compute for a Dart source. The object used as an
- * extension must be a [ResultDescriptor].
- */
-final String DART_ERRORS_FOR_SOURCE_EXTENSION_POINT_ID = Plugin.join(
-    EnginePlugin.UNIQUE_IDENTIFIER,
-    EnginePlugin.DART_ERRORS_FOR_SOURCE_EXTENSION_POINT);
-
-/**
- * The identifier of the extension point that allows plugins to register new
- * analysis error results to compute for a Dart library specific unit. The
- * object used as an extension must be a [ResultDescriptor].
- */
-final String DART_ERRORS_FOR_UNIT_EXTENSION_POINT_ID = Plugin.join(
-    EnginePlugin.UNIQUE_IDENTIFIER,
-    EnginePlugin.DART_ERRORS_FOR_UNIT_EXTENSION_POINT);
-
-/**
- * The identifier of the extension point that allows plugins to register new
- * analysis error results to compute for an HTML source. The object used as an
- * extension must be a [ResultDescriptor].
- */
-final String HTML_ERRORS_EXTENSION_POINT_ID = Plugin.join(
-    EnginePlugin.UNIQUE_IDENTIFIER, EnginePlugin.HTML_ERRORS_EXTENSION_POINT);
-
-/**
- * The identifier of the extension point that allows plugins to register new
- * work managers with the analysis engine. The object used as an extension must
- * be a [WorkManagerFactory].
- */
-final String WORK_MANAGER_EXTENSION_POINT_ID = Plugin.join(
-    EnginePlugin.UNIQUE_IDENTIFIER,
-    EnginePlugin.WORK_MANAGER_FACTORY_EXTENSION_POINT);
 
 /**
  * A function that will create a new [WorkManager] for the given [context].
diff --git a/pkg/analyzer/lib/src/services/available_declarations.dart b/pkg/analyzer/lib/src/services/available_declarations.dart
index 4ec0123..aaed6fe 100644
--- a/pkg/analyzer/lib/src/services/available_declarations.dart
+++ b/pkg/analyzer/lib/src/services/available_declarations.dart
@@ -624,6 +624,7 @@
 
     var isLibrary = file.isLibrary;
     var library = isLibrary ? file : file.library;
+    if (library == null) return;
 
     if (isLibrary) {
       file.refresh(containingContext);
diff --git a/pkg/analyzer/lib/src/summary/expr_builder.dart b/pkg/analyzer/lib/src/summary/expr_builder.dart
index 3301d95..960e342 100644
--- a/pkg/analyzer/lib/src/summary/expr_builder.dart
+++ b/pkg/analyzer/lib/src/summary/expr_builder.dart
@@ -17,7 +17,7 @@
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/resynthesize.dart';
 
-bool _isSetOrMapEnabled(ExperimentStatus experimentStatus) =>
+bool _isSpreadOrControlFlowEnabled(ExperimentStatus experimentStatus) =>
     experimentStatus.spread_collections ||
     experimentStatus.control_flow_collections;
 
@@ -31,7 +31,8 @@
   final ElementImpl context;
   final UnlinkedExpr _uc;
   final bool requireValidConst;
-  final bool useSetOrMap;
+  final bool isSpreadOrControlFlowEnabled;
+  final bool becomeSetOrMap;
 
   int intPtr = 0;
   int doublePtr = 0;
@@ -47,15 +48,20 @@
 
   final Map<String, ParameterElement> parametersInScope;
 
-  ExprBuilder(this.resynthesizer, this.context, this._uc,
-      {this.requireValidConst: true,
-      this.localFunctions,
-      Map<String, ParameterElement> parametersInScope})
-      : this.parametersInScope =
+  ExprBuilder(
+    this.resynthesizer,
+    this.context,
+    this._uc, {
+    this.requireValidConst: true,
+    this.localFunctions,
+    Map<String, ParameterElement> parametersInScope,
+    this.becomeSetOrMap: true,
+  })  : this.parametersInScope =
             parametersInScope ?? _parametersInScope(context),
-        this.useSetOrMap = _isSetOrMapEnabled((resynthesizer
-                .library.context.analysisOptions as AnalysisOptionsImpl)
-            .experimentStatus);
+        this.isSpreadOrControlFlowEnabled = _isSpreadOrControlFlowEnabled(
+            (resynthesizer.library.context.analysisOptions
+                    as AnalysisOptionsImpl)
+                .experimentStatus);
 
   bool get hasNonEmptyExpr => _uc != null && _uc.operations.isNotEmpty;
 
@@ -234,7 +240,7 @@
           break;
         case UnlinkedExprOperation.makeTypedSet:
           TypeAnnotation itemType = _newTypeName();
-          if (useSetOrMap) {
+          if (isSpreadOrControlFlowEnabled) {
             _pushSetOrMap(
                 AstTestFactory.typeArgumentList(<TypeAnnotation>[itemType]));
           } else {
@@ -311,6 +317,18 @@
         case UnlinkedExprOperation.pushThis:
           _push(AstTestFactory.thisExpression());
           break;
+        case UnlinkedExprOperation.spreadElement:
+          _pushSpread(TokenType.PERIOD_PERIOD_PERIOD);
+          break;
+        case UnlinkedExprOperation.nullAwareSpreadElement:
+          _pushSpread(TokenType.PERIOD_PERIOD_PERIOD_QUESTION);
+          break;
+        case UnlinkedExprOperation.ifElement:
+          _pushIfElement(false);
+          break;
+        case UnlinkedExprOperation.ifElseElement:
+          _pushIfElement(true);
+          break;
         case UnlinkedExprOperation.cascadeSectionBegin:
         case UnlinkedExprOperation.cascadeSectionEnd:
         case UnlinkedExprOperation.pushLocalFunctionReference:
@@ -613,7 +631,7 @@
 
   CollectionElement _popCollectionElement() => stack.removeLast();
 
-  void _push(Expression expr) {
+  void _push(CollectionElement expr) {
     stack.add(expr);
   }
 
@@ -638,6 +656,13 @@
     _push(AstTestFactory.propertyAccess(target, propertyNode));
   }
 
+  void _pushIfElement(bool hasElse) {
+    CollectionElement elseElement = hasElse ? _popCollectionElement() : null;
+    CollectionElement thenElement = _popCollectionElement();
+    Expression condition = _pop();
+    _push(AstTestFactory.ifElement(condition, thenElement, elseElement));
+  }
+
   void _pushInstanceCreation() {
     EntityRef ref = _uc.references[refPtr++];
     ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
@@ -750,9 +775,10 @@
 
   void _pushList(TypeArgumentList typeArguments) {
     int count = _uc.ints[intPtr++];
-    List<Expression> elements = <Expression>[];
+    List<CollectionElement> elements =
+        isSpreadOrControlFlowEnabled ? <CollectionElement>[] : <Expression>[];
     for (int i = 0; i < count; i++) {
-      elements.insert(0, _pop());
+      elements.insert(0, _popCollectionElement());
     }
     var typeArg = typeArguments == null
         ? resynthesizer.typeProvider.dynamicType
@@ -825,7 +851,7 @@
         : typeArguments.arguments[1].type;
     var staticType =
         resynthesizer.typeProvider.mapType.instantiate([keyType, valueType]);
-    if (useSetOrMap) {
+    if (isSpreadOrControlFlowEnabled) {
       _push(
           AstTestFactory.setOrMapLiteral(Keyword.CONST, typeArguments, entries)
             ..staticType = staticType);
@@ -865,27 +891,54 @@
     int count = _uc.ints[intPtr++];
     List<CollectionElement> elements = <CollectionElement>[];
     for (int i = 0; i < count; i++) {
-      elements.add(_popCollectionElement());
+      elements.insert(0, _popCollectionElement());
     }
+
+    bool isMap = true; // assume Map unless can prove otherwise
     DartType staticType;
-    if (typeArguments != null && typeArguments.arguments.length == 2) {
-      var keyType = typeArguments.arguments[0].type;
-      var valueType = typeArguments.arguments[1].type;
-      staticType =
-          resynthesizer.typeProvider.mapType.instantiate([keyType, valueType]);
-    } else if (typeArguments != null && typeArguments.arguments.length == 1) {
-      var valueType = typeArguments == null
-          ? resynthesizer.typeProvider.dynamicType
-          : typeArguments.arguments[0].type;
-      staticType = resynthesizer.typeProvider.setType.instantiate([valueType]);
+    if (typeArguments != null) {
+      if (typeArguments.arguments.length == 2) {
+        var keyType = typeArguments.arguments[0].type;
+        var valueType = typeArguments.arguments[1].type;
+        staticType = resynthesizer.typeProvider.mapType
+            .instantiate([keyType, valueType]);
+      } else if (typeArguments.arguments.length == 1) {
+        isMap = false;
+        var valueType = typeArguments == null
+            ? resynthesizer.typeProvider.dynamicType
+            : typeArguments.arguments[0].type;
+        staticType =
+            resynthesizer.typeProvider.setType.instantiate([valueType]);
+      }
+    } else {
+      for (var i = 0; i < elements.length; ++i) {
+        var element = elements[i];
+        if (element is Expression) {
+          isMap = false;
+        }
+      }
     }
-    _push(astFactory.setOrMapLiteral(
-        constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
-        typeArguments: typeArguments,
-        leftBracket: TokenFactory.tokenFromType(TokenType.OPEN_CURLY_BRACKET),
-        elements: elements,
-        rightBracket: TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET))
-      ..staticType = staticType);
+
+    SetOrMapLiteral setOrMapLiteral = astFactory.setOrMapLiteral(
+      constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
+      typeArguments: typeArguments,
+      leftBracket: TokenFactory.tokenFromType(TokenType.OPEN_CURLY_BRACKET),
+      elements: elements,
+      rightBracket: TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET),
+    );
+    if (becomeSetOrMap) {
+      if (isMap) {
+        (setOrMapLiteral as SetOrMapLiteralImpl).becomeMap();
+      } else {
+        (setOrMapLiteral as SetOrMapLiteralImpl).becomeSet();
+      }
+    }
+    _push(setOrMapLiteral..staticType = staticType);
+  }
+
+  void _pushSpread(TokenType operator) {
+    Expression operand = _pop();
+    _push(AstTestFactory.spreadElement(operator, operand));
   }
 
   List<Expression> _removeTopExpressions(int count) {
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index f77a8b6..ca27841f 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -4571,6 +4571,7 @@
   bool _variantField_31;
   String _variantField_20;
   String _variantField_22;
+  LinkedNodeVariablesDeclarationBuilder _variantField_32;
 
   @override
   List<LinkedNodeBuilder> get adjacentStrings_strings {
@@ -8781,6 +8782,12 @@
   }
 
   @override
+  int get methodDeclaration_actualProperty {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    return _variantField_19 ??= 0;
+  }
+
+  @override
   int get normalFormalParameter_covariantKeyword {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
@@ -8862,6 +8869,12 @@
     _variantField_19 = value;
   }
 
+  void set methodDeclaration_actualProperty(int value) {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    assert(value == null || value >= 0);
+    _variantField_19 = value;
+  }
+
   void set normalFormalParameter_covariantKeyword(int value) {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
@@ -8906,6 +8919,30 @@
   }
 
   @override
+  LinkedNodeTypeBuilder get fieldFormalParameter_type2 {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
+    return _variantField_24;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get functionDeclaration_returnType2 {
+    assert(kind == idl.LinkedNodeKind.functionDeclaration);
+    return _variantField_24;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get functionTypeAlias_returnType2 {
+    assert(kind == idl.LinkedNodeKind.functionTypeAlias);
+    return _variantField_24;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get genericFunctionType_returnType2 {
+    assert(kind == idl.LinkedNodeKind.genericFunctionType);
+    return _variantField_24;
+  }
+
+  @override
   LinkedNodeTypeBuilder get invocationExpression_invokeType {
     assert(kind == idl.LinkedNodeKind.functionExpressionInvocation ||
         kind == idl.LinkedNodeKind.methodInvocation);
@@ -8913,27 +8950,80 @@
   }
 
   @override
+  LinkedNodeTypeBuilder get methodDeclaration_returnType2 {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    return _variantField_24;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get simpleFormalParameter_type2 {
+    assert(kind == idl.LinkedNodeKind.simpleFormalParameter);
+    return _variantField_24;
+  }
+
+  @override
   LinkedNodeTypeBuilder get typeName_type {
     assert(kind == idl.LinkedNodeKind.typeName);
     return _variantField_24;
   }
 
+  @override
+  LinkedNodeTypeBuilder get variableDeclaration_type2 {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    return _variantField_24;
+  }
+
   void set binaryExpression_invokeType(LinkedNodeTypeBuilder value) {
     assert(kind == idl.LinkedNodeKind.binaryExpression);
     _variantField_24 = value;
   }
 
+  void set fieldFormalParameter_type2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
+    _variantField_24 = value;
+  }
+
+  void set functionDeclaration_returnType2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.functionDeclaration);
+    _variantField_24 = value;
+  }
+
+  void set functionTypeAlias_returnType2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.functionTypeAlias);
+    _variantField_24 = value;
+  }
+
+  void set genericFunctionType_returnType2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.genericFunctionType);
+    _variantField_24 = value;
+  }
+
   void set invocationExpression_invokeType(LinkedNodeTypeBuilder value) {
     assert(kind == idl.LinkedNodeKind.functionExpressionInvocation ||
         kind == idl.LinkedNodeKind.methodInvocation);
     _variantField_24 = value;
   }
 
+  void set methodDeclaration_returnType2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_24 = value;
+  }
+
+  void set simpleFormalParameter_type2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.simpleFormalParameter);
+    _variantField_24 = value;
+  }
+
   void set typeName_type(LinkedNodeTypeBuilder value) {
     assert(kind == idl.LinkedNodeKind.typeName);
     _variantField_24 = value;
   }
 
+  void set variableDeclaration_type2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_24 = value;
+  }
+
   @override
   bool get booleanLiteral_value {
     assert(kind == idl.LinkedNodeKind.booleanLiteral);
@@ -8941,12 +9031,26 @@
   }
 
   @override
+  bool get classDeclaration_isDartObject {
+    assert(kind == idl.LinkedNodeKind.classDeclaration);
+    return _variantField_27 ??= false;
+  }
+
+  @override
   bool get defaultFormalParameter_isNamed {
     assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
     return _variantField_27 ??= false;
   }
 
   @override
+  bool get normalFormalParameter_isCovariant {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter);
+    return _variantField_27 ??= false;
+  }
+
+  @override
   bool get setOrMapLiteral_isMap {
     assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
     return _variantField_27 ??= false;
@@ -8957,11 +9061,23 @@
     _variantField_27 = value;
   }
 
+  void set classDeclaration_isDartObject(bool value) {
+    assert(kind == idl.LinkedNodeKind.classDeclaration);
+    _variantField_27 = value;
+  }
+
   void set defaultFormalParameter_isNamed(bool value) {
     assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
     _variantField_27 = value;
   }
 
+  void set normalFormalParameter_isCovariant(bool value) {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter);
+    _variantField_27 = value;
+  }
+
   void set setOrMapLiteral_isMap(bool value) {
     assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
     _variantField_27 = value;
@@ -9454,6 +9570,18 @@
     _variantField_22 = value;
   }
 
+  @override
+  LinkedNodeVariablesDeclarationBuilder get variableDeclaration_declaration {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    return _variantField_32;
+  }
+
+  void set variableDeclaration_declaration(
+      LinkedNodeVariablesDeclarationBuilder value) {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_32 = value;
+  }
+
   LinkedNodeBuilder.adjacentStrings({
     List<LinkedNodeBuilder> adjacentStrings_strings,
     LinkedNodeTypeBuilder expression_type,
@@ -9775,6 +9903,7 @@
     int classDeclaration_classKeyword,
     int classOrMixinDeclaration_rightBracket,
     int classOrMixinDeclaration_leftBracket,
+    bool classDeclaration_isDartObject,
     LinkedNodeBuilder classOrMixinDeclaration_implementsClause,
     List<LinkedNodeBuilder> classOrMixinDeclaration_members,
     LinkedNodeBuilder classOrMixinDeclaration_typeParameters,
@@ -9788,6 +9917,7 @@
         _variantField_16 = classDeclaration_classKeyword,
         _variantField_18 = classOrMixinDeclaration_rightBracket,
         _variantField_19 = classOrMixinDeclaration_leftBracket,
+        _variantField_27 = classDeclaration_isDartObject,
         _variantField_12 = classOrMixinDeclaration_implementsClause,
         _variantField_5 = classOrMixinDeclaration_members,
         _variantField_13 = classOrMixinDeclaration_typeParameters,
@@ -9862,6 +9992,7 @@
     int functionDeclaration_externalKeyword,
     LinkedNodeBuilder functionDeclaration_returnType,
     int functionDeclaration_propertyKeyword,
+    LinkedNodeTypeBuilder functionDeclaration_returnType2,
     LinkedNodeBuilder namedCompilationUnitMember_name,
   })  : _kind = idl.LinkedNodeKind.functionDeclaration,
         _variantField_11 = annotatedNode_comment,
@@ -9870,6 +10001,7 @@
         _variantField_15 = functionDeclaration_externalKeyword,
         _variantField_7 = functionDeclaration_returnType,
         _variantField_16 = functionDeclaration_propertyKeyword,
+        _variantField_24 = functionDeclaration_returnType2,
         _variantField_14 = namedCompilationUnitMember_name;
 
   LinkedNodeBuilder.functionTypeAlias({
@@ -9880,6 +10012,7 @@
     LinkedNodeBuilder functionTypeAlias_typeParameters,
     int typeAlias_typedefKeyword,
     int typeAlias_semicolon,
+    LinkedNodeTypeBuilder functionTypeAlias_returnType2,
     LinkedNodeBuilder namedCompilationUnitMember_name,
   })  : _kind = idl.LinkedNodeKind.functionTypeAlias,
         _variantField_11 = annotatedNode_comment,
@@ -9889,6 +10022,7 @@
         _variantField_8 = functionTypeAlias_typeParameters,
         _variantField_18 = typeAlias_typedefKeyword,
         _variantField_19 = typeAlias_semicolon,
+        _variantField_24 = functionTypeAlias_returnType2,
         _variantField_14 = namedCompilationUnitMember_name;
 
   LinkedNodeBuilder.genericTypeAlias({
@@ -9933,6 +10067,8 @@
     int methodDeclaration_modifierKeyword,
     int methodDeclaration_operatorKeyword,
     int methodDeclaration_propertyKeyword,
+    int methodDeclaration_actualProperty,
+    LinkedNodeTypeBuilder methodDeclaration_returnType2,
     LinkedNodeBuilder methodDeclaration_typeParameters,
     LinkedNodeBuilder methodDeclaration_name,
   })  : _kind = idl.LinkedNodeKind.methodDeclaration,
@@ -9945,6 +10081,8 @@
         _variantField_16 = methodDeclaration_modifierKeyword,
         _variantField_17 = methodDeclaration_operatorKeyword,
         _variantField_18 = methodDeclaration_propertyKeyword,
+        _variantField_19 = methodDeclaration_actualProperty,
+        _variantField_24 = methodDeclaration_returnType2,
         _variantField_9 = methodDeclaration_typeParameters,
         _variantField_10 = methodDeclaration_name;
 
@@ -10039,12 +10177,16 @@
     LinkedNodeBuilder variableDeclaration_initializer,
     int variableDeclaration_equals,
     LinkedNodeBuilder variableDeclaration_name,
+    LinkedNodeTypeBuilder variableDeclaration_type2,
+    LinkedNodeVariablesDeclarationBuilder variableDeclaration_declaration,
   })  : _kind = idl.LinkedNodeKind.variableDeclaration,
         _variantField_11 = annotatedNode_comment,
         _variantField_4 = annotatedNode_metadata,
         _variantField_6 = variableDeclaration_initializer,
         _variantField_15 = variableDeclaration_equals,
-        _variantField_7 = variableDeclaration_name;
+        _variantField_7 = variableDeclaration_name,
+        _variantField_24 = variableDeclaration_type2,
+        _variantField_32 = variableDeclaration_declaration;
 
   LinkedNodeBuilder.fieldFormalParameter({
     List<LinkedNodeBuilder> normalFormalParameter_metadata,
@@ -10055,6 +10197,8 @@
     int fieldFormalParameter_period,
     int fieldFormalParameter_thisKeyword,
     int normalFormalParameter_covariantKeyword,
+    LinkedNodeTypeBuilder fieldFormalParameter_type2,
+    bool normalFormalParameter_isCovariant,
     LinkedNodeBuilder normalFormalParameter_identifier,
     idl.LinkedNodeFormalParameterKind formalParameter_kind,
     LinkedNodeBuilder normalFormalParameter_comment,
@@ -10067,6 +10211,8 @@
         _variantField_16 = fieldFormalParameter_period,
         _variantField_17 = fieldFormalParameter_thisKeyword,
         _variantField_19 = normalFormalParameter_covariantKeyword,
+        _variantField_24 = fieldFormalParameter_type2,
+        _variantField_27 = normalFormalParameter_isCovariant,
         _variantField_12 = normalFormalParameter_identifier,
         _variantField_26 = formalParameter_kind,
         _variantField_14 = normalFormalParameter_comment;
@@ -10077,6 +10223,7 @@
     LinkedNodeBuilder functionTypedFormalParameter_returnType,
     LinkedNodeBuilder functionTypedFormalParameter_typeParameters,
     int normalFormalParameter_covariantKeyword,
+    bool normalFormalParameter_isCovariant,
     LinkedNodeBuilder normalFormalParameter_identifier,
     idl.LinkedNodeFormalParameterKind formalParameter_kind,
     LinkedNodeBuilder normalFormalParameter_comment,
@@ -10086,6 +10233,7 @@
         _variantField_7 = functionTypedFormalParameter_returnType,
         _variantField_8 = functionTypedFormalParameter_typeParameters,
         _variantField_19 = normalFormalParameter_covariantKeyword,
+        _variantField_27 = normalFormalParameter_isCovariant,
         _variantField_12 = normalFormalParameter_identifier,
         _variantField_26 = formalParameter_kind,
         _variantField_14 = normalFormalParameter_comment;
@@ -10095,6 +10243,8 @@
     LinkedNodeBuilder simpleFormalParameter_type,
     int simpleFormalParameter_keyword,
     int normalFormalParameter_covariantKeyword,
+    LinkedNodeTypeBuilder simpleFormalParameter_type2,
+    bool normalFormalParameter_isCovariant,
     LinkedNodeBuilder normalFormalParameter_identifier,
     idl.LinkedNodeFormalParameterKind formalParameter_kind,
     LinkedNodeBuilder normalFormalParameter_comment,
@@ -10103,6 +10253,8 @@
         _variantField_6 = simpleFormalParameter_type,
         _variantField_15 = simpleFormalParameter_keyword,
         _variantField_19 = normalFormalParameter_covariantKeyword,
+        _variantField_24 = simpleFormalParameter_type2,
+        _variantField_27 = normalFormalParameter_isCovariant,
         _variantField_12 = normalFormalParameter_identifier,
         _variantField_26 = formalParameter_kind,
         _variantField_14 = normalFormalParameter_comment;
@@ -10488,12 +10640,14 @@
     LinkedNodeBuilder genericFunctionType_returnType,
     LinkedNodeBuilder genericFunctionType_formalParameters,
     int genericFunctionType_question,
+    LinkedNodeTypeBuilder genericFunctionType_returnType2,
   })  : _kind = idl.LinkedNodeKind.genericFunctionType,
         _variantField_6 = genericFunctionType_typeParameters,
         _variantField_15 = genericFunctionType_functionKeyword,
         _variantField_7 = genericFunctionType_returnType,
         _variantField_8 = genericFunctionType_formalParameters,
-        _variantField_16 = genericFunctionType_question;
+        _variantField_16 = genericFunctionType_question,
+        _variantField_24 = genericFunctionType_returnType2;
 
   LinkedNodeBuilder.ifElement({
     LinkedNodeBuilder ifMixin_condition,
@@ -10899,6 +11053,7 @@
     _variantField_10?.flushInformative();
     _variantField_25?.flushInformative();
     _variantField_14?.flushInformative();
+    _variantField_32?.flushInformative();
   }
 
   /**
@@ -10985,6 +11140,8 @@
         this._variantField_29 == null ? 0 : this._variantField_29.index);
     signature.addString(this._variantField_30 ?? '');
     signature.addBool(this._variantField_31 == true);
+    signature.addBool(this._variantField_32 != null);
+    this._variantField_32?.collectApiSignature(signature);
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
@@ -11008,6 +11165,7 @@
     fb.Offset offset_variantField_23;
     fb.Offset offset_variantField_20;
     fb.Offset offset_variantField_22;
+    fb.Offset offset_variantField_32;
     if (!(_variantField_2 == null || _variantField_2.isEmpty)) {
       offset_variantField_2 = fbBuilder
           .writeList(_variantField_2.map((b) => b.finish(fbBuilder)).toList());
@@ -11072,6 +11230,9 @@
     if (_variantField_22 != null) {
       offset_variantField_22 = fbBuilder.writeString(_variantField_22);
     }
+    if (_variantField_32 != null) {
+      offset_variantField_32 = _variantField_32.finish(fbBuilder);
+    }
     fbBuilder.startTable();
     if (offset_variantField_2 != null) {
       fbBuilder.addOffset(2, offset_variantField_2);
@@ -11171,6 +11332,9 @@
     if (offset_variantField_22 != null) {
       fbBuilder.addOffset(22, offset_variantField_22);
     }
+    if (offset_variantField_32 != null) {
+      fbBuilder.addOffset(32, offset_variantField_32);
+    }
     return fbBuilder.endTable();
   }
 }
@@ -11223,6 +11387,7 @@
   bool _variantField_31;
   String _variantField_20;
   String _variantField_22;
+  idl.LinkedNodeVariablesDeclaration _variantField_32;
 
   @override
   List<idl.LinkedNode> get adjacentStrings_strings {
@@ -14174,6 +14339,14 @@
   }
 
   @override
+  int get methodDeclaration_actualProperty {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_19 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
+    return _variantField_19;
+  }
+
+  @override
   int get normalFormalParameter_covariantKeyword {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
@@ -14229,6 +14402,38 @@
   }
 
   @override
+  idl.LinkedNodeType get fieldFormalParameter_type2 {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
+  idl.LinkedNodeType get functionDeclaration_returnType2 {
+    assert(kind == idl.LinkedNodeKind.functionDeclaration);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
+  idl.LinkedNodeType get functionTypeAlias_returnType2 {
+    assert(kind == idl.LinkedNodeKind.functionTypeAlias);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
+  idl.LinkedNodeType get genericFunctionType_returnType2 {
+    assert(kind == idl.LinkedNodeKind.genericFunctionType);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
   idl.LinkedNodeType get invocationExpression_invokeType {
     assert(kind == idl.LinkedNodeKind.functionExpressionInvocation ||
         kind == idl.LinkedNodeKind.methodInvocation);
@@ -14238,6 +14443,22 @@
   }
 
   @override
+  idl.LinkedNodeType get methodDeclaration_returnType2 {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
+  idl.LinkedNodeType get simpleFormalParameter_type2 {
+    assert(kind == idl.LinkedNodeKind.simpleFormalParameter);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
   idl.LinkedNodeType get typeName_type {
     assert(kind == idl.LinkedNodeKind.typeName);
     _variantField_24 ??=
@@ -14246,6 +14467,14 @@
   }
 
   @override
+  idl.LinkedNodeType get variableDeclaration_type2 {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
   bool get booleanLiteral_value {
     assert(kind == idl.LinkedNodeKind.booleanLiteral);
     _variantField_27 ??=
@@ -14254,6 +14483,14 @@
   }
 
   @override
+  bool get classDeclaration_isDartObject {
+    assert(kind == idl.LinkedNodeKind.classDeclaration);
+    _variantField_27 ??=
+        const fb.BoolReader().vTableGet(_bc, _bcOffset, 27, false);
+    return _variantField_27;
+  }
+
+  @override
   bool get defaultFormalParameter_isNamed {
     assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
     _variantField_27 ??=
@@ -14262,6 +14499,16 @@
   }
 
   @override
+  bool get normalFormalParameter_isCovariant {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter);
+    _variantField_27 ??=
+        const fb.BoolReader().vTableGet(_bc, _bcOffset, 27, false);
+    return _variantField_27;
+  }
+
+  @override
   bool get setOrMapLiteral_isMap {
     assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
     _variantField_27 ??=
@@ -14601,6 +14848,14 @@
         const fb.StringReader().vTableGet(_bc, _bcOffset, 22, '');
     return _variantField_22;
   }
+
+  @override
+  idl.LinkedNodeVariablesDeclaration get variableDeclaration_declaration {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_32 ??= const _LinkedNodeVariablesDeclarationReader()
+        .vTableGet(_bc, _bcOffset, 32, null);
+    return _variantField_32;
+  }
 }
 
 abstract class _LinkedNodeMixin implements idl.LinkedNode {
@@ -15014,6 +15269,9 @@
       if (classOrMixinDeclaration_leftBracket != 0)
         _result["classOrMixinDeclaration_leftBracket"] =
             classOrMixinDeclaration_leftBracket;
+      if (classDeclaration_isDartObject != false)
+        _result["classDeclaration_isDartObject"] =
+            classDeclaration_isDartObject;
       if (classOrMixinDeclaration_implementsClause != null)
         _result["classOrMixinDeclaration_implementsClause"] =
             classOrMixinDeclaration_implementsClause.toJson();
@@ -15119,6 +15377,9 @@
       if (functionDeclaration_propertyKeyword != 0)
         _result["functionDeclaration_propertyKeyword"] =
             functionDeclaration_propertyKeyword;
+      if (functionDeclaration_returnType2 != null)
+        _result["functionDeclaration_returnType2"] =
+            functionDeclaration_returnType2.toJson();
       if (namedCompilationUnitMember_name != null)
         _result["namedCompilationUnitMember_name"] =
             namedCompilationUnitMember_name.toJson();
@@ -15142,6 +15403,9 @@
         _result["typeAlias_typedefKeyword"] = typeAlias_typedefKeyword;
       if (typeAlias_semicolon != 0)
         _result["typeAlias_semicolon"] = typeAlias_semicolon;
+      if (functionTypeAlias_returnType2 != null)
+        _result["functionTypeAlias_returnType2"] =
+            functionTypeAlias_returnType2.toJson();
       if (namedCompilationUnitMember_name != null)
         _result["namedCompilationUnitMember_name"] =
             namedCompilationUnitMember_name.toJson();
@@ -15207,6 +15471,12 @@
       if (methodDeclaration_propertyKeyword != 0)
         _result["methodDeclaration_propertyKeyword"] =
             methodDeclaration_propertyKeyword;
+      if (methodDeclaration_actualProperty != 0)
+        _result["methodDeclaration_actualProperty"] =
+            methodDeclaration_actualProperty;
+      if (methodDeclaration_returnType2 != null)
+        _result["methodDeclaration_returnType2"] =
+            methodDeclaration_returnType2.toJson();
       if (methodDeclaration_typeParameters != null)
         _result["methodDeclaration_typeParameters"] =
             methodDeclaration_typeParameters.toJson();
@@ -15326,6 +15596,12 @@
         _result["variableDeclaration_equals"] = variableDeclaration_equals;
       if (variableDeclaration_name != null)
         _result["variableDeclaration_name"] = variableDeclaration_name.toJson();
+      if (variableDeclaration_type2 != null)
+        _result["variableDeclaration_type2"] =
+            variableDeclaration_type2.toJson();
+      if (variableDeclaration_declaration != null)
+        _result["variableDeclaration_declaration"] =
+            variableDeclaration_declaration.toJson();
     }
     if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
       if (normalFormalParameter_metadata.isNotEmpty)
@@ -15352,6 +15628,12 @@
       if (normalFormalParameter_covariantKeyword != 0)
         _result["normalFormalParameter_covariantKeyword"] =
             normalFormalParameter_covariantKeyword;
+      if (fieldFormalParameter_type2 != null)
+        _result["fieldFormalParameter_type2"] =
+            fieldFormalParameter_type2.toJson();
+      if (normalFormalParameter_isCovariant != false)
+        _result["normalFormalParameter_isCovariant"] =
+            normalFormalParameter_isCovariant;
       if (normalFormalParameter_identifier != null)
         _result["normalFormalParameter_identifier"] =
             normalFormalParameter_identifier.toJson();
@@ -15380,6 +15662,9 @@
       if (normalFormalParameter_covariantKeyword != 0)
         _result["normalFormalParameter_covariantKeyword"] =
             normalFormalParameter_covariantKeyword;
+      if (normalFormalParameter_isCovariant != false)
+        _result["normalFormalParameter_isCovariant"] =
+            normalFormalParameter_isCovariant;
       if (normalFormalParameter_identifier != null)
         _result["normalFormalParameter_identifier"] =
             normalFormalParameter_identifier.toJson();
@@ -15405,6 +15690,12 @@
       if (normalFormalParameter_covariantKeyword != 0)
         _result["normalFormalParameter_covariantKeyword"] =
             normalFormalParameter_covariantKeyword;
+      if (simpleFormalParameter_type2 != null)
+        _result["simpleFormalParameter_type2"] =
+            simpleFormalParameter_type2.toJson();
+      if (normalFormalParameter_isCovariant != false)
+        _result["normalFormalParameter_isCovariant"] =
+            normalFormalParameter_isCovariant;
       if (normalFormalParameter_identifier != null)
         _result["normalFormalParameter_identifier"] =
             normalFormalParameter_identifier.toJson();
@@ -15832,6 +16123,9 @@
             genericFunctionType_formalParameters.toJson();
       if (genericFunctionType_question != 0)
         _result["genericFunctionType_question"] = genericFunctionType_question;
+      if (genericFunctionType_returnType2 != null)
+        _result["genericFunctionType_returnType2"] =
+            genericFunctionType_returnType2.toJson();
     }
     if (kind == idl.LinkedNodeKind.ifElement) {
       if (ifMixin_condition != null)
@@ -16519,6 +16813,7 @@
             classOrMixinDeclaration_rightBracket,
         "classOrMixinDeclaration_leftBracket":
             classOrMixinDeclaration_leftBracket,
+        "classDeclaration_isDartObject": classDeclaration_isDartObject,
         "classOrMixinDeclaration_implementsClause":
             classOrMixinDeclaration_implementsClause,
         "classOrMixinDeclaration_members": classOrMixinDeclaration_members,
@@ -16589,6 +16884,7 @@
         "functionDeclaration_returnType": functionDeclaration_returnType,
         "functionDeclaration_propertyKeyword":
             functionDeclaration_propertyKeyword,
+        "functionDeclaration_returnType2": functionDeclaration_returnType2,
         "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -16604,6 +16900,7 @@
         "functionTypeAlias_typeParameters": functionTypeAlias_typeParameters,
         "typeAlias_typedefKeyword": typeAlias_typedefKeyword,
         "typeAlias_semicolon": typeAlias_semicolon,
+        "functionTypeAlias_returnType2": functionTypeAlias_returnType2,
         "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -16646,6 +16943,8 @@
         "methodDeclaration_modifierKeyword": methodDeclaration_modifierKeyword,
         "methodDeclaration_operatorKeyword": methodDeclaration_operatorKeyword,
         "methodDeclaration_propertyKeyword": methodDeclaration_propertyKeyword,
+        "methodDeclaration_actualProperty": methodDeclaration_actualProperty,
+        "methodDeclaration_returnType2": methodDeclaration_returnType2,
         "methodDeclaration_typeParameters": methodDeclaration_typeParameters,
         "methodDeclaration_name": methodDeclaration_name,
         "isSynthetic": isSynthetic,
@@ -16732,8 +17031,10 @@
         "variableDeclaration_initializer": variableDeclaration_initializer,
         "variableDeclaration_equals": variableDeclaration_equals,
         "variableDeclaration_name": variableDeclaration_name,
+        "variableDeclaration_type2": variableDeclaration_type2,
         "isSynthetic": isSynthetic,
         "kind": kind,
+        "variableDeclaration_declaration": variableDeclaration_declaration,
       };
     }
     if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
@@ -16749,6 +17050,8 @@
         "fieldFormalParameter_thisKeyword": fieldFormalParameter_thisKeyword,
         "normalFormalParameter_covariantKeyword":
             normalFormalParameter_covariantKeyword,
+        "fieldFormalParameter_type2": fieldFormalParameter_type2,
+        "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
         "normalFormalParameter_identifier": normalFormalParameter_identifier,
         "formalParameter_kind": formalParameter_kind,
         "normalFormalParameter_comment": normalFormalParameter_comment,
@@ -16767,6 +17070,7 @@
             functionTypedFormalParameter_typeParameters,
         "normalFormalParameter_covariantKeyword":
             normalFormalParameter_covariantKeyword,
+        "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
         "normalFormalParameter_identifier": normalFormalParameter_identifier,
         "formalParameter_kind": formalParameter_kind,
         "normalFormalParameter_comment": normalFormalParameter_comment,
@@ -16781,6 +17085,8 @@
         "simpleFormalParameter_keyword": simpleFormalParameter_keyword,
         "normalFormalParameter_covariantKeyword":
             normalFormalParameter_covariantKeyword,
+        "simpleFormalParameter_type2": simpleFormalParameter_type2,
+        "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
         "normalFormalParameter_identifier": normalFormalParameter_identifier,
         "formalParameter_kind": formalParameter_kind,
         "normalFormalParameter_comment": normalFormalParameter_comment,
@@ -17143,6 +17449,7 @@
         "genericFunctionType_formalParameters":
             genericFunctionType_formalParameters,
         "genericFunctionType_question": genericFunctionType_question,
+        "genericFunctionType_returnType2": genericFunctionType_returnType2,
         "isSynthetic": isSynthetic,
         "kind": kind,
       };
@@ -17547,58 +17854,53 @@
 class LinkedNodeBundleBuilder extends Object
     with _LinkedNodeBundleMixin
     implements idl.LinkedNodeBundle {
-  LinkedNodeBuilder _node;
-  LinkedNodeReferenceBuilder _references;
-  UnlinkedTokensBuilder _tokens;
+  List<LinkedNodeLibraryBuilder> _libraries;
+  LinkedNodeReferencesBuilder _references;
 
   @override
-  LinkedNodeBuilder get node => _node;
+  List<LinkedNodeLibraryBuilder> get libraries =>
+      _libraries ??= <LinkedNodeLibraryBuilder>[];
 
-  void set node(LinkedNodeBuilder value) {
-    this._node = value;
+  void set libraries(List<LinkedNodeLibraryBuilder> value) {
+    this._libraries = value;
   }
 
   @override
-  LinkedNodeReferenceBuilder get references => _references;
+  LinkedNodeReferencesBuilder get references => _references;
 
-  void set references(LinkedNodeReferenceBuilder value) {
+  /// The shared list of references used in the [libraries].
+  void set references(LinkedNodeReferencesBuilder value) {
     this._references = value;
   }
 
-  @override
-  UnlinkedTokensBuilder get tokens => _tokens;
-
-  void set tokens(UnlinkedTokensBuilder value) {
-    this._tokens = value;
-  }
-
   LinkedNodeBundleBuilder(
-      {LinkedNodeBuilder node,
-      LinkedNodeReferenceBuilder references,
-      UnlinkedTokensBuilder tokens})
-      : _node = node,
-        _references = references,
-        _tokens = tokens;
+      {List<LinkedNodeLibraryBuilder> libraries,
+      LinkedNodeReferencesBuilder references})
+      : _libraries = libraries,
+        _references = references;
 
   /**
    * Flush [informative] data recursively.
    */
   void flushInformative() {
-    _node?.flushInformative();
+    _libraries?.forEach((b) => b.flushInformative());
     _references?.flushInformative();
-    _tokens?.flushInformative();
   }
 
   /**
    * Accumulate non-[informative] data into [signature].
    */
   void collectApiSignature(api_sig.ApiSignature signature) {
-    signature.addBool(this._tokens != null);
-    this._tokens?.collectApiSignature(signature);
     signature.addBool(this._references != null);
     this._references?.collectApiSignature(signature);
-    signature.addBool(this._node != null);
-    this._node?.collectApiSignature(signature);
+    if (this._libraries == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._libraries.length);
+      for (var x in this._libraries) {
+        x?.collectApiSignature(signature);
+      }
+    }
   }
 
   List<int> toBuffer() {
@@ -17607,27 +17909,21 @@
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
-    fb.Offset offset_node;
+    fb.Offset offset_libraries;
     fb.Offset offset_references;
-    fb.Offset offset_tokens;
-    if (_node != null) {
-      offset_node = _node.finish(fbBuilder);
+    if (!(_libraries == null || _libraries.isEmpty)) {
+      offset_libraries = fbBuilder
+          .writeList(_libraries.map((b) => b.finish(fbBuilder)).toList());
     }
     if (_references != null) {
       offset_references = _references.finish(fbBuilder);
     }
-    if (_tokens != null) {
-      offset_tokens = _tokens.finish(fbBuilder);
-    }
     fbBuilder.startTable();
-    if (offset_node != null) {
-      fbBuilder.addOffset(2, offset_node);
+    if (offset_libraries != null) {
+      fbBuilder.addOffset(1, offset_libraries);
     }
     if (offset_references != null) {
-      fbBuilder.addOffset(1, offset_references);
-    }
-    if (offset_tokens != null) {
-      fbBuilder.addOffset(0, offset_tokens);
+      fbBuilder.addOffset(0, offset_references);
     }
     return fbBuilder.endTable();
   }
@@ -17654,55 +17950,283 @@
 
   _LinkedNodeBundleImpl(this._bc, this._bcOffset);
 
-  idl.LinkedNode _node;
-  idl.LinkedNodeReference _references;
-  idl.UnlinkedTokens _tokens;
+  List<idl.LinkedNodeLibrary> _libraries;
+  idl.LinkedNodeReferences _references;
 
   @override
-  idl.LinkedNode get node {
-    _node ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 2, null);
-    return _node;
+  List<idl.LinkedNodeLibrary> get libraries {
+    _libraries ??= const fb.ListReader<idl.LinkedNodeLibrary>(
+            const _LinkedNodeLibraryReader())
+        .vTableGet(_bc, _bcOffset, 1, const <idl.LinkedNodeLibrary>[]);
+    return _libraries;
   }
 
   @override
-  idl.LinkedNodeReference get references {
+  idl.LinkedNodeReferences get references {
     _references ??=
-        const _LinkedNodeReferenceReader().vTableGet(_bc, _bcOffset, 1, null);
+        const _LinkedNodeReferencesReader().vTableGet(_bc, _bcOffset, 0, null);
     return _references;
   }
-
-  @override
-  idl.UnlinkedTokens get tokens {
-    _tokens ??=
-        const _UnlinkedTokensReader().vTableGet(_bc, _bcOffset, 0, null);
-    return _tokens;
-  }
 }
 
 abstract class _LinkedNodeBundleMixin implements idl.LinkedNodeBundle {
   @override
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
-    if (node != null) _result["node"] = node.toJson();
+    if (libraries.isNotEmpty)
+      _result["libraries"] =
+          libraries.map((_value) => _value.toJson()).toList();
     if (references != null) _result["references"] = references.toJson();
-    if (tokens != null) _result["tokens"] = tokens.toJson();
     return _result;
   }
 
   @override
   Map<String, Object> toMap() => {
-        "node": node,
+        "libraries": libraries,
         "references": references,
-        "tokens": tokens,
       };
 
   @override
   String toString() => convert.json.encode(toJson());
 }
 
-class LinkedNodeReferenceBuilder extends Object
-    with _LinkedNodeReferenceMixin
-    implements idl.LinkedNodeReference {
+class LinkedNodeLibraryBuilder extends Object
+    with _LinkedNodeLibraryMixin
+    implements idl.LinkedNodeLibrary {
+  List<int> _exports;
+  String _name;
+  int _nameLength;
+  int _nameOffset;
+  List<LinkedNodeUnitBuilder> _units;
+  String _uriStr;
+
+  @override
+  List<int> get exports => _exports ??= <int>[];
+
+  void set exports(List<int> value) {
+    assert(value == null || value.every((e) => e >= 0));
+    this._exports = value;
+  }
+
+  @override
+  String get name => _name ??= '';
+
+  void set name(String value) {
+    this._name = value;
+  }
+
+  @override
+  int get nameLength => _nameLength ??= 0;
+
+  void set nameLength(int value) {
+    assert(value == null || value >= 0);
+    this._nameLength = value;
+  }
+
+  @override
+  int get nameOffset => _nameOffset ??= 0;
+
+  void set nameOffset(int value) {
+    assert(value == null || value >= 0);
+    this._nameOffset = value;
+  }
+
+  @override
+  List<LinkedNodeUnitBuilder> get units => _units ??= <LinkedNodeUnitBuilder>[];
+
+  void set units(List<LinkedNodeUnitBuilder> value) {
+    this._units = value;
+  }
+
+  @override
+  String get uriStr => _uriStr ??= '';
+
+  void set uriStr(String value) {
+    this._uriStr = value;
+  }
+
+  LinkedNodeLibraryBuilder(
+      {List<int> exports,
+      String name,
+      int nameLength,
+      int nameOffset,
+      List<LinkedNodeUnitBuilder> units,
+      String uriStr})
+      : _exports = exports,
+        _name = name,
+        _nameLength = nameLength,
+        _nameOffset = nameOffset,
+        _units = units,
+        _uriStr = uriStr;
+
+  /**
+   * Flush [informative] data recursively.
+   */
+  void flushInformative() {
+    _units?.forEach((b) => b.flushInformative());
+  }
+
+  /**
+   * Accumulate non-[informative] data into [signature].
+   */
+  void collectApiSignature(api_sig.ApiSignature signature) {
+    signature.addString(this._uriStr ?? '');
+    if (this._units == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._units.length);
+      for (var x in this._units) {
+        x?.collectApiSignature(signature);
+      }
+    }
+    if (this._exports == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._exports.length);
+      for (var x in this._exports) {
+        signature.addInt(x);
+      }
+    }
+    signature.addString(this._name ?? '');
+    signature.addInt(this._nameOffset ?? 0);
+    signature.addInt(this._nameLength ?? 0);
+  }
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_exports;
+    fb.Offset offset_name;
+    fb.Offset offset_units;
+    fb.Offset offset_uriStr;
+    if (!(_exports == null || _exports.isEmpty)) {
+      offset_exports = fbBuilder.writeListUint32(_exports);
+    }
+    if (_name != null) {
+      offset_name = fbBuilder.writeString(_name);
+    }
+    if (!(_units == null || _units.isEmpty)) {
+      offset_units =
+          fbBuilder.writeList(_units.map((b) => b.finish(fbBuilder)).toList());
+    }
+    if (_uriStr != null) {
+      offset_uriStr = fbBuilder.writeString(_uriStr);
+    }
+    fbBuilder.startTable();
+    if (offset_exports != null) {
+      fbBuilder.addOffset(2, offset_exports);
+    }
+    if (offset_name != null) {
+      fbBuilder.addOffset(3, offset_name);
+    }
+    if (_nameLength != null && _nameLength != 0) {
+      fbBuilder.addUint32(5, _nameLength);
+    }
+    if (_nameOffset != null && _nameOffset != 0) {
+      fbBuilder.addUint32(4, _nameOffset);
+    }
+    if (offset_units != null) {
+      fbBuilder.addOffset(1, offset_units);
+    }
+    if (offset_uriStr != null) {
+      fbBuilder.addOffset(0, offset_uriStr);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+class _LinkedNodeLibraryReader extends fb.TableReader<_LinkedNodeLibraryImpl> {
+  const _LinkedNodeLibraryReader();
+
+  @override
+  _LinkedNodeLibraryImpl createObject(fb.BufferContext bc, int offset) =>
+      new _LinkedNodeLibraryImpl(bc, offset);
+}
+
+class _LinkedNodeLibraryImpl extends Object
+    with _LinkedNodeLibraryMixin
+    implements idl.LinkedNodeLibrary {
+  final fb.BufferContext _bc;
+  final int _bcOffset;
+
+  _LinkedNodeLibraryImpl(this._bc, this._bcOffset);
+
+  List<int> _exports;
+  String _name;
+  int _nameLength;
+  int _nameOffset;
+  List<idl.LinkedNodeUnit> _units;
+  String _uriStr;
+
+  @override
+  List<int> get exports {
+    _exports ??=
+        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 2, const <int>[]);
+    return _exports;
+  }
+
+  @override
+  String get name {
+    _name ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 3, '');
+    return _name;
+  }
+
+  @override
+  int get nameLength {
+    _nameLength ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 5, 0);
+    return _nameLength;
+  }
+
+  @override
+  int get nameOffset {
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 4, 0);
+    return _nameOffset;
+  }
+
+  @override
+  List<idl.LinkedNodeUnit> get units {
+    _units ??=
+        const fb.ListReader<idl.LinkedNodeUnit>(const _LinkedNodeUnitReader())
+            .vTableGet(_bc, _bcOffset, 1, const <idl.LinkedNodeUnit>[]);
+    return _units;
+  }
+
+  @override
+  String get uriStr {
+    _uriStr ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
+    return _uriStr;
+  }
+}
+
+abstract class _LinkedNodeLibraryMixin implements idl.LinkedNodeLibrary {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (exports.isNotEmpty) _result["exports"] = exports;
+    if (name != '') _result["name"] = name;
+    if (nameLength != 0) _result["nameLength"] = nameLength;
+    if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+    if (units.isNotEmpty)
+      _result["units"] = units.map((_value) => _value.toJson()).toList();
+    if (uriStr != '') _result["uriStr"] = uriStr;
+    return _result;
+  }
+
+  @override
+  Map<String, Object> toMap() => {
+        "exports": exports,
+        "name": name,
+        "nameLength": nameLength,
+        "nameOffset": nameOffset,
+        "units": units,
+        "uriStr": uriStr,
+      };
+
+  @override
+  String toString() => convert.json.encode(toJson());
+}
+
+class LinkedNodeReferencesBuilder extends Object
+    with _LinkedNodeReferencesMixin
+    implements idl.LinkedNodeReferences {
   List<String> _name;
   List<int> _parent;
 
@@ -17721,7 +18245,7 @@
     this._parent = value;
   }
 
-  LinkedNodeReferenceBuilder({List<String> name, List<int> parent})
+  LinkedNodeReferencesBuilder({List<String> name, List<int> parent})
       : _name = name,
         _parent = parent;
 
@@ -17773,22 +18297,22 @@
   }
 }
 
-class _LinkedNodeReferenceReader
-    extends fb.TableReader<_LinkedNodeReferenceImpl> {
-  const _LinkedNodeReferenceReader();
+class _LinkedNodeReferencesReader
+    extends fb.TableReader<_LinkedNodeReferencesImpl> {
+  const _LinkedNodeReferencesReader();
 
   @override
-  _LinkedNodeReferenceImpl createObject(fb.BufferContext bc, int offset) =>
-      new _LinkedNodeReferenceImpl(bc, offset);
+  _LinkedNodeReferencesImpl createObject(fb.BufferContext bc, int offset) =>
+      new _LinkedNodeReferencesImpl(bc, offset);
 }
 
-class _LinkedNodeReferenceImpl extends Object
-    with _LinkedNodeReferenceMixin
-    implements idl.LinkedNodeReference {
+class _LinkedNodeReferencesImpl extends Object
+    with _LinkedNodeReferencesMixin
+    implements idl.LinkedNodeReferences {
   final fb.BufferContext _bc;
   final int _bcOffset;
 
-  _LinkedNodeReferenceImpl(this._bc, this._bcOffset);
+  _LinkedNodeReferencesImpl(this._bc, this._bcOffset);
 
   List<String> _name;
   List<int> _parent;
@@ -17808,7 +18332,7 @@
   }
 }
 
-abstract class _LinkedNodeReferenceMixin implements idl.LinkedNodeReference {
+abstract class _LinkedNodeReferencesMixin implements idl.LinkedNodeReferences {
   @override
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
@@ -17842,7 +18366,7 @@
   List<int> get functionFormalParameters =>
       _functionFormalParameters ??= <int>[];
 
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   void set functionFormalParameters(List<int> value) {
     assert(value == null || value.every((e) => e >= 0));
     this._functionFormalParameters = value;
@@ -17858,7 +18382,7 @@
   @override
   List<int> get functionTypeParameters => _functionTypeParameters ??= <int>[];
 
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   void set functionTypeParameters(List<int> value) {
     assert(value == null || value.every((e) => e >= 0));
     this._functionTypeParameters = value;
@@ -17867,7 +18391,7 @@
   @override
   int get interfaceClass => _interfaceClass ??= 0;
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   void set interfaceClass(int value) {
     assert(value == null || value >= 0);
     this._interfaceClass = value;
@@ -17891,7 +18415,7 @@
   @override
   int get typeParameterParameter => _typeParameterParameter ??= 0;
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   void set typeParameterParameter(int value) {
     assert(value == null || value >= 0);
     this._typeParameterParameter = value;
@@ -18113,6 +18637,302 @@
   String toString() => convert.json.encode(toJson());
 }
 
+class LinkedNodeUnitBuilder extends Object
+    with _LinkedNodeUnitMixin
+    implements idl.LinkedNodeUnit {
+  LinkedNodeBuilder _node;
+  UnlinkedTokensBuilder _tokens;
+  String _uriStr;
+
+  @override
+  LinkedNodeBuilder get node => _node;
+
+  void set node(LinkedNodeBuilder value) {
+    this._node = value;
+  }
+
+  @override
+  UnlinkedTokensBuilder get tokens => _tokens;
+
+  void set tokens(UnlinkedTokensBuilder value) {
+    this._tokens = value;
+  }
+
+  @override
+  String get uriStr => _uriStr ??= '';
+
+  void set uriStr(String value) {
+    this._uriStr = value;
+  }
+
+  LinkedNodeUnitBuilder(
+      {LinkedNodeBuilder node, UnlinkedTokensBuilder tokens, String uriStr})
+      : _node = node,
+        _tokens = tokens,
+        _uriStr = uriStr;
+
+  /**
+   * Flush [informative] data recursively.
+   */
+  void flushInformative() {
+    _node?.flushInformative();
+    _tokens?.flushInformative();
+  }
+
+  /**
+   * Accumulate non-[informative] data into [signature].
+   */
+  void collectApiSignature(api_sig.ApiSignature signature) {
+    signature.addString(this._uriStr ?? '');
+    signature.addBool(this._tokens != null);
+    this._tokens?.collectApiSignature(signature);
+    signature.addBool(this._node != null);
+    this._node?.collectApiSignature(signature);
+  }
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_node;
+    fb.Offset offset_tokens;
+    fb.Offset offset_uriStr;
+    if (_node != null) {
+      offset_node = _node.finish(fbBuilder);
+    }
+    if (_tokens != null) {
+      offset_tokens = _tokens.finish(fbBuilder);
+    }
+    if (_uriStr != null) {
+      offset_uriStr = fbBuilder.writeString(_uriStr);
+    }
+    fbBuilder.startTable();
+    if (offset_node != null) {
+      fbBuilder.addOffset(2, offset_node);
+    }
+    if (offset_tokens != null) {
+      fbBuilder.addOffset(1, offset_tokens);
+    }
+    if (offset_uriStr != null) {
+      fbBuilder.addOffset(0, offset_uriStr);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+class _LinkedNodeUnitReader extends fb.TableReader<_LinkedNodeUnitImpl> {
+  const _LinkedNodeUnitReader();
+
+  @override
+  _LinkedNodeUnitImpl createObject(fb.BufferContext bc, int offset) =>
+      new _LinkedNodeUnitImpl(bc, offset);
+}
+
+class _LinkedNodeUnitImpl extends Object
+    with _LinkedNodeUnitMixin
+    implements idl.LinkedNodeUnit {
+  final fb.BufferContext _bc;
+  final int _bcOffset;
+
+  _LinkedNodeUnitImpl(this._bc, this._bcOffset);
+
+  idl.LinkedNode _node;
+  idl.UnlinkedTokens _tokens;
+  String _uriStr;
+
+  @override
+  idl.LinkedNode get node {
+    _node ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 2, null);
+    return _node;
+  }
+
+  @override
+  idl.UnlinkedTokens get tokens {
+    _tokens ??=
+        const _UnlinkedTokensReader().vTableGet(_bc, _bcOffset, 1, null);
+    return _tokens;
+  }
+
+  @override
+  String get uriStr {
+    _uriStr ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
+    return _uriStr;
+  }
+}
+
+abstract class _LinkedNodeUnitMixin implements idl.LinkedNodeUnit {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (node != null) _result["node"] = node.toJson();
+    if (tokens != null) _result["tokens"] = tokens.toJson();
+    if (uriStr != '') _result["uriStr"] = uriStr;
+    return _result;
+  }
+
+  @override
+  Map<String, Object> toMap() => {
+        "node": node,
+        "tokens": tokens,
+        "uriStr": uriStr,
+      };
+
+  @override
+  String toString() => convert.json.encode(toJson());
+}
+
+class LinkedNodeVariablesDeclarationBuilder extends Object
+    with _LinkedNodeVariablesDeclarationMixin
+    implements idl.LinkedNodeVariablesDeclaration {
+  LinkedNodeBuilder _comment;
+  bool _isConst;
+  bool _isFinal;
+  bool _isStatic;
+
+  @override
+  LinkedNodeBuilder get comment => _comment;
+
+  void set comment(LinkedNodeBuilder value) {
+    this._comment = value;
+  }
+
+  @override
+  bool get isConst => _isConst ??= false;
+
+  void set isConst(bool value) {
+    this._isConst = value;
+  }
+
+  @override
+  bool get isFinal => _isFinal ??= false;
+
+  void set isFinal(bool value) {
+    this._isFinal = value;
+  }
+
+  @override
+  bool get isStatic => _isStatic ??= false;
+
+  void set isStatic(bool value) {
+    this._isStatic = value;
+  }
+
+  LinkedNodeVariablesDeclarationBuilder(
+      {LinkedNodeBuilder comment, bool isConst, bool isFinal, bool isStatic})
+      : _comment = comment,
+        _isConst = isConst,
+        _isFinal = isFinal,
+        _isStatic = isStatic;
+
+  /**
+   * Flush [informative] data recursively.
+   */
+  void flushInformative() {
+    _comment?.flushInformative();
+  }
+
+  /**
+   * Accumulate non-[informative] data into [signature].
+   */
+  void collectApiSignature(api_sig.ApiSignature signature) {
+    signature.addBool(this._isConst == true);
+    signature.addBool(this._isFinal == true);
+    signature.addBool(this._isStatic == true);
+    signature.addBool(this._comment != null);
+    this._comment?.collectApiSignature(signature);
+  }
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_comment;
+    if (_comment != null) {
+      offset_comment = _comment.finish(fbBuilder);
+    }
+    fbBuilder.startTable();
+    if (offset_comment != null) {
+      fbBuilder.addOffset(3, offset_comment);
+    }
+    if (_isConst == true) {
+      fbBuilder.addBool(0, true);
+    }
+    if (_isFinal == true) {
+      fbBuilder.addBool(1, true);
+    }
+    if (_isStatic == true) {
+      fbBuilder.addBool(2, true);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+class _LinkedNodeVariablesDeclarationReader
+    extends fb.TableReader<_LinkedNodeVariablesDeclarationImpl> {
+  const _LinkedNodeVariablesDeclarationReader();
+
+  @override
+  _LinkedNodeVariablesDeclarationImpl createObject(
+          fb.BufferContext bc, int offset) =>
+      new _LinkedNodeVariablesDeclarationImpl(bc, offset);
+}
+
+class _LinkedNodeVariablesDeclarationImpl extends Object
+    with _LinkedNodeVariablesDeclarationMixin
+    implements idl.LinkedNodeVariablesDeclaration {
+  final fb.BufferContext _bc;
+  final int _bcOffset;
+
+  _LinkedNodeVariablesDeclarationImpl(this._bc, this._bcOffset);
+
+  idl.LinkedNode _comment;
+  bool _isConst;
+  bool _isFinal;
+  bool _isStatic;
+
+  @override
+  idl.LinkedNode get comment {
+    _comment ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 3, null);
+    return _comment;
+  }
+
+  @override
+  bool get isConst {
+    _isConst ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 0, false);
+    return _isConst;
+  }
+
+  @override
+  bool get isFinal {
+    _isFinal ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 1, false);
+    return _isFinal;
+  }
+
+  @override
+  bool get isStatic {
+    _isStatic ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 2, false);
+    return _isStatic;
+  }
+}
+
+abstract class _LinkedNodeVariablesDeclarationMixin
+    implements idl.LinkedNodeVariablesDeclaration {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (comment != null) _result["comment"] = comment.toJson();
+    if (isConst != false) _result["isConst"] = isConst;
+    if (isFinal != false) _result["isFinal"] = isFinal;
+    if (isStatic != false) _result["isStatic"] = isStatic;
+    return _result;
+  }
+
+  @override
+  Map<String, Object> toMap() => {
+        "comment": comment,
+        "isConst": isConst,
+        "isFinal": isFinal,
+        "isStatic": isStatic,
+      };
+
+  @override
+  String toString() => convert.json.encode(toJson());
+}
+
 class LinkedReferenceBuilder extends Object
     with _LinkedReferenceMixin
     implements idl.LinkedReference {
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index bb8bc6b..6cd172f 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -398,6 +398,8 @@
 
   function,
 
+  genericTypeAlias,
+
   interface,
 
   typeParameter,
@@ -970,7 +972,26 @@
 
   /// Pop the top 2 values from the stack, place them in a [MapLiteralEntry],
   /// and push the result back onto the stack.
-  makeMapLiteralEntry
+  makeMapLiteralEntry,
+
+  /// Pop the top value from the stack, convert it to a spread element of type
+  /// `...`, and push the result back onto the stack.
+  spreadElement,
+
+  /// Pop the top value from the stack, convert it to a spread element of type
+  /// `...?`, and push the result back onto the stack.
+  nullAwareSpreadElement,
+
+  /// Pop the top two values from the stack.  The first is a condition
+  /// and the second is a collection element.  Push an "if" element having the
+  /// given condition, with the collection element as its "then" clause.
+  ifElement,
+
+  /// Pop the top three values from the stack.  The first is a condition and the
+  /// other two are collection elements.  Push an "if" element having the given
+  /// condition, with the two collection elements as its "then" and "else"
+  /// clauses, respectively.
+  ifElseElement
 }
 
 /// Enum used to indicate the kind of a parameter.
@@ -1791,19 +1812,36 @@
   variantField_20:string (id: 20);
 
   variantField_22:string (id: 22);
+
+  variantField_32:LinkedNodeVariablesDeclaration (id: 32);
 }
 
-/// TODO(scheglov) extend to support multiple libraries or remove
+/// Information about a group of libraries linked together, for example because
+/// they form a single cycle, or because they represent a single build artifact.
 table LinkedNodeBundle {
-  node:LinkedNode (id: 2);
+  libraries:[LinkedNodeLibrary] (id: 1);
 
-  references:LinkedNodeReference (id: 1);
+  /// The shared list of references used in the [libraries].
+  references:LinkedNodeReferences (id: 0);
+}
 
-  tokens:UnlinkedTokens (id: 0);
+/// Information about a single library in a [LinkedNodeBundle].
+table LinkedNodeLibrary {
+  exports:[uint] (id: 2);
+
+  name:string (id: 3);
+
+  nameLength:uint (id: 5);
+
+  nameOffset:uint (id: 4);
+
+  units:[LinkedNodeUnit] (id: 1);
+
+  uriStr:string (id: 0);
 }
 
 /// Flattened tree of declarations referenced from [LinkedNode]s.
-table LinkedNodeReference {
+table LinkedNodeReferences {
   name:[string] (id: 1);
 
   parent:[uint] (id: 0);
@@ -1811,25 +1849,46 @@
 
 /// Information about a Dart type.
 table LinkedNodeType {
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   functionFormalParameters:[uint] (id: 0);
 
   functionReturnType:LinkedNodeType (id: 1);
 
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   functionTypeParameters:[uint] (id: 2);
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   interfaceClass:uint (id: 3);
 
   interfaceTypeArguments:[LinkedNodeType] (id: 4);
 
   kind:LinkedNodeTypeKind (id: 5);
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   typeParameterParameter:uint (id: 6);
 }
 
+/// Information about a single library in a [LinkedNodeLibrary].
+table LinkedNodeUnit {
+  node:LinkedNode (id: 2);
+
+  tokens:UnlinkedTokens (id: 1);
+
+  uriStr:string (id: 0);
+}
+
+/// Information about a top-level declaration, or a field declaration that
+/// contributes information to [LinkedNodeKind.variableDeclaration].
+table LinkedNodeVariablesDeclaration {
+  comment:LinkedNode (id: 3);
+
+  isConst:bool (id: 0);
+
+  isFinal:bool (id: 1);
+
+  isStatic:bool (id: 2);
+}
+
 /// Information about the resolution of an [UnlinkedReference].
 table LinkedReference {
   /// If this [LinkedReference] doesn't have an associated [UnlinkedReference],
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index b25b830..c9e84f8 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -987,6 +987,9 @@
   @VariantId(6, variant: LinkedNodeKind.classDeclaration)
   LinkedNode get classDeclaration_extendsClause;
 
+  @VariantId(27, variant: LinkedNodeKind.classDeclaration)
+  bool get classDeclaration_isDartObject;
+
   @VariantId(7, variant: LinkedNodeKind.classDeclaration)
   LinkedNode get classDeclaration_withClause;
 
@@ -1338,6 +1341,9 @@
   @VariantId(6, variant: LinkedNodeKind.fieldFormalParameter)
   LinkedNode get fieldFormalParameter_type;
 
+  @VariantId(24, variant: LinkedNodeKind.fieldFormalParameter)
+  LinkedNodeType get fieldFormalParameter_type2;
+
   @VariantId(7, variant: LinkedNodeKind.fieldFormalParameter)
   LinkedNode get fieldFormalParameter_typeParameters;
 
@@ -1459,6 +1465,9 @@
   @VariantId(7, variant: LinkedNodeKind.functionDeclaration)
   LinkedNode get functionDeclaration_returnType;
 
+  @VariantId(24, variant: LinkedNodeKind.functionDeclaration)
+  LinkedNodeType get functionDeclaration_returnType2;
+
   @VariantId(6, variant: LinkedNodeKind.functionDeclarationStatement)
   LinkedNode get functionDeclarationStatement_functionDeclaration;
 
@@ -1480,6 +1489,9 @@
   @VariantId(7, variant: LinkedNodeKind.functionTypeAlias)
   LinkedNode get functionTypeAlias_returnType;
 
+  @VariantId(24, variant: LinkedNodeKind.functionTypeAlias)
+  LinkedNodeType get functionTypeAlias_returnType2;
+
   @VariantId(8, variant: LinkedNodeKind.functionTypeAlias)
   LinkedNode get functionTypeAlias_typeParameters;
 
@@ -1504,6 +1516,9 @@
   @VariantId(7, variant: LinkedNodeKind.genericFunctionType)
   LinkedNode get genericFunctionType_returnType;
 
+  @VariantId(24, variant: LinkedNodeKind.genericFunctionType)
+  LinkedNodeType get genericFunctionType_returnType2;
+
   @VariantId(6, variant: LinkedNodeKind.genericFunctionType)
   LinkedNode get genericFunctionType_typeParameters;
 
@@ -1696,6 +1711,9 @@
   @VariantId(7, variant: LinkedNodeKind.mapLiteralEntry)
   LinkedNode get mapLiteralEntry_value;
 
+  @VariantId(19, variant: LinkedNodeKind.methodDeclaration)
+  int get methodDeclaration_actualProperty;
+
   @VariantId(6, variant: LinkedNodeKind.methodDeclaration)
   LinkedNode get methodDeclaration_body;
 
@@ -1720,6 +1738,9 @@
   @VariantId(8, variant: LinkedNodeKind.methodDeclaration)
   LinkedNode get methodDeclaration_returnType;
 
+  @VariantId(24, variant: LinkedNodeKind.methodDeclaration)
+  LinkedNodeType get methodDeclaration_returnType2;
+
   @VariantId(9, variant: LinkedNodeKind.methodDeclaration)
   LinkedNode get methodDeclaration_typeParameters;
 
@@ -1804,6 +1825,13 @@
   ])
   LinkedNode get normalFormalParameter_identifier;
 
+  @VariantId(27, variantList: [
+    LinkedNodeKind.fieldFormalParameter,
+    LinkedNodeKind.functionTypedFormalParameter,
+    LinkedNodeKind.simpleFormalParameter,
+  ])
+  bool get normalFormalParameter_isCovariant;
+
   @VariantId(4, variantList: [
     LinkedNodeKind.fieldFormalParameter,
     LinkedNodeKind.functionTypedFormalParameter,
@@ -1931,6 +1959,9 @@
   @VariantId(6, variant: LinkedNodeKind.simpleFormalParameter)
   LinkedNode get simpleFormalParameter_type;
 
+  @VariantId(24, variant: LinkedNodeKind.simpleFormalParameter)
+  LinkedNodeType get simpleFormalParameter_type2;
+
   @VariantId(15, variant: LinkedNodeKind.simpleIdentifier)
   int get simpleIdentifier_element;
 
@@ -2140,6 +2171,9 @@
   ])
   int get uriBasedDirective_uriElement;
 
+  @VariantId(32, variant: LinkedNodeKind.variableDeclaration)
+  LinkedNodeVariablesDeclaration get variableDeclaration_declaration;
+
   @VariantId(15, variant: LinkedNodeKind.variableDeclaration)
   int get variableDeclaration_equals;
 
@@ -2149,6 +2183,9 @@
   @VariantId(7, variant: LinkedNodeKind.variableDeclaration)
   LinkedNode get variableDeclaration_name;
 
+  @VariantId(24, variant: LinkedNodeKind.variableDeclaration)
+  LinkedNodeType get variableDeclaration_type2;
+
   @VariantId(15, variant: LinkedNodeKind.variableDeclarationList)
   int get variableDeclarationList_keyword;
 
@@ -2198,20 +2235,19 @@
   int get yieldStatement_yieldKeyword;
 }
 
-/// TODO(scheglov) extend to support multiple libraries or remove
+/// Information about a group of libraries linked together, for example because
+/// they form a single cycle, or because they represent a single build artifact.
 @TopLevel('LNBn')
 abstract class LinkedNodeBundle extends base.SummaryClass {
   factory LinkedNodeBundle.fromBuffer(List<int> buffer) =>
       generated.readLinkedNodeBundle(buffer);
 
-  @Id(2)
-  LinkedNode get node;
-
   @Id(1)
-  LinkedNodeReference get references;
+  List<LinkedNodeLibrary> get libraries;
 
+  /// The shared list of references used in the [libraries].
   @Id(0)
-  UnlinkedTokens get tokens;
+  LinkedNodeReferences get references;
 }
 
 /// Types of comments.
@@ -2344,8 +2380,29 @@
   yieldStatement,
 }
 
+/// Information about a single library in a [LinkedNodeBundle].
+abstract class LinkedNodeLibrary extends base.SummaryClass {
+  @Id(2)
+  List<int> get exports;
+
+  @Id(3)
+  String get name;
+
+  @Id(5)
+  int get nameLength;
+
+  @Id(4)
+  int get nameOffset;
+
+  @Id(1)
+  List<LinkedNodeUnit> get units;
+
+  @Id(0)
+  String get uriStr;
+}
+
 /// Flattened tree of declarations referenced from [LinkedNode]s.
-abstract class LinkedNodeReference extends base.SummaryClass {
+abstract class LinkedNodeReferences extends base.SummaryClass {
   @Id(1)
   List<String> get name;
 
@@ -2355,18 +2412,18 @@
 
 /// Information about a Dart type.
 abstract class LinkedNodeType extends base.SummaryClass {
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   @Id(0)
   List<int> get functionFormalParameters;
 
   @Id(1)
   LinkedNodeType get functionReturnType;
 
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   @Id(2)
   List<int> get functionTypeParameters;
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   @Id(3)
   int get interfaceClass;
 
@@ -2376,7 +2433,7 @@
   @Id(5)
   LinkedNodeTypeKind get kind;
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   @Id(6)
   int get typeParameterParameter;
 }
@@ -2386,11 +2443,40 @@
   bottom,
   dynamic_,
   function,
+  genericTypeAlias,
   interface,
   typeParameter,
   void_
 }
 
+/// Information about a single library in a [LinkedNodeLibrary].
+abstract class LinkedNodeUnit extends base.SummaryClass {
+  @Id(2)
+  LinkedNode get node;
+
+  @Id(1)
+  UnlinkedTokens get tokens;
+
+  @Id(0)
+  String get uriStr;
+}
+
+/// Information about a top-level declaration, or a field declaration that
+/// contributes information to [LinkedNodeKind.variableDeclaration].
+abstract class LinkedNodeVariablesDeclaration extends base.SummaryClass {
+  @Id(3)
+  LinkedNode get comment;
+
+  @Id(0)
+  bool get isConst;
+
+  @Id(1)
+  bool get isFinal;
+
+  @Id(2)
+  bool get isStatic;
+}
+
 /// Information about the resolution of an [UnlinkedReference].
 abstract class LinkedReference extends base.SummaryClass {
   /// If this [LinkedReference] doesn't have an associated [UnlinkedReference],
@@ -3782,6 +3868,25 @@
   /// Pop the top 2 values from the stack, place them in a [MapLiteralEntry],
   /// and push the result back onto the stack.
   makeMapLiteralEntry,
+
+  /// Pop the top value from the stack, convert it to a spread element of type
+  /// `...`, and push the result back onto the stack.
+  spreadElement,
+
+  /// Pop the top value from the stack, convert it to a spread element of type
+  /// `...?`, and push the result back onto the stack.
+  nullAwareSpreadElement,
+
+  /// Pop the top two values from the stack.  The first is a condition
+  /// and the second is a collection element.  Push an "if" element having the
+  /// given condition, with the collection element as its "then" clause.
+  ifElement,
+
+  /// Pop the top three values from the stack.  The first is a condition and the
+  /// other two are collection elements.  Push an "if" element having the given
+  /// condition, with the two collection elements as its "then" and "else"
+  /// clauses, respectively.
+  ifElseElement,
 }
 
 /// Unlinked summary information about an import declaration.
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index 541cfe7..d38b602 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -2,8 +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.
 
-import 'package:analyzer/dart/analysis/session.dart';
-
 /// This library is capable of producing linked summaries from unlinked
 /// ones (or prelinked ones).  It functions by building a miniature
 /// element model to represent the contents of the summaries, and then
@@ -57,12 +55,13 @@
 ///
 /// - Where possible, we favor method dispatch instead of "is" and "as"
 ///   checks.  E.g. see [ReferenceableElementForLink.asConstructor].
+import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/builder.dart';
@@ -116,11 +115,12 @@
     Set<String> libraryUris,
     GetDependencyCallback getDependency,
     GetUnitCallback getUnit,
-    GetDeclaredVariable getDeclaredVariable,
+    DeclaredVariables declaredVariables,
+    AnalysisOptions analysisOptions,
     [GetAstCallback getAst]) {
   Map<String, LinkedLibraryBuilder> linkedLibraries =
-      setupForLink(libraryUris, getUnit, getDeclaredVariable);
-  _relink(linkedLibraries, getDependency, getUnit, getAst);
+      setupForLink(libraryUris, getUnit, declaredVariables);
+  _relink(linkedLibraries, getDependency, getUnit, getAst, analysisOptions);
   return linkedLibraries;
 }
 
@@ -132,7 +132,7 @@
 /// of the libraries in this build unit, and whose values are the corresponding
 /// [LinkedLibraryBuilder]s.
 Map<String, LinkedLibraryBuilder> setupForLink(Set<String> libraryUris,
-    GetUnitCallback getUnit, GetDeclaredVariable getDeclaredVariable) {
+    GetUnitCallback getUnit, DeclaredVariables declaredVariables) {
   Map<String, LinkedLibraryBuilder> linkedLibraries =
       <String, LinkedLibraryBuilder>{};
   for (String absoluteUri in libraryUris) {
@@ -141,7 +141,7 @@
         getUnit(absoluteUri),
         getUnit,
         (String absoluteUri) => getUnit(absoluteUri)?.publicNamespace,
-        getDeclaredVariable);
+        declaredVariables);
   }
   return linkedLibraries;
 }
@@ -301,8 +301,9 @@
     Map<String, LinkedLibraryBuilder> libraries,
     GetDependencyCallback getDependency,
     GetUnitCallback getUnit,
-    GetAstCallback getAst) {
-  new Linker(libraries, getDependency, getUnit, getAst).link();
+    GetAstCallback getAst,
+    AnalysisOptions analysisOptions) {
+  new Linker(libraries, getDependency, getUnit, getAst, analysisOptions).link();
 }
 
 /// Create an [UnlinkedParam] representing the given [parameter], which should
@@ -412,37 +413,7 @@
 /// [UnlinkedUnit] objects.
 typedef UnlinkedUnit GetUnitCallback(String absoluteUri);
 
-/// Stub implementation of [AnalysisOptions] used during linking.
-class AnalysisOptionsForLink implements AnalysisOptionsImpl {
-  final Linker _linker;
-
-  AnalysisOptionsForLink(this._linker);
-
-  @override
-  bool get hint => false;
-
-  @override
-  bool get implicitCasts => true;
-
-  @override
-  bool get strictInference => false;
-
-  @override
-  bool get strictRawTypes => false;
-
-  @deprecated
-  @override
-  bool get previewDart2 => true;
-
-  @override
-  bool get strongMode => true;
-
-  @override
-  bool get strongModeHints => false;
-
-  @override
-  ExperimentStatus get experimentStatus => new ExperimentStatus();
-
+class AnalysisSessionForLink implements AnalysisSession {
   @override
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
@@ -498,6 +469,9 @@
   Source get librarySource => library.source;
 
   @override
+  get linkedNode => null;
+
+  @override
   List<MethodElementForLink> get methods;
 
   @override
@@ -1931,6 +1905,7 @@
         case UnlinkedExprOperation.makeUntypedList:
         case UnlinkedExprOperation.makeUntypedMap:
         case UnlinkedExprOperation.makeUntypedSet:
+        case UnlinkedExprOperation.makeUntypedSetOrMap:
           intPtr++;
           break;
         case UnlinkedExprOperation.assignToRef:
@@ -1958,6 +1933,7 @@
           intPtr++;
           break;
         case UnlinkedExprOperation.makeTypedMap:
+        case UnlinkedExprOperation.makeTypedMap2:
           refPtr += 2;
           intPtr++;
           break;
@@ -2105,7 +2081,7 @@
   ContextForLink(this._linker);
 
   @override
-  AnalysisOptionsForLink get analysisOptions => _linker.analysisOptions;
+  AnalysisOptions get analysisOptions => _linker.analysisOptions;
 
   @override
   TypeProvider get typeProvider => _linker.typeProvider;
@@ -2344,6 +2320,9 @@
   LibraryElement get library => enclosingElement.library;
 
   @override
+  get linkedNode => null;
+
+  @override
   String get name {
     if (_name == null) {
       _name = serializedExecutable.name;
@@ -2512,7 +2491,9 @@
       List<UnlinkedExecutable> localFunctions)
       : _builder = new ExprBuilder(
             unitResynthesizer, _functionElement, unlinkedConst,
-            requireValidConst: false, localFunctions: localFunctions);
+            requireValidConst: false,
+            localFunctions: localFunctions,
+            becomeSetOrMap: false);
 
   TopLevelInferenceErrorKind get errorKind {
     // TODO(paulberry): should we return TopLevelInferenceErrorKind.assignment
@@ -2854,6 +2835,9 @@
   bool get isAsynchronous => serializedExecutable.isAsynchronous;
 
   @override
+  get linkedNode => null;
+
+  @override
   DartType get returnType {
     // If this is a variable whose type needs inferring, infer it.
     if (_variable.hasImplicitType) {
@@ -3169,6 +3153,9 @@
   LibraryElementForLink get library => enclosingElement.library;
 
   @override
+  get linkedNode => null;
+
+  @override
   String get name => _unlinkedTypedef.name;
 
   @override
@@ -3287,6 +3274,9 @@
   LibraryElementForLink get library => enclosingElement.library;
 
   @override
+  get linkedNode => null;
+
+  @override
   String get name => '-';
 
   @override
@@ -3370,6 +3360,9 @@
   LibraryElementForLink get library => enclosingElement.library;
 
   @override
+  get linkedNode => null;
+
+  @override
   String get name => _unlinkedTypedef.name;
 
   @override
@@ -3651,6 +3644,9 @@
   LibraryResynthesizerContext get resynthesizerContext => this;
 
   @override
+  AnalysisSession get session => _linker.session;
+
+  @override
   Source get source => definingCompilationUnit.source;
 
   @override
@@ -3948,10 +3944,13 @@
   SpecialTypeElementForLink _bottomElement;
   InheritanceManager2 _inheritanceManager;
   ContextForLink _context;
-  AnalysisOptionsForLink _analysisOptions;
+  AnalysisSessionForLink _session;
+
+  /// Gets an instance of [AnalysisOptions] for use during linking.
+  final AnalysisOptions analysisOptions;
 
   Linker(Map<String, LinkedLibraryBuilder> linkedLibraries, this.getDependency,
-      this.getUnit, this.getAst) {
+      this.getUnit, this.getAst, this.analysisOptions) {
     // Create elements for the libraries to be linked.  The rest of
     // the element model will be created on demand.
     linkedLibraries
@@ -3962,10 +3961,6 @@
     });
   }
 
-  /// Get an instance of [AnalysisOptions] for use during linking.
-  AnalysisOptionsForLink get analysisOptions =>
-      _analysisOptions ??= new AnalysisOptionsForLink(this);
-
   /// Get the library element for `dart:async`.
   LibraryElementForLink get asyncLibrary =>
       _asyncLibrary ??= getLibrary(Uri.parse('dart:async'));
@@ -3990,6 +3985,10 @@
   InheritanceManager2 get inheritanceManager =>
       _inheritanceManager ??= new InheritanceManager2(typeSystem);
 
+  /// Get a stub implementation of [AnalysisContext] which can be used during
+  /// linking.
+  get session => _session ??= new AnalysisSessionForLink();
+
   /// Indicates whether type inference should use strong mode rules.
   @deprecated
   bool get strongMode => true;
diff --git a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
index dc9e818..91a51d2 100644
--- a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
@@ -1,23 +1,21 @@
+// 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.
+
 import 'dart:io' as io;
 import 'dart:math' show min;
 
 import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/resynthesize.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/api/general.dart';
 import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/dart.dart';
 
 /**
  * A [ConflictingSummaryException] indicates that two different summaries
@@ -187,130 +185,7 @@
 
   @override
   bool compute(CacheEntry entry, ResultDescriptor result) {
-    AnalysisTarget target = entry.target;
-
-    if (result == TYPE_PROVIDER) {
-      entry.setValue(result as ResultDescriptor<TypeProvider>,
-          _resynthesizer.typeProvider, const <TargetedResult>[]);
-      return true;
-    }
-
-    // LINE_INFO can be provided using just the UnlinkedUnit.
-    if (target is Source && result == LINE_INFO) {
-      String uriString = target.uri.toString();
-      UnlinkedUnit unlinkedUnit = _dataStore.unlinkedMap[uriString];
-      if (unlinkedUnit != null) {
-        List<int> lineStarts = unlinkedUnit.lineStarts;
-        if (lineStarts.isNotEmpty) {
-          LineInfo lineInfo = new LineInfo(lineStarts);
-          entry.setValue(result as ResultDescriptor<LineInfo>, lineInfo,
-              const <TargetedResult>[]);
-          return true;
-        }
-      }
-      return false;
-    }
-
-    // Check whether there are results for the source.
-    if (!hasResultsForSource(target.librarySource ?? target.source)) {
-      return false;
-    }
-    // Constant expressions are always resolved in summaries.
-    if (result == CONSTANT_EXPRESSION_RESOLVED &&
-        target is ConstantEvaluationTarget) {
-      entry.setValue(
-          result as ResultDescriptor<bool>, true, const <TargetedResult>[]);
-      return true;
-    }
-    // Provide results for Source.
-    if (target is Source) {
-      String uriString = target.uri.toString();
-      // Provide known results.
-      if (result == LIBRARY_ELEMENT1 ||
-          result == LIBRARY_ELEMENT2 ||
-          result == LIBRARY_ELEMENT3 ||
-          result == LIBRARY_ELEMENT4 ||
-          result == LIBRARY_ELEMENT5 ||
-          result == LIBRARY_ELEMENT6 ||
-          result == LIBRARY_ELEMENT7 ||
-          result == LIBRARY_ELEMENT8 ||
-          result == LIBRARY_ELEMENT9 ||
-          result == LIBRARY_ELEMENT) {
-        LibraryElement libraryElement =
-            resynthesizer.getLibraryElement(uriString);
-        entry.setValue(result as ResultDescriptor<LibraryElement>,
-            libraryElement, const <TargetedResult>[]);
-        return true;
-      } else if (result == READY_LIBRARY_ELEMENT2 ||
-          result == READY_LIBRARY_ELEMENT6 ||
-          result == READY_LIBRARY_ELEMENT7) {
-        entry.setValue(
-            result as ResultDescriptor<bool>, true, const <TargetedResult>[]);
-        return true;
-      } else if (result == MODIFICATION_TIME) {
-        entry.setValue(
-            result as ResultDescriptor<int>, 0, const <TargetedResult>[]);
-        return true;
-      } else if (result == SOURCE_KIND) {
-        UnlinkedUnit unlinked = _dataStore.unlinkedMap[uriString];
-        if (unlinked != null) {
-          entry.setValue(
-              result as ResultDescriptor<SourceKind>,
-              unlinked.isPartOf ? SourceKind.PART : SourceKind.LIBRARY,
-              const <TargetedResult>[]);
-          return true;
-        }
-        return false;
-      } else if (result == CONTAINING_LIBRARIES) {
-        List<String> libraryUriStrings =
-            _dataStore.getContainingLibraryUris(uriString);
-        if (libraryUriStrings != null) {
-          List<Source> librarySources = libraryUriStrings
-              .map((libraryUriString) =>
-                  context.sourceFactory.resolveUri(target, libraryUriString))
-              .toList(growable: false);
-          entry.setValue(result as ResultDescriptor<List<Source>>,
-              librarySources, const <TargetedResult>[]);
-          return true;
-        }
-        return false;
-      }
-    } else if (target is LibrarySpecificUnit) {
-      if (result == CREATED_RESOLVED_UNIT1 ||
-          result == CREATED_RESOLVED_UNIT2 ||
-          result == CREATED_RESOLVED_UNIT3 ||
-          result == CREATED_RESOLVED_UNIT4 ||
-          result == CREATED_RESOLVED_UNIT5 ||
-          result == CREATED_RESOLVED_UNIT6 ||
-          result == CREATED_RESOLVED_UNIT7 ||
-          result == CREATED_RESOLVED_UNIT8 ||
-          result == CREATED_RESOLVED_UNIT9 ||
-          result == CREATED_RESOLVED_UNIT10 ||
-          result == CREATED_RESOLVED_UNIT11) {
-        entry.setValue(
-            result as ResultDescriptor<bool>, true, const <TargetedResult>[]);
-        return true;
-      }
-      if (result == COMPILATION_UNIT_ELEMENT) {
-        String libraryUri = target.library.uri.toString();
-        String unitUri = target.unit.uri.toString();
-        CompilationUnitElement unit = resynthesizer.getElement(
-            new ElementLocationImpl.con3(<String>[libraryUri, unitUri]));
-        if (unit != null) {
-          entry.setValue(result as ResultDescriptor<CompilationUnitElement>,
-              unit, const <TargetedResult>[]);
-          return true;
-        }
-      }
-    } else if (target is VariableElement) {
-      if (result == INFERRED_STATIC_VARIABLE) {
-        entry.setValue(result as ResultDescriptor<VariableElement>, target,
-            const <TargetedResult>[]);
-        return true;
-      }
-    }
-    // Unknown target.
-    return false;
+    throw UnimplementedError();
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/summary/prelink.dart b/pkg/analyzer/lib/src/summary/prelink.dart
index 6bda8fd..1785442 100644
--- a/pkg/analyzer/lib/src/summary/prelink.dart
+++ b/pkg/analyzer/lib/src/summary/prelink.dart
@@ -2,6 +2,7 @@
 // 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 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
@@ -21,19 +22,13 @@
     UnlinkedUnit definingUnit,
     GetPartCallback getPart,
     GetImportCallback getImport,
-    GetDeclaredVariable getDeclaredVariable) {
-  return new _Prelinker(definingUnitUri, definingUnit, getPart, getImport,
-          getDeclaredVariable)
+    DeclaredVariables declaredVariables) {
+  return new _Prelinker(
+          definingUnitUri, definingUnit, getPart, getImport, declaredVariables)
       .prelink();
 }
 
 /**
- * Return the raw string value of the variable with the given [name],
- * or `null` of the variable is not defined.
- */
-typedef String GetDeclaredVariable(String name);
-
-/**
  * Type of the callback used by the prelinker to obtain public namespace
  * information about libraries with the given [absoluteUri] imported by the
  * library to be prelinked (and the transitive closure of parts and exports
@@ -219,7 +214,7 @@
   final UnlinkedUnit definingUnit;
   final GetPartCallback getPart;
   final GetImportCallback getImport;
-  final GetDeclaredVariable getDeclaredVariable;
+  final DeclaredVariables declaredVariables;
 
   /**
    * Cache of values returned by [getImport].
@@ -263,7 +258,7 @@
   final Map<String, _ExportNamespace> exportNamespaces = {};
 
   _Prelinker(this.definingUnitUri, this.definingUnit, this.getPart,
-      this.getImport, this.getDeclaredVariable) {
+      this.getImport, this.declaredVariables) {
     partCache[definingUnitUri] = definingUnit;
     importCache[definingUnitUri] = definingUnit.publicNamespace;
   }
@@ -719,7 +714,7 @@
   String _selectUri(
       String defaultUri, List<UnlinkedConfiguration> configurations) {
     for (UnlinkedConfiguration configuration in configurations) {
-      if (getDeclaredVariable(configuration.name) == configuration.value) {
+      if (declaredVariables.get(configuration.name) == configuration.value) {
         return configuration.uri;
       }
     }
diff --git a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
index 5e93786..f367937 100644
--- a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
@@ -344,14 +344,6 @@
           typeName.typeArguments != null);
     } else if (expr is ListLiteral) {
       _serializeListLiteral(expr);
-      // ignore: deprecated_member_use_from_same_package
-    } else if (expr is MapLiteral) {
-      // ignore: deprecated_member_use_from_same_package
-      _serializeMapLiteral(expr);
-      // ignore: deprecated_member_use_from_same_package
-    } else if (expr is SetLiteral) {
-      // ignore: deprecated_member_use_from_same_package
-      _serializeSetLiteral(expr);
     } else if (expr is SetOrMapLiteral) {
       _serializeSetOrMapLiteral(expr);
     } else if (expr is MethodInvocation) {
@@ -549,6 +541,23 @@
       _serialize(element.key);
       _serialize(element.value);
       operations.add(UnlinkedExprOperation.makeMapLiteralEntry);
+    } else if (element is SpreadElement) {
+      _serialize(element.expression);
+      bool isNullAware = element.spreadOperator.type ==
+          TokenType.PERIOD_PERIOD_PERIOD_QUESTION;
+      operations.add(isNullAware
+          ? UnlinkedExprOperation.nullAwareSpreadElement
+          : UnlinkedExprOperation.spreadElement);
+    } else if (element is IfElement) {
+      _serialize(element.condition);
+      _serializeCollectionElement(element.thenElement);
+      var elseElement = element.elseElement;
+      if (elseElement == null) {
+        operations.add(UnlinkedExprOperation.ifElement);
+      } else {
+        _serializeCollectionElement(elseElement);
+        operations.add(UnlinkedExprOperation.ifElseElement);
+      }
     } else {
       // TODO(paulberry): Implement serialization for spread and control flow
       //  elements.
@@ -573,27 +582,6 @@
     }
   }
 
-  @deprecated
-  void _serializeMapLiteral(MapLiteral expr) {
-    if (forConst || expr.typeArguments == null) {
-      for (MapLiteralEntry entry in expr.entries) {
-        _serialize(entry.key);
-        _serialize(entry.value);
-      }
-      ints.add(expr.entries.length);
-    } else {
-      ints.add(0);
-    }
-    if (expr.typeArguments != null &&
-        expr.typeArguments.arguments.length == 2) {
-      references.add(serializeType(expr.typeArguments.arguments[0]));
-      references.add(serializeType(expr.typeArguments.arguments[1]));
-      operations.add(UnlinkedExprOperation.makeTypedMap);
-    } else {
-      operations.add(UnlinkedExprOperation.makeUntypedMap);
-    }
-  }
-
   void _serializeMethodInvocation(MethodInvocation invocation) {
     Expression target = invocation.target;
     SimpleIdentifier methodName = invocation.methodName;
@@ -673,24 +661,6 @@
     }
   }
 
-  @deprecated
-  void _serializeSetLiteral(SetLiteral expr) {
-    if (forConst || expr.typeArguments == null) {
-      List<Expression> elements = expr.elements;
-      elements.forEach(_serialize);
-      ints.add(elements.length);
-    } else {
-      ints.add(0);
-    }
-    if (expr.typeArguments != null &&
-        expr.typeArguments.arguments.length == 1) {
-      references.add(serializeType(expr.typeArguments.arguments[0]));
-      operations.add(UnlinkedExprOperation.makeTypedSet);
-    } else {
-      operations.add(UnlinkedExprOperation.makeUntypedSet);
-    }
-  }
-
   void _serializeSetOrMapLiteral(SetOrMapLiteral expr) {
     if (forConst || expr.typeArguments == null) {
       for (CollectionElement element in expr.elements2) {
diff --git a/pkg/analyzer/lib/src/summary/summary_file_builder.dart b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
index 9d7b6ad..f774d2a 100644
--- a/pkg/analyzer/lib/src/summary/summary_file_builder.dart
+++ b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
@@ -4,6 +4,7 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/listener.dart';
@@ -25,11 +26,9 @@
 class SummaryBuilder {
   final Iterable<Source> librarySources;
   final AnalysisContext context;
+
   /**
    * Create a summary builder for these [librarySources] and [context].
-   *
-   * TODO(paulberry): remove optional "strong" parameter once all callers have
-   * stopped passing it in.
    */
   SummaryBuilder(this.librarySources, this.context);
 
@@ -92,9 +91,7 @@
         throw new StateError('Unable to find unresolved unit $uri.');
       }
       return unlinked;
-    }, (String name) {
-      throw new StateError('Unexpected call to GetDeclaredVariable($name).');
-    });
+    }, DeclaredVariables(), context.analysisOptions);
     map.forEach(bundleAssembler.addLinkedLibrary);
 
     return bundleAssembler.assemble().toBuffer();
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index f8490e1..33f51e3 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -8,25 +8,17 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/linked_unit_context.dart';
 
 /// Deserializer of fully resolved ASTs from flat buffers.
 class AstBinaryReader {
-  final Reference _nameRoot;
-  final LinkedNodeReference _linkedReferences;
-  final List<Reference> _references;
+  final LinkedUnitContext _unitContext;
 
-  final UnlinkedTokens _tokensBinary;
-  final List<Token> _tokens;
-
-  AstBinaryReader(this._nameRoot, this._linkedReferences, this._tokensBinary)
-      : _references = List<Reference>(_linkedReferences.name.length),
-        _tokens = List<Token>(_tokensBinary.type.length);
+  AstBinaryReader(this._unitContext);
 
   AstNode readNode(LinkedNode data) {
     if (data == null) return null;
@@ -269,89 +261,18 @@
     }
   }
 
-  CommentToken _getCommentToken(int index) {
-    var result = _getToken(index);
-    var token = result;
-    while (true) {
-      index = _tokensBinary.next[index];
-      if (index == 0) return result;
-
-      var nextToken = _getToken(index);
-      token.next = nextToken;
-      token = nextToken;
-    }
-  }
-
   T _getElement<T extends Element>(int index) {
-    return _getReferenceByIndex(index)?.element;
+    var bundleContext = _unitContext.bundleContext;
+    return bundleContext.elementOfIndex(index);
   }
 
   List<T> _getElements<T extends Element>(List<int> indexList) {
-    var result = List<T>(indexList.length);
-    for (var i = 0; i < indexList.length; ++i) {
-      var index = indexList[i];
-      result[i] = _getElement(index);
-    }
-    return result;
-  }
-
-  Reference _getReferenceByIndex(int index) {
-    var reference = _references[index];
-    if (reference != null) return reference;
-
-    if (index == 0) {
-      _references[index] = _nameRoot;
-      return _nameRoot;
-    }
-
-    var parentIndex = _linkedReferences.parent[index];
-    var parent = _getReferenceByIndex(parentIndex);
-    if (parent == null) return null;
-
-    var name = _linkedReferences.name[index];
-    reference = parent[name];
-    _references[index] = reference;
-
-    return reference;
+    var bundleContext = _unitContext.bundleContext;
+    return bundleContext.elementsOfIndexes(indexList);
   }
 
   Token _getToken(int index) {
-    var token = _tokens[index];
-    if (token == null) {
-      var kind = _tokensBinary.kind[index];
-      switch (kind) {
-        case UnlinkedTokenKind.nothing:
-          return null;
-        case UnlinkedTokenKind.comment:
-          return CommentToken(
-            _binaryToAstTokenType(_tokensBinary.type[index]),
-            _tokensBinary.lexeme[index],
-            _tokensBinary.offset[index],
-          );
-        case UnlinkedTokenKind.keyword:
-          return KeywordToken(
-            _binaryToAstTokenType(_tokensBinary.type[index]),
-            _tokensBinary.offset[index],
-            _getCommentToken(_tokensBinary.precedingComment[index]),
-          );
-        case UnlinkedTokenKind.simple:
-          return SimpleToken(
-            _binaryToAstTokenType(_tokensBinary.type[index]),
-            _tokensBinary.offset[index],
-            _getCommentToken(_tokensBinary.precedingComment[index]),
-          );
-        case UnlinkedTokenKind.string:
-          return StringToken(
-            _binaryToAstTokenType(_tokensBinary.type[index]),
-            _tokensBinary.lexeme[index],
-            _tokensBinary.offset[index],
-            _getCommentToken(_tokensBinary.precedingComment[index]),
-          );
-        default:
-          throw UnimplementedError('Token kind: $kind');
-      }
-    }
-    return token;
+    return _unitContext.tokensContext.tokenOfIndex(index);
   }
 
   List<Token> _getTokens(List<int> indexList) {
@@ -1236,7 +1157,7 @@
       leftBracket: _getToken(data.setOrMapLiteral_leftBracket),
       typeArguments: readNode(data.typedLiteral_typeArguments),
       rightBracket: _getToken(data.setOrMapLiteral_leftBracket),
-    );
+    )..staticType = _readType(data.expression_type);
     if (data.setOrMapLiteral_isMap) {
       node.becomeMap();
     } else if (data.setOrMapLiteral_isSet) {
@@ -1523,279 +1444,4 @@
     }
     return result;
   }
-
-  static TokenType _binaryToAstTokenType(UnlinkedTokenType type) {
-    switch (type) {
-      case UnlinkedTokenType.ABSTRACT:
-        return Keyword.ABSTRACT;
-      case UnlinkedTokenType.AMPERSAND:
-        return TokenType.AMPERSAND;
-      case UnlinkedTokenType.AMPERSAND_AMPERSAND:
-        return TokenType.AMPERSAND_AMPERSAND;
-      case UnlinkedTokenType.AMPERSAND_EQ:
-        return TokenType.AMPERSAND_EQ;
-      case UnlinkedTokenType.AS:
-        return TokenType.AS;
-      case UnlinkedTokenType.ASSERT:
-        return Keyword.ASSERT;
-      case UnlinkedTokenType.ASYNC:
-        return Keyword.ASYNC;
-      case UnlinkedTokenType.AT:
-        return TokenType.AT;
-      case UnlinkedTokenType.AWAIT:
-        return Keyword.AWAIT;
-      case UnlinkedTokenType.BACKPING:
-        return TokenType.BACKPING;
-      case UnlinkedTokenType.BACKSLASH:
-        return TokenType.BACKSLASH;
-      case UnlinkedTokenType.BANG:
-        return TokenType.BANG;
-      case UnlinkedTokenType.BANG_EQ:
-        return TokenType.BANG_EQ;
-      case UnlinkedTokenType.BAR:
-        return TokenType.BAR;
-      case UnlinkedTokenType.BAR_BAR:
-        return TokenType.BAR_BAR;
-      case UnlinkedTokenType.BAR_EQ:
-        return TokenType.BAR_EQ;
-      case UnlinkedTokenType.BREAK:
-        return Keyword.BREAK;
-      case UnlinkedTokenType.CARET:
-        return TokenType.CARET;
-      case UnlinkedTokenType.CARET_EQ:
-        return TokenType.CARET_EQ;
-      case UnlinkedTokenType.CASE:
-        return Keyword.CASE;
-      case UnlinkedTokenType.CATCH:
-        return Keyword.CATCH;
-      case UnlinkedTokenType.CLASS:
-        return Keyword.CLASS;
-      case UnlinkedTokenType.CLOSE_CURLY_BRACKET:
-        return TokenType.CLOSE_CURLY_BRACKET;
-      case UnlinkedTokenType.CLOSE_PAREN:
-        return TokenType.CLOSE_PAREN;
-      case UnlinkedTokenType.CLOSE_SQUARE_BRACKET:
-        return TokenType.CLOSE_SQUARE_BRACKET;
-      case UnlinkedTokenType.COLON:
-        return TokenType.COLON;
-      case UnlinkedTokenType.COMMA:
-        return TokenType.COMMA;
-      case UnlinkedTokenType.CONST:
-        return Keyword.CONST;
-      case UnlinkedTokenType.CONTINUE:
-        return Keyword.CONTINUE;
-      case UnlinkedTokenType.COVARIANT:
-        return Keyword.COVARIANT;
-      case UnlinkedTokenType.DEFAULT:
-        return Keyword.DEFAULT;
-      case UnlinkedTokenType.DEFERRED:
-        return Keyword.DEFERRED;
-      case UnlinkedTokenType.DO:
-        return Keyword.DO;
-      case UnlinkedTokenType.DOUBLE:
-        return TokenType.DOUBLE;
-      case UnlinkedTokenType.DYNAMIC:
-        return Keyword.DYNAMIC;
-      case UnlinkedTokenType.ELSE:
-        return Keyword.ELSE;
-      case UnlinkedTokenType.ENUM:
-        return Keyword.ENUM;
-      case UnlinkedTokenType.EOF:
-        return TokenType.EOF;
-      case UnlinkedTokenType.EQ:
-        return TokenType.EQ;
-      case UnlinkedTokenType.EQ_EQ:
-        return TokenType.EQ_EQ;
-      case UnlinkedTokenType.EXPORT:
-        return Keyword.EXPORT;
-      case UnlinkedTokenType.EXTENDS:
-        return Keyword.EXTENDS;
-      case UnlinkedTokenType.EXTERNAL:
-        return Keyword.EXTERNAL;
-      case UnlinkedTokenType.FACTORY:
-        return Keyword.FACTORY;
-      case UnlinkedTokenType.FALSE:
-        return Keyword.FALSE;
-      case UnlinkedTokenType.FINAL:
-        return Keyword.FINAL;
-      case UnlinkedTokenType.FINALLY:
-        return Keyword.FINALLY;
-      case UnlinkedTokenType.FOR:
-        return Keyword.FOR;
-      case UnlinkedTokenType.FUNCTION:
-        return TokenType.FUNCTION;
-      case UnlinkedTokenType.FUNCTION_KEYWORD:
-        return Keyword.FUNCTION;
-      case UnlinkedTokenType.GET:
-        return Keyword.GET;
-      case UnlinkedTokenType.GT:
-        return TokenType.GT;
-      case UnlinkedTokenType.GT_EQ:
-        return TokenType.GT_EQ;
-      case UnlinkedTokenType.GT_GT:
-        return TokenType.GT_GT;
-      case UnlinkedTokenType.GT_GT_EQ:
-        return TokenType.GT_GT_EQ;
-      case UnlinkedTokenType.HASH:
-        return TokenType.HASH;
-      case UnlinkedTokenType.HEXADECIMAL:
-        return TokenType.HEXADECIMAL;
-      case UnlinkedTokenType.HIDE:
-        return Keyword.HIDE;
-      case UnlinkedTokenType.IDENTIFIER:
-        return TokenType.IDENTIFIER;
-      case UnlinkedTokenType.IF:
-        return Keyword.IF;
-      case UnlinkedTokenType.IMPLEMENTS:
-        return Keyword.IMPLEMENTS;
-      case UnlinkedTokenType.IMPORT:
-        return Keyword.IMPORT;
-      case UnlinkedTokenType.IN:
-        return Keyword.IN;
-      case UnlinkedTokenType.INDEX:
-        return TokenType.INDEX;
-      case UnlinkedTokenType.INDEX_EQ:
-        return TokenType.INDEX_EQ;
-      case UnlinkedTokenType.INT:
-        return TokenType.INT;
-      case UnlinkedTokenType.INTERFACE:
-        return Keyword.INTERFACE;
-      case UnlinkedTokenType.IS:
-        return TokenType.IS;
-      case UnlinkedTokenType.LIBRARY:
-        return Keyword.LIBRARY;
-      case UnlinkedTokenType.LT:
-        return TokenType.LT;
-      case UnlinkedTokenType.LT_EQ:
-        return TokenType.LT_EQ;
-      case UnlinkedTokenType.LT_LT:
-        return TokenType.LT_LT;
-      case UnlinkedTokenType.LT_LT_EQ:
-        return TokenType.LT_LT_EQ;
-      case UnlinkedTokenType.MINUS:
-        return TokenType.MINUS;
-      case UnlinkedTokenType.MINUS_EQ:
-        return TokenType.MINUS_EQ;
-      case UnlinkedTokenType.MINUS_MINUS:
-        return TokenType.MINUS_MINUS;
-      case UnlinkedTokenType.MIXIN:
-        return Keyword.MIXIN;
-      case UnlinkedTokenType.MULTI_LINE_COMMENT:
-        return TokenType.MULTI_LINE_COMMENT;
-      case UnlinkedTokenType.NATIVE:
-        return Keyword.NATIVE;
-      case UnlinkedTokenType.NEW:
-        return Keyword.NEW;
-      case UnlinkedTokenType.NULL:
-        return Keyword.NULL;
-      case UnlinkedTokenType.OF:
-        return Keyword.OF;
-      case UnlinkedTokenType.ON:
-        return Keyword.ON;
-      case UnlinkedTokenType.OPEN_CURLY_BRACKET:
-        return TokenType.OPEN_CURLY_BRACKET;
-      case UnlinkedTokenType.OPEN_PAREN:
-        return TokenType.OPEN_PAREN;
-      case UnlinkedTokenType.OPEN_SQUARE_BRACKET:
-        return TokenType.OPEN_SQUARE_BRACKET;
-      case UnlinkedTokenType.OPERATOR:
-        return Keyword.OPERATOR;
-      case UnlinkedTokenType.PART:
-        return Keyword.PART;
-      case UnlinkedTokenType.PATCH:
-        return Keyword.PATCH;
-      case UnlinkedTokenType.PERCENT:
-        return TokenType.PERCENT;
-      case UnlinkedTokenType.PERCENT_EQ:
-        return TokenType.PERCENT_EQ;
-      case UnlinkedTokenType.PERIOD:
-        return TokenType.PERIOD;
-      case UnlinkedTokenType.PERIOD_PERIOD:
-        return TokenType.PERIOD_PERIOD;
-      case UnlinkedTokenType.PERIOD_PERIOD_PERIOD:
-        return TokenType.PERIOD_PERIOD_PERIOD;
-      case UnlinkedTokenType.PERIOD_PERIOD_PERIOD_QUESTION:
-        return TokenType.PERIOD_PERIOD_PERIOD_QUESTION;
-      case UnlinkedTokenType.PLUS:
-        return TokenType.PLUS;
-      case UnlinkedTokenType.PLUS_EQ:
-        return TokenType.PLUS_EQ;
-      case UnlinkedTokenType.PLUS_PLUS:
-        return TokenType.PLUS_PLUS;
-      case UnlinkedTokenType.QUESTION:
-        return TokenType.QUESTION;
-      case UnlinkedTokenType.QUESTION_PERIOD:
-        return TokenType.QUESTION_PERIOD;
-      case UnlinkedTokenType.QUESTION_QUESTION:
-        return TokenType.QUESTION_QUESTION;
-      case UnlinkedTokenType.QUESTION_QUESTION_EQ:
-        return TokenType.QUESTION_QUESTION_EQ;
-      case UnlinkedTokenType.RETHROW:
-        return Keyword.RETHROW;
-      case UnlinkedTokenType.RETURN:
-        return Keyword.RETURN;
-      case UnlinkedTokenType.SCRIPT_TAG:
-        return TokenType.SCRIPT_TAG;
-      case UnlinkedTokenType.SEMICOLON:
-        return TokenType.SEMICOLON;
-      case UnlinkedTokenType.SET:
-        return Keyword.SET;
-      case UnlinkedTokenType.SHOW:
-        return Keyword.SHOW;
-      case UnlinkedTokenType.SINGLE_LINE_COMMENT:
-        return TokenType.SINGLE_LINE_COMMENT;
-      case UnlinkedTokenType.SLASH:
-        return TokenType.SLASH;
-      case UnlinkedTokenType.SLASH_EQ:
-        return TokenType.SLASH_EQ;
-      case UnlinkedTokenType.SOURCE:
-        return Keyword.SOURCE;
-      case UnlinkedTokenType.STAR:
-        return TokenType.STAR;
-      case UnlinkedTokenType.STAR_EQ:
-        return TokenType.STAR_EQ;
-      case UnlinkedTokenType.STATIC:
-        return Keyword.STATIC;
-      case UnlinkedTokenType.STRING:
-        return TokenType.STRING;
-      case UnlinkedTokenType.STRING_INTERPOLATION_EXPRESSION:
-        return TokenType.STRING_INTERPOLATION_EXPRESSION;
-      case UnlinkedTokenType.STRING_INTERPOLATION_IDENTIFIER:
-        return TokenType.STRING_INTERPOLATION_IDENTIFIER;
-      case UnlinkedTokenType.SUPER:
-        return Keyword.SUPER;
-      case UnlinkedTokenType.SWITCH:
-        return Keyword.SWITCH;
-      case UnlinkedTokenType.SYNC:
-        return Keyword.SYNC;
-      case UnlinkedTokenType.THIS:
-        return Keyword.THIS;
-      case UnlinkedTokenType.THROW:
-        return Keyword.THROW;
-      case UnlinkedTokenType.TILDE:
-        return TokenType.TILDE;
-      case UnlinkedTokenType.TILDE_SLASH:
-        return TokenType.TILDE_SLASH;
-      case UnlinkedTokenType.TILDE_SLASH_EQ:
-        return TokenType.TILDE_SLASH_EQ;
-      case UnlinkedTokenType.TRUE:
-        return Keyword.TRUE;
-      case UnlinkedTokenType.TRY:
-        return Keyword.TRY;
-      case UnlinkedTokenType.TYPEDEF:
-        return Keyword.TYPEDEF;
-      case UnlinkedTokenType.VAR:
-        return Keyword.VAR;
-      case UnlinkedTokenType.VOID:
-        return Keyword.VOID;
-      case UnlinkedTokenType.WHILE:
-        return Keyword.WHILE;
-      case UnlinkedTokenType.WITH:
-        return Keyword.WITH;
-      case UnlinkedTokenType.YIELD:
-        return Keyword.YIELD;
-      default:
-        throw StateError('Unexpected type: $type');
-    }
-  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index 185370e..187dc7b 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -8,36 +8,24 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/reference.dart';
-import 'package:meta/meta.dart';
+import 'package:analyzer/src/summary2/linking_bundle_context.dart';
+import 'package:analyzer/src/summary2/tokens_context.dart';
 
 /// Serializer of fully resolved ASTs into flat buffers.
 class AstBinaryWriter extends ThrowingAstVisitor<LinkedNodeBuilder> {
-  final referenceRoot = Reference.root();
-  final referenceBuilder = LinkedNodeReferenceBuilder();
-  final _references = <Reference>[];
+  final LinkingBundleContext _linkingBundleContext;
+  final TokensContext _tokensContext;
 
-  final UnlinkedTokensBuilder tokens = UnlinkedTokensBuilder();
-  final Map<Token, int> _tokenMap = Map.identity();
-  int _tokenIndex = 0;
+  /// This field is set temporary while visiting [FieldDeclaration] or
+  /// [TopLevelVariableDeclaration] to store data shared among all variables
+  /// in these declarations.
+  LinkedNodeVariablesDeclarationBuilder _variablesDeclaration;
 
-  AstBinaryWriter() {
-    _references.add(referenceRoot);
-    _addToken(
-      isSynthetic: true,
-      kind: UnlinkedTokenKind.nothing,
-      length: 0,
-      lexeme: '',
-      offset: 0,
-      precedingComment: 0,
-      type: UnlinkedTokenType.NOTHING,
-    );
-  }
+  AstBinaryWriter(this._linkingBundleContext, this._tokensContext);
 
   @override
   LinkedNodeBuilder visitAdjacentStrings(AdjacentStrings node) {
@@ -105,7 +93,7 @@
   @override
   LinkedNodeBuilder visitAssignmentExpression(AssignmentExpression node) {
     return LinkedNodeBuilder.assignmentExpression(
-      assignmentExpression_element: _getReference(node.staticElement).index,
+      assignmentExpression_element: _getReferenceIndex(node.staticElement),
       assignmentExpression_leftHandSide: node.leftHandSide.accept(this),
       assignmentExpression_operator: _getToken(node.operator),
       assignmentExpression_rightHandSide: node.rightHandSide.accept(this),
@@ -125,7 +113,7 @@
   @override
   LinkedNodeBuilder visitBinaryExpression(BinaryExpression node) {
     return LinkedNodeBuilder.binaryExpression(
-      binaryExpression_element: _getReference(node.staticElement).index,
+      binaryExpression_element: _getReferenceIndex(node.staticElement),
       binaryExpression_leftOperand: node.leftOperand.accept(this),
       binaryExpression_operator: _getToken(node.operator),
       binaryExpression_rightOperand: node.rightOperand.accept(this),
@@ -312,7 +300,7 @@
   @override
   LinkedNodeBuilder visitConstructorName(ConstructorName node) {
     return LinkedNodeBuilder.constructorName(
-      constructorName_element: _getReference(node.staticElement).index,
+      constructorName_element: _getReferenceIndex(node.staticElement),
       constructorName_name: node.name?.accept(this),
       constructorName_period: _getToken(node.period),
       constructorName_type: node.type.accept(this),
@@ -452,6 +440,10 @@
 
   @override
   LinkedNodeBuilder visitFieldDeclaration(FieldDeclaration node) {
+    _variablesDeclaration = LinkedNodeVariablesDeclarationBuilder(
+      isStatic: node.isStatic,
+    );
+
     var builder = LinkedNodeBuilder.fieldDeclaration(
       fieldDeclaration_covariantKeyword: _getToken(node.covariantKeyword),
       fieldDeclaration_fields: node.fields.accept(this),
@@ -459,6 +451,10 @@
       fieldDeclaration_staticKeyword: _getToken(node.staticKeyword),
     );
     _storeClassMember(builder, node);
+
+    _variablesDeclaration.comment = builder.annotatedNode_comment;
+    _variablesDeclaration = null;
+
     return builder;
   }
 
@@ -688,7 +684,7 @@
   @override
   LinkedNodeBuilder visitIndexExpression(IndexExpression node) {
     return LinkedNodeBuilder.indexExpression(
-      indexExpression_element: _getReference(node.staticElement).index,
+      indexExpression_element: _getReferenceIndex(node.staticElement),
       indexExpression_index: node.index.accept(this),
       indexExpression_leftBracket: _getToken(node.leftBracket),
       indexExpression_rightBracket: _getToken(node.rightBracket),
@@ -812,6 +808,7 @@
       methodDeclaration_operatorKeyword: _getToken(node.operatorKeyword),
       methodDeclaration_propertyKeyword: _getToken(node.propertyKeyword),
       methodDeclaration_returnType: node.returnType?.accept(this),
+      methodDeclaration_typeParameters: node.typeParameters?.accept(this),
     );
     _storeClassMember(builder, node);
     return builder;
@@ -899,7 +896,7 @@
   LinkedNodeBuilder visitPostfixExpression(PostfixExpression node) {
     return LinkedNodeBuilder.postfixExpression(
       expression_type: _writeType(node.staticType),
-      postfixExpression_element: _getReference(node.staticElement).index,
+      postfixExpression_element: _getReferenceIndex(node.staticElement),
       postfixExpression_operand: node.operand.accept(this),
       postfixExpression_operator: _getToken(node.operator),
     );
@@ -919,7 +916,7 @@
   LinkedNodeBuilder visitPrefixExpression(PrefixExpression node) {
     return LinkedNodeBuilder.prefixExpression(
       expression_type: _writeType(node.staticType),
-      prefixExpression_element: _getReference(node.staticElement).index,
+      prefixExpression_element: _getReferenceIndex(node.staticElement),
       prefixExpression_operand: node.operand.accept(this),
       prefixExpression_operator: _getToken(node.operator),
     );
@@ -945,7 +942,7 @@
       redirectingConstructorInvocation_constructorName:
           node.constructorName?.accept(this),
       redirectingConstructorInvocation_element:
-          _getReference(node.staticElement).index,
+          _getReferenceIndex(node.staticElement),
       redirectingConstructorInvocation_period: _getToken(node.period),
       redirectingConstructorInvocation_thisKeyword: _getToken(node.thisKeyword),
     );
@@ -1012,11 +1009,16 @@
 
   @override
   LinkedNodeBuilder visitSimpleIdentifier(SimpleIdentifier node) {
-    var isDeclared = node.inDeclarationContext();
+    Element element;
+    if (!node.inDeclarationContext()) {
+      element = node.staticElement;
+      if (element is MultiplyDefinedElement) {
+        element = null;
+      }
+    }
 
     return LinkedNodeBuilder.simpleIdentifier(
-      simpleIdentifier_element:
-          isDeclared ? null : _getReference(node.staticElement).index,
+      simpleIdentifier_element: _getReferenceIndex(element),
       simpleIdentifier_token: _getToken(node.token),
       expression_type: _writeType(node.staticType),
     );
@@ -1056,7 +1058,7 @@
       superConstructorInvocation_constructorName:
           node.constructorName?.accept(this),
       superConstructorInvocation_element:
-          _getReference(node.staticElement).index,
+          _getReferenceIndex(node.staticElement),
       superConstructorInvocation_period: _getToken(node.period),
       superConstructorInvocation_superKeyword: _getToken(node.superKeyword),
     );
@@ -1133,11 +1135,17 @@
   @override
   LinkedNodeBuilder visitTopLevelVariableDeclaration(
       TopLevelVariableDeclaration node) {
+    _variablesDeclaration = LinkedNodeVariablesDeclarationBuilder();
+
     var builder = LinkedNodeBuilder.topLevelVariableDeclaration(
       topLevelVariableDeclaration_semicolon: _getToken(node.semicolon),
       topLevelVariableDeclaration_variableList: node.variables?.accept(this),
     );
     _storeCompilationUnitMember(builder, node);
+
+    _variablesDeclaration.comment = builder.annotatedNode_comment;
+    _variablesDeclaration = null;
+
     return builder;
   }
 
@@ -1196,11 +1204,17 @@
       variableDeclaration_equals: _getToken(node.equals),
       variableDeclaration_initializer: node.initializer?.accept(this),
       variableDeclaration_name: node.name.accept(this),
+      variableDeclaration_declaration: _variablesDeclaration,
     );
   }
 
   @override
   LinkedNodeBuilder visitVariableDeclarationList(VariableDeclarationList node) {
+    if (_variablesDeclaration != null) {
+      _variablesDeclaration.isConst = node.isConst;
+      _variablesDeclaration.isFinal = node.isFinal;
+    }
+
     var builder = LinkedNodeBuilder.variableDeclarationList(
       variableDeclarationList_keyword: _getToken(node.keyword),
       variableDeclarationList_type: node.type?.accept(this),
@@ -1251,184 +1265,26 @@
   }
 
   LinkedNodeBuilder writeNode(AstNode node) {
-    _writeTokens(node.beginToken, node.endToken);
     return node.accept(this);
   }
 
-  /// Write [referenceRoot] and all its children into [referenceBuilder].
-  void writeReferences() {
-    for (var reference in _references) {
-      referenceBuilder.parent.add(reference.parent?.index ?? 0);
-      referenceBuilder.name.add(reference.name);
+  int _getReferenceIndex(Element element) {
+    if (element == null) return 0;
+
+    if (element is Member) {
+      element = (element as Member).baseElement;
     }
-  }
 
-  void _addToken({
-    @required bool isSynthetic,
-    @required UnlinkedTokenKind kind,
-    @required int length,
-    @required String lexeme,
-    @required int offset,
-    @required int precedingComment,
-    @required UnlinkedTokenType type,
-  }) {
-    tokens.endGroup.add(0);
-    tokens.isSynthetic.add(isSynthetic);
-    tokens.kind.add(kind);
-    tokens.length.add(length);
-    tokens.lexeme.add(lexeme);
-    tokens.next.add(0);
-    tokens.offset.add(offset);
-    tokens.precedingComment.add(precedingComment);
-    tokens.type.add(type);
-    _tokenIndex++;
-  }
-
-  void _ensureReferenceIndex(Reference reference) {
-    if (reference.index == null) {
-      reference.index = _references.length;
-      _references.add(reference);
+    var reference = (element as ElementImpl).reference;
+    if (identical(element, DynamicElementImpl.instance)) {
+      reference = _linkingBundleContext.dynamicReference;
     }
-  }
 
-  Reference _getReference(Element element) {
-    if (element == null) return referenceRoot;
-
-    // TODO(scheglov) handle Member elements
-
-    Reference result;
-    if (element is ClassElement) {
-      var containerRef = _getReference(element.library).getChild('@class');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is CompilationUnitElement) {
-      return _getReference(element.enclosingElement);
-    } else if (element is ConstructorElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@constructor');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is DynamicElementImpl) {
-      result = _getReference(element.library).getChild('@dynamic');
-    } else if (element is FieldElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@field');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is FunctionElement) {
-      var containerRef = _getReference(element.library).getChild('@function');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name ?? '');
-    } else if (element is FunctionTypeAliasElement) {
-      var libraryRef = _getReference(element.library);
-      var containerRef = libraryRef.getChild('@functionTypeAlias');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is GenericFunctionTypeElement) {
-      if (element.enclosingElement is GenericTypeAliasElement) {
-        return _getReference(element.enclosingElement);
-      } else {
-        var libraryRef = _getReference(element.library);
-        var containerRef = libraryRef.getChild('@functionType');
-        _ensureReferenceIndex(containerRef);
-
-        // TODO(scheglov) do we need to store these elements at all?
-        result = containerRef.getChild('<unnamed>');
-      }
-    } else if (element is GenericTypeAliasElement) {
-      var containerRef = _getReference(element.library).getChild('@typeAlias');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is GenericFunctionTypeElement &&
-        element.enclosingElement is ParameterElement) {
-      return _getReference(element.enclosingElement);
-    } else if (element is LibraryElement) {
-      var uriStr = element.source.uri.toString();
-      result = referenceRoot.getChild(uriStr);
-    } else if (element is LabelElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@label');
-      _ensureReferenceIndex(containerRef);
-
-      // TODO(scheglov) use index instead of offset
-      result = containerRef.getChild('${element.nameOffset}');
-    } else if (element is LocalVariableElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@localVariable');
-      _ensureReferenceIndex(containerRef);
-
-      // TODO(scheglov) use index instead of offset
-      result = containerRef.getChild('${element.nameOffset}');
-    } else if (element is MethodElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@method');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is MultiplyDefinedElement) {
-      return referenceRoot;
-    } else if (element is ParameterElement) {
-      var enclosing = element.enclosingElement;
-      var enclosingRef = _getReference(enclosing);
-      var containerRef = enclosingRef.getChild('@parameter');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is PrefixElement) {
-      var containerRef = _getReference(element.library).getChild('@prefix');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is PropertyAccessorElement) {
-      var enclosingRef = _getReference(element.library);
-      var containerRef = enclosingRef.getChild(
-        element.isGetter ? '@getter' : '@setter',
-      );
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.displayName);
-    } else if (element is TopLevelVariableElement) {
-      var enclosingRef = _getReference(element.library);
-      var containerRef = enclosingRef.getChild('@variable');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is TypeParameterElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@typeParameter');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else {
-      throw UnimplementedError('(${element.runtimeType}) $element');
-    }
-    _ensureReferenceIndex(result);
-    return result;
-  }
-
-  List<int> _getReferences(List<Element> elements) {
-    var result = List<int>(elements.length);
-    for (var i = 0; i < elements.length; ++i) {
-      var element = elements[i];
-      result[i] = _getReference(element).index;
-    }
-    return result;
+    return _linkingBundleContext.indexOfReference(reference);
   }
 
   int _getToken(Token token) {
-    if (token == null) return 0;
-
-    var index = _tokenMap[token];
-    if (index == null) {
-      throw StateError('Token must be written first: $token');
-    }
-    return index;
+    return _tokensContext.indexOfToken(token);
   }
 
   List<int> _getTokens(List<Token> tokenList) {
@@ -1602,36 +1458,7 @@
     builder
       ..uriBasedDirective_uri = node.uri.accept(this)
       ..uriBasedDirective_uriContent = node.uriContent
-      ..uriBasedDirective_uriElement = _getReference(node.uriElement).index;
-  }
-
-  int _writeCommentToken(CommentToken token) {
-    if (token == null) return 0;
-    var firstIndex = _tokenIndex;
-
-    var previousIndex = 0;
-    while (token != null) {
-      var index = _tokenIndex;
-      _tokenMap[token] = index;
-      _addToken(
-        isSynthetic: false,
-        kind: UnlinkedTokenKind.comment,
-        length: token.length,
-        lexeme: token.lexeme,
-        offset: token.offset,
-        precedingComment: 0,
-        type: _astToBinaryTokenType(token.type),
-      );
-
-      if (previousIndex != 0) {
-        tokens.next[previousIndex] = index;
-      }
-      previousIndex = index;
-
-      token = token.next;
-    }
-
-    return firstIndex;
+      ..uriBasedDirective_uriElement = _getReferenceIndex(node.uriElement);
   }
 
   List<LinkedNodeBuilder> _writeNodeList(List<AstNode> nodeList) {
@@ -1646,389 +1473,7 @@
     return result;
   }
 
-  int _writeToken(Token token) {
-    assert(_tokenMap[token] == null);
-
-    var commentIndex = _writeCommentToken(token.precedingComments);
-
-    var index = _tokenIndex;
-    _tokenMap[token] = index;
-
-    if (token is KeywordToken) {
-      _addToken(
-        isSynthetic: token.isSynthetic,
-        kind: UnlinkedTokenKind.keyword,
-        lexeme: '',
-        offset: token.offset,
-        length: token.length,
-        precedingComment: commentIndex,
-        type: _astToBinaryTokenType(token.type),
-      );
-    } else if (token is StringToken) {
-      _addToken(
-        isSynthetic: token.isSynthetic,
-        kind: UnlinkedTokenKind.string,
-        lexeme: token.lexeme,
-        offset: token.offset,
-        length: token.length,
-        precedingComment: commentIndex,
-        type: _astToBinaryTokenType(token.type),
-      );
-    } else if (token is SimpleToken) {
-      _addToken(
-        isSynthetic: token.isSynthetic,
-        kind: UnlinkedTokenKind.simple,
-        lexeme: token.lexeme,
-        offset: token.offset,
-        length: token.length,
-        precedingComment: commentIndex,
-        type: _astToBinaryTokenType(token.type),
-      );
-    } else {
-      throw UnimplementedError('(${token.runtimeType}) $token');
-    }
-
-    return index;
-  }
-
-  /// Write all the tokens from the [first] to the [last] inclusively.
-  void _writeTokens(Token first, Token last) {
-    if (first is CommentToken) {
-      first = (first as CommentToken).parent;
-    }
-
-    var endGroupToBeginIndexMap = <Token, int>{};
-    var previousIndex = 0;
-    for (var token = first;; token = token.next) {
-      var index = _writeToken(token);
-
-      if (previousIndex != 0) {
-        tokens.next[previousIndex] = index;
-      }
-      previousIndex = index;
-
-      if (token.endGroup != null) {
-        endGroupToBeginIndexMap[token.endGroup] = index;
-      }
-
-      var beginIndex = endGroupToBeginIndexMap[token];
-      if (beginIndex != null) {
-        tokens.endGroup[beginIndex] = index;
-      }
-
-      if (token == last) break;
-    }
-  }
-
   LinkedNodeTypeBuilder _writeType(DartType type) {
-    if (type == null) return null;
-
-    if (type.isBottom) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.bottom,
-      );
-    } else if (type.isDynamic) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.dynamic_,
-      );
-    } else if (type is FunctionType) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.function,
-        functionFormalParameters: _getReferences(type.parameters),
-        functionReturnType: _writeType(type.returnType),
-        functionTypeParameters: _getReferences(type.parameters),
-      );
-    } else if (type is InterfaceType) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.interface,
-        interfaceClass: _getReference(type.element).index,
-        interfaceTypeArguments: type.typeArguments.map(_writeType).toList(),
-      );
-    } else if (type is TypeParameterType) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.typeParameter,
-        typeParameterParameter: _getReference(type.element).index,
-      );
-    } else if (type is VoidType) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.void_,
-      );
-    } else {
-      throw UnimplementedError('(${type.runtimeType}) $type');
-    }
-  }
-
-  static UnlinkedTokenType _astToBinaryTokenType(TokenType type) {
-    if (type == Keyword.ABSTRACT) {
-      return UnlinkedTokenType.ABSTRACT;
-    } else if (type == TokenType.AMPERSAND) {
-      return UnlinkedTokenType.AMPERSAND;
-    } else if (type == TokenType.AMPERSAND_AMPERSAND) {
-      return UnlinkedTokenType.AMPERSAND_AMPERSAND;
-    } else if (type == TokenType.AMPERSAND_EQ) {
-      return UnlinkedTokenType.AMPERSAND_EQ;
-    } else if (type == TokenType.AS) {
-      return UnlinkedTokenType.AS;
-    } else if (type == Keyword.ASSERT) {
-      return UnlinkedTokenType.ASSERT;
-    } else if (type == Keyword.ASYNC) {
-      return UnlinkedTokenType.ASYNC;
-    } else if (type == TokenType.AT) {
-      return UnlinkedTokenType.AT;
-    } else if (type == Keyword.AWAIT) {
-      return UnlinkedTokenType.AWAIT;
-    } else if (type == TokenType.BACKPING) {
-      return UnlinkedTokenType.BACKPING;
-    } else if (type == TokenType.BACKSLASH) {
-      return UnlinkedTokenType.BACKSLASH;
-    } else if (type == TokenType.BANG) {
-      return UnlinkedTokenType.BANG;
-    } else if (type == TokenType.BANG_EQ) {
-      return UnlinkedTokenType.BANG_EQ;
-    } else if (type == TokenType.BAR) {
-      return UnlinkedTokenType.BAR;
-    } else if (type == TokenType.BAR_BAR) {
-      return UnlinkedTokenType.BAR_BAR;
-    } else if (type == TokenType.BAR_EQ) {
-      return UnlinkedTokenType.BAR_EQ;
-    } else if (type == Keyword.BREAK) {
-      return UnlinkedTokenType.BREAK;
-    } else if (type == TokenType.CARET) {
-      return UnlinkedTokenType.CARET;
-    } else if (type == TokenType.CARET_EQ) {
-      return UnlinkedTokenType.CARET_EQ;
-    } else if (type == Keyword.CASE) {
-      return UnlinkedTokenType.CASE;
-    } else if (type == Keyword.CATCH) {
-      return UnlinkedTokenType.CATCH;
-    } else if (type == Keyword.CLASS) {
-      return UnlinkedTokenType.CLASS;
-    } else if (type == TokenType.CLOSE_CURLY_BRACKET) {
-      return UnlinkedTokenType.CLOSE_CURLY_BRACKET;
-    } else if (type == TokenType.CLOSE_PAREN) {
-      return UnlinkedTokenType.CLOSE_PAREN;
-    } else if (type == TokenType.CLOSE_SQUARE_BRACKET) {
-      return UnlinkedTokenType.CLOSE_SQUARE_BRACKET;
-    } else if (type == TokenType.COLON) {
-      return UnlinkedTokenType.COLON;
-    } else if (type == TokenType.COMMA) {
-      return UnlinkedTokenType.COMMA;
-    } else if (type == Keyword.CONST) {
-      return UnlinkedTokenType.CONST;
-    } else if (type == Keyword.CONTINUE) {
-      return UnlinkedTokenType.CONTINUE;
-    } else if (type == Keyword.COVARIANT) {
-      return UnlinkedTokenType.COVARIANT;
-    } else if (type == Keyword.DEFAULT) {
-      return UnlinkedTokenType.DEFAULT;
-    } else if (type == Keyword.DEFERRED) {
-      return UnlinkedTokenType.DEFERRED;
-    } else if (type == Keyword.DO) {
-      return UnlinkedTokenType.DO;
-    } else if (type == TokenType.DOUBLE) {
-      return UnlinkedTokenType.DOUBLE;
-    } else if (type == Keyword.DYNAMIC) {
-      return UnlinkedTokenType.DYNAMIC;
-    } else if (type == Keyword.ELSE) {
-      return UnlinkedTokenType.ELSE;
-    } else if (type == Keyword.ENUM) {
-      return UnlinkedTokenType.ENUM;
-    } else if (type == TokenType.EOF) {
-      return UnlinkedTokenType.EOF;
-    } else if (type == TokenType.EQ) {
-      return UnlinkedTokenType.EQ;
-    } else if (type == TokenType.EQ_EQ) {
-      return UnlinkedTokenType.EQ_EQ;
-    } else if (type == Keyword.EXPORT) {
-      return UnlinkedTokenType.EXPORT;
-    } else if (type == Keyword.EXTENDS) {
-      return UnlinkedTokenType.EXTENDS;
-    } else if (type == Keyword.EXTERNAL) {
-      return UnlinkedTokenType.EXTERNAL;
-    } else if (type == Keyword.FACTORY) {
-      return UnlinkedTokenType.FACTORY;
-    } else if (type == Keyword.FALSE) {
-      return UnlinkedTokenType.FALSE;
-    } else if (type == Keyword.FINAL) {
-      return UnlinkedTokenType.FINAL;
-    } else if (type == Keyword.FINALLY) {
-      return UnlinkedTokenType.FINALLY;
-    } else if (type == Keyword.FOR) {
-      return UnlinkedTokenType.FOR;
-    } else if (type == Keyword.FUNCTION) {
-      return UnlinkedTokenType.FUNCTION_KEYWORD;
-    } else if (type == TokenType.FUNCTION) {
-      return UnlinkedTokenType.FUNCTION;
-    } else if (type == Keyword.GET) {
-      return UnlinkedTokenType.GET;
-    } else if (type == TokenType.GT) {
-      return UnlinkedTokenType.GT;
-    } else if (type == TokenType.GT_EQ) {
-      return UnlinkedTokenType.GT_EQ;
-    } else if (type == TokenType.GT_GT) {
-      return UnlinkedTokenType.GT_GT;
-    } else if (type == TokenType.GT_GT_EQ) {
-      return UnlinkedTokenType.GT_GT_EQ;
-    } else if (type == TokenType.HASH) {
-      return UnlinkedTokenType.HASH;
-    } else if (type == TokenType.HEXADECIMAL) {
-      return UnlinkedTokenType.HEXADECIMAL;
-    } else if (type == Keyword.HIDE) {
-      return UnlinkedTokenType.HIDE;
-    } else if (type == TokenType.IDENTIFIER) {
-      return UnlinkedTokenType.IDENTIFIER;
-    } else if (type == Keyword.IF) {
-      return UnlinkedTokenType.IF;
-    } else if (type == Keyword.IMPLEMENTS) {
-      return UnlinkedTokenType.IMPLEMENTS;
-    } else if (type == Keyword.IMPORT) {
-      return UnlinkedTokenType.IMPORT;
-    } else if (type == Keyword.IN) {
-      return UnlinkedTokenType.IN;
-    } else if (type == TokenType.INDEX) {
-      return UnlinkedTokenType.INDEX;
-    } else if (type == TokenType.INDEX_EQ) {
-      return UnlinkedTokenType.INDEX_EQ;
-    } else if (type == TokenType.INT) {
-      return UnlinkedTokenType.INT;
-    } else if (type == Keyword.INTERFACE) {
-      return UnlinkedTokenType.INTERFACE;
-    } else if (type == TokenType.IS) {
-      return UnlinkedTokenType.IS;
-    } else if (type == Keyword.LIBRARY) {
-      return UnlinkedTokenType.LIBRARY;
-    } else if (type == TokenType.LT) {
-      return UnlinkedTokenType.LT;
-    } else if (type == TokenType.LT_EQ) {
-      return UnlinkedTokenType.LT_EQ;
-    } else if (type == TokenType.LT_LT) {
-      return UnlinkedTokenType.LT_LT;
-    } else if (type == TokenType.LT_LT_EQ) {
-      return UnlinkedTokenType.LT_LT_EQ;
-    } else if (type == TokenType.MINUS) {
-      return UnlinkedTokenType.MINUS;
-    } else if (type == TokenType.MINUS_EQ) {
-      return UnlinkedTokenType.MINUS_EQ;
-    } else if (type == TokenType.MINUS_MINUS) {
-      return UnlinkedTokenType.MINUS_MINUS;
-    } else if (type == Keyword.MIXIN) {
-      return UnlinkedTokenType.MIXIN;
-    } else if (type == TokenType.MULTI_LINE_COMMENT) {
-      return UnlinkedTokenType.MULTI_LINE_COMMENT;
-    } else if (type == Keyword.NATIVE) {
-      return UnlinkedTokenType.NATIVE;
-    } else if (type == Keyword.NEW) {
-      return UnlinkedTokenType.NEW;
-    } else if (type == Keyword.NULL) {
-      return UnlinkedTokenType.NULL;
-    } else if (type == Keyword.OF) {
-      return UnlinkedTokenType.OF;
-    } else if (type == Keyword.ON) {
-      return UnlinkedTokenType.ON;
-    } else if (type == TokenType.OPEN_CURLY_BRACKET) {
-      return UnlinkedTokenType.OPEN_CURLY_BRACKET;
-    } else if (type == TokenType.OPEN_PAREN) {
-      return UnlinkedTokenType.OPEN_PAREN;
-    } else if (type == TokenType.OPEN_SQUARE_BRACKET) {
-      return UnlinkedTokenType.OPEN_SQUARE_BRACKET;
-    } else if (type == Keyword.OPERATOR) {
-      return UnlinkedTokenType.OPERATOR;
-    } else if (type == Keyword.PART) {
-      return UnlinkedTokenType.PART;
-    } else if (type == Keyword.PATCH) {
-      return UnlinkedTokenType.PATCH;
-    } else if (type == TokenType.PERCENT) {
-      return UnlinkedTokenType.PERCENT;
-    } else if (type == TokenType.PERCENT_EQ) {
-      return UnlinkedTokenType.PERCENT_EQ;
-    } else if (type == TokenType.PERIOD) {
-      return UnlinkedTokenType.PERIOD;
-    } else if (type == TokenType.PERIOD_PERIOD) {
-      return UnlinkedTokenType.PERIOD_PERIOD;
-    } else if (type == TokenType.PERIOD_PERIOD_PERIOD) {
-      return UnlinkedTokenType.PERIOD_PERIOD_PERIOD;
-    } else if (type == TokenType.PERIOD_PERIOD_PERIOD_QUESTION) {
-      return UnlinkedTokenType.PERIOD_PERIOD_PERIOD_QUESTION;
-    } else if (type == TokenType.PLUS) {
-      return UnlinkedTokenType.PLUS;
-    } else if (type == TokenType.PLUS_EQ) {
-      return UnlinkedTokenType.PLUS_EQ;
-    } else if (type == TokenType.PLUS_PLUS) {
-      return UnlinkedTokenType.PLUS_PLUS;
-    } else if (type == TokenType.QUESTION) {
-      return UnlinkedTokenType.QUESTION;
-    } else if (type == TokenType.QUESTION_PERIOD) {
-      return UnlinkedTokenType.QUESTION_PERIOD;
-    } else if (type == TokenType.QUESTION_QUESTION) {
-      return UnlinkedTokenType.QUESTION_QUESTION;
-    } else if (type == TokenType.QUESTION_QUESTION_EQ) {
-      return UnlinkedTokenType.QUESTION_QUESTION_EQ;
-    } else if (type == Keyword.RETHROW) {
-      return UnlinkedTokenType.RETHROW;
-    } else if (type == Keyword.RETURN) {
-      return UnlinkedTokenType.RETURN;
-    } else if (type == TokenType.SCRIPT_TAG) {
-      return UnlinkedTokenType.SCRIPT_TAG;
-    } else if (type == TokenType.SEMICOLON) {
-      return UnlinkedTokenType.SEMICOLON;
-    } else if (type == Keyword.SET) {
-      return UnlinkedTokenType.SET;
-    } else if (type == Keyword.SHOW) {
-      return UnlinkedTokenType.SHOW;
-    } else if (type == TokenType.SINGLE_LINE_COMMENT) {
-      return UnlinkedTokenType.SINGLE_LINE_COMMENT;
-    } else if (type == TokenType.SLASH) {
-      return UnlinkedTokenType.SLASH;
-    } else if (type == TokenType.SLASH_EQ) {
-      return UnlinkedTokenType.SLASH_EQ;
-    } else if (type == Keyword.SOURCE) {
-      return UnlinkedTokenType.SOURCE;
-    } else if (type == TokenType.STAR) {
-      return UnlinkedTokenType.STAR;
-    } else if (type == TokenType.STAR_EQ) {
-      return UnlinkedTokenType.STAR_EQ;
-    } else if (type == Keyword.STATIC) {
-      return UnlinkedTokenType.STATIC;
-    } else if (type == TokenType.STRING) {
-      return UnlinkedTokenType.STRING;
-    } else if (type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
-      return UnlinkedTokenType.STRING_INTERPOLATION_EXPRESSION;
-    } else if (type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
-      return UnlinkedTokenType.STRING_INTERPOLATION_IDENTIFIER;
-    } else if (type == Keyword.SUPER) {
-      return UnlinkedTokenType.SUPER;
-    } else if (type == Keyword.SWITCH) {
-      return UnlinkedTokenType.SWITCH;
-    } else if (type == Keyword.SYNC) {
-      return UnlinkedTokenType.SYNC;
-    } else if (type == Keyword.THIS) {
-      return UnlinkedTokenType.THIS;
-    } else if (type == Keyword.THROW) {
-      return UnlinkedTokenType.THROW;
-    } else if (type == TokenType.TILDE) {
-      return UnlinkedTokenType.TILDE;
-    } else if (type == TokenType.TILDE_SLASH) {
-      return UnlinkedTokenType.TILDE_SLASH;
-    } else if (type == TokenType.TILDE_SLASH_EQ) {
-      return UnlinkedTokenType.TILDE_SLASH_EQ;
-    } else if (type == Keyword.TRUE) {
-      return UnlinkedTokenType.TRUE;
-    } else if (type == Keyword.TRY) {
-      return UnlinkedTokenType.TRY;
-    } else if (type == Keyword.TYPEDEF) {
-      return UnlinkedTokenType.TYPEDEF;
-    } else if (type == Keyword.VAR) {
-      return UnlinkedTokenType.VAR;
-    } else if (type == Keyword.VOID) {
-      return UnlinkedTokenType.VOID;
-    } else if (type == Keyword.WHILE) {
-      return UnlinkedTokenType.WHILE;
-    } else if (type == Keyword.WITH) {
-      return UnlinkedTokenType.WITH;
-    } else if (type == Keyword.YIELD) {
-      return UnlinkedTokenType.YIELD;
-    } else {
-      throw StateError('Unexpected type: $type');
-    }
+    return _linkingBundleContext.writeType(type);
   }
 }
diff --git a/pkg/analyzer/lib/src/summary2/ast_resolver.dart b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
new file mode 100644
index 0000000..c3dcf81
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2019, 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 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/ast_binary_writer.dart';
+import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
+import 'package:analyzer/src/summary2/link.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+
+/// Used to resolve some AST nodes - variable initializers, and annotations.
+class AstResolver {
+  final Linker _linker;
+
+  LibraryElement _library;
+  Scope _nameScope;
+
+  AstResolver(this._linker, Reference libraryRef) {
+    _library = _linker.elementFactory.elementOfReference(libraryRef);
+    _nameScope = LibraryScope(_library);
+  }
+
+  LinkedNode resolve(UnitBuilder unit, AstNode node) {
+    var source = _FakeSource();
+    var errorListener = AnalysisErrorListener.NULL_LISTENER;
+
+    var typeResolverVisitor = new TypeResolverVisitor(
+        _library, source, _linker.typeProvider, errorListener,
+        nameScope: _nameScope);
+    node.accept(typeResolverVisitor);
+
+//    expression.accept(_astRewriteVisitor);
+//    expression.accept(_variableResolverVisitor);
+//    if (_linker.getAst != null) {
+//      expression.accept(_partialResolverVisitor);
+//    }
+
+    var resolverVisitor = new ResolverVisitor(_linker.inheritance, _library,
+        source, _linker.typeProvider, errorListener,
+        nameScope: _nameScope,
+        propagateTypes: false,
+        reportConstEvaluationErrors: false);
+    node.accept(resolverVisitor);
+
+    var writer = AstBinaryWriter(
+      _linker.linkingBundleContext,
+      unit.context.tokensContext,
+    );
+    return writer.writeNode(node);
+  }
+}
+
+class _FakeSource implements Source {
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/analyzer/lib/src/summary2/builder/library_builder.dart b/pkg/analyzer/lib/src/summary2/builder/library_builder.dart
deleted file mode 100644
index a816247..0000000
--- a/pkg/analyzer/lib/src/summary2/builder/library_builder.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2019, 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 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/builder/prefix_builder.dart';
-import 'package:analyzer/src/summary2/declaration.dart';
-import 'package:analyzer/src/summary2/linked_unit_context.dart';
-import 'package:analyzer/src/summary2/reference.dart';
-import 'package:analyzer/src/summary2/scope.dart';
-
-class LibraryBuilder {
-  final Uri uri;
-  final Reference reference;
-  final List<UnitBuilder> units = [];
-
-  /// The import scope of the library.
-  final Scope importScope;
-
-  /// Local declarations, enclosed by [importScope].
-  final Scope scope;
-
-  /// The export scope of the library.
-  final Scope exportScope = Scope.top();
-
-  LibraryBuilder(Uri uri, Reference reference)
-      : this._(uri, reference, Scope.top());
-
-  LibraryBuilder._(this.uri, this.reference, this.importScope)
-      : scope = Scope(importScope, <String, Declaration>{});
-
-  /// Add top-level declaration of the library units to the local scope.
-  void addLocalDeclarations() {
-    for (var unit in units) {
-      for (var node in unit.node.compilationUnit_declarations) {
-        if (node.kind == LinkedNodeKind.classDeclaration) {
-          var name = unit.context.getUnitMemberName(node);
-          var reference = this.reference.getChild('@class').getChild(name);
-          reference.node = node;
-          var declaration = Declaration(name, reference);
-          scope.declare(name, declaration);
-        } else {
-          // TODO(scheglov) implement
-          throw UnimplementedError();
-        }
-      }
-    }
-  }
-
-  /// Return `true` if the export scope was modified.
-  bool addToExportScope(String name, Declaration declaration) {
-    if (name.startsWith('_')) return false;
-    if (declaration is PrefixBuilder) return false;
-
-    var existing = exportScope.map[name];
-    if (existing == declaration) return false;
-
-    // Ambiguous declaration detected.
-    if (existing != null) return false;
-
-    exportScope.map[name] = declaration;
-    return true;
-  }
-
-  void addUnit(LinkedUnitContext context, LinkedNode node) {
-    units.add(UnitBuilder(context, node));
-  }
-
-  void buildInitialExportScope() {
-    // TODO(scheglov) Maybe store export scopes in summaries?
-    scope.forEach((name, declaration) {
-      addToExportScope(name, declaration);
-    });
-  }
-}
-
-class UnitBuilder {
-  final LinkedUnitContext context;
-  final LinkedNode node;
-
-  UnitBuilder(this.context, this.node);
-}
diff --git a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
index c676b9b..f029ec9 100644
--- a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
@@ -2,27 +2,170 @@
 // 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 'package:analyzer/dart/ast/ast.dart' as ast;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/builder/library_builder.dart';
+import 'package:analyzer/src/summary2/ast_binary_writer.dart';
+import 'package:analyzer/src/summary2/builder/prefix_builder.dart';
+import 'package:analyzer/src/summary2/declaration.dart';
 import 'package:analyzer/src/summary2/link.dart';
-import 'package:analyzer/src/summary2/linked_bundle_context.dart';
 import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/metadata_resolver.dart';
 import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/reference_resolver.dart';
+import 'package:analyzer/src/summary2/scope.dart';
+import 'package:analyzer/src/summary2/tokens_writer.dart';
+import 'package:analyzer/src/summary2/top_level_inference.dart';
 
-class SourceLibraryBuilder extends LibraryBuilder {
+class SourceLibraryBuilder {
   final Linker linker;
-  final LinkedBundleContext bundleContext;
+  final Uri uri;
   final Reference reference;
+  final LinkedNodeLibraryBuilder node;
+  final List<UnitBuilder> units = [];
 
-  SourceLibraryBuilder(this.linker, this.bundleContext, Uri uri, this.reference)
-      : super(uri, reference);
+  /// The import scope of the library.
+  final Scope importScope;
+
+  /// Local declarations, enclosed by [importScope].
+  final Scope scope;
+
+  /// The export scope of the library.
+  final Scope exportScope = Scope.top();
+
+  SourceLibraryBuilder(Linker linker, Uri uri, Reference reference,
+      LinkedNodeLibraryBuilder node)
+      : this._(linker, uri, reference, node, Scope.top());
+
+  SourceLibraryBuilder._(
+      this.linker, this.uri, this.reference, this.node, this.importScope)
+      : scope = Scope(importScope, <String, Declaration>{});
+
+  void addImportsToScope() {
+    // TODO
+    var hasDartCore = false;
+    var unitContext = units[0].context;
+    for (var directive in units[0].node.compilationUnit_directives) {
+      if (directive.kind == LinkedNodeKind.importDirective) {
+        var relativeUriStr = unitContext.getStringContent(
+          directive.uriBasedDirective_uri,
+        );
+        var relativeUri = Uri.parse(relativeUriStr);
+        var uri = resolveRelativeUri(this.uri, relativeUri);
+        var builder = linker.builders[uri];
+        if (builder != null) {
+          builder.exportScope.forEach((name, declaration) {
+            importScope.declare(name, declaration);
+          });
+        } else {
+          var references = linker.elementFactory.exportsOfLibrary('$uri');
+          _importExportedReferences(references);
+        }
+        // TODO(scheglov) prefix
+        // TODO(scheglov) combinators
+      }
+    }
+    if (!hasDartCore) {
+      var importDartCore = LinkedNodeBuilder.importDirective(
+        uriBasedDirective_uri: LinkedNodeBuilder.simpleStringLiteral(
+          simpleStringLiteral_value: 'dart:core',
+        ),
+      )..isSynthetic = true;
+      units[0].node.compilationUnit_directives.add(importDartCore);
+
+      // TODO(scheglov) This works only when dart:core is linked
+      var references = linker.elementFactory.exportsOfLibrary('dart:core');
+      _importExportedReferences(references);
+    }
+  }
+
+  /// Add top-level declaration of the library units to the local scope.
+  void addLocalDeclarations() {
+    for (var unit in units) {
+      var unitRef = reference.getChild('@unit').getChild('${unit.uri}');
+      var classRef = unitRef.getChild('@class');
+      var enumRef = unitRef.getChild('@enum');
+      var functionRef = unitRef.getChild('@function');
+      var typeAliasRef = unitRef.getChild('@typeAlias');
+      var getterRef = unitRef.getChild('@getter');
+      var setterRef = unitRef.getChild('@setter');
+      var variableRef = unitRef.getChild('@variable');
+      for (var node in unit.node.compilationUnit_declarations) {
+        if (node.kind == LinkedNodeKind.classDeclaration ||
+            node.kind == LinkedNodeKind.classTypeAlias) {
+          var name = unit.context.getUnitMemberName(node);
+          var reference = classRef.getChild(name);
+          reference.node = node;
+          var declaration = Declaration(name, reference);
+          scope.declare(name, declaration);
+        } else if (node.kind == LinkedNodeKind.enumDeclaration) {
+          var name = unit.context.getUnitMemberName(node);
+          var reference = enumRef.getChild(name);
+          reference.node = node;
+          var declaration = Declaration(name, reference);
+          scope.declare(name, declaration);
+        } else if (node.kind == LinkedNodeKind.functionDeclaration) {
+          var name = unit.context.getUnitMemberName(node);
+
+          Reference containerRef;
+          if (unit.context.isGetterFunction(node)) {
+            containerRef = getterRef;
+          } else if (unit.context.isSetterFunction(node)) {
+            containerRef = setterRef;
+          } else {
+            containerRef = functionRef;
+          }
+
+          var reference = containerRef.getChild(name);
+          reference.node = node;
+
+          var declaration = Declaration(name, reference);
+          scope.declare(name, declaration);
+        } else if (node.kind == LinkedNodeKind.functionTypeAlias) {
+          var name = unit.context.getUnitMemberName(node);
+          var reference = typeAliasRef.getChild(name);
+          reference.node = node;
+
+          var declaration = Declaration(name, reference);
+          scope.declare(name, declaration);
+        } else if (node.kind == LinkedNodeKind.genericTypeAlias) {
+          var name = unit.context.getUnitMemberName(node);
+          var reference = typeAliasRef.getChild(name);
+          reference.node = node;
+
+          var declaration = Declaration(name, reference);
+          scope.declare(name, declaration);
+        } else if (node.kind == LinkedNodeKind.topLevelVariableDeclaration) {
+          var variableList = node.topLevelVariableDeclaration_variableList;
+          for (var variable in variableList.variableDeclarationList_variables) {
+            var name = unit.context.getVariableName(variable);
+
+            var reference = variableRef.getChild(name);
+            reference.node = node;
+
+            var getter = getterRef.getChild(name);
+            scope.declare(name, Declaration(name, getter));
+
+            if (!unit.context.isFinal(variable)) {
+              var setter = setterRef.getChild(name);
+              scope.declare('$name=', Declaration(name, setter));
+            }
+          }
+        } else {
+          // TODO(scheglov) implement
+          throw UnimplementedError('${node.kind}');
+        }
+      }
+    }
+  }
 
   void addSyntheticConstructors() {
     for (var declaration in scope.map.values) {
       var reference = declaration.reference;
       var node = reference.node;
-
+      if (node == null) continue;
       if (node.kind != LinkedNodeKind.classDeclaration) continue;
 
       // Skip the class if it already has a constructor.
@@ -35,75 +178,154 @@
         LinkedNodeBuilder.constructorDeclaration(
           constructorDeclaration_parameters:
               LinkedNodeBuilder.formalParameterList(),
+          constructorDeclaration_body: LinkedNodeBuilder.emptyFunctionBody(),
         )..isSynthetic = true,
       );
     }
   }
 
+  /// Return `true` if the export scope was modified.
+  bool addToExportScope(String name, Declaration declaration) {
+    if (name.startsWith('_')) return false;
+    if (declaration is PrefixBuilder) return false;
+
+    var existing = exportScope.map[name];
+    if (existing == declaration) return false;
+
+    // Ambiguous declaration detected.
+    if (existing != null) return false;
+
+    exportScope.map[name] = declaration;
+    return true;
+  }
+
+  void buildInitialExportScope() {
+    scope.forEach((name, declaration) {
+      addToExportScope(name, declaration);
+    });
+  }
+
+  void performTopLevelInference() {
+    for (var unit in units) {
+      TopLevelInference(linker, reference, unit).infer();
+    }
+  }
+
+  void resolveMetadata() {
+    var metadataResolver = MetadataResolver(linker, reference);
+    for (var unit in units) {
+      metadataResolver.resolve(unit);
+    }
+  }
+
   void resolveTypes() {
     for (var unit in units) {
-      for (var node in unit.node.compilationUnit_declarations) {
-        if (node.kind == LinkedNodeKind.classDeclaration) {
-          var extendsClause = node.classDeclaration_extendsClause;
-          if (extendsClause != null) {
-            _resolveTypeName(
-              unit.context,
-              extendsClause.extendsClause_superclass,
-            );
-          }
+      var unitReference = reference.getChild('@unit').getChild('${unit.uri}');
+      ReferenceResolver(
+        linker.linkingBundleContext,
+        unit,
+        scope,
+        unitReference,
+      ).resolve();
+    }
+  }
 
-          var withClause = node.classDeclaration_withClause;
-          if (withClause != null) {
-            for (var typeName in withClause.withClause_mixinTypes) {
-              _resolveTypeName(unit.context, typeName);
+  void storeExportScope() {
+    var linkingBundleContext = linker.linkingBundleContext;
+    for (var declaration in exportScope.map.values) {
+      var reference = declaration.reference;
+      var index = linkingBundleContext.indexOfReference(reference);
+      node.exports.add(index);
+    }
+  }
+
+  void _importExportedReferences(List<Reference> exportedReferences) {
+    for (var reference in exportedReferences) {
+      var name = reference.name;
+      importScope.declare(name, Declaration(name, reference));
+    }
+  }
+
+  static void build(Linker linker, Source librarySource,
+      Map<Source, ast.CompilationUnit> libraryUnits) {
+    var libraryUriStr = librarySource.uri.toString();
+    var libraryReference = linker.rootReference.getChild(libraryUriStr);
+
+    var unitNodeList = <LinkedNodeUnitBuilder>[];
+    var libraryNode = LinkedNodeLibraryBuilder(
+      units: unitNodeList,
+      uriStr: libraryUriStr,
+    );
+
+    var builder = SourceLibraryBuilder(
+      linker,
+      librarySource.uri,
+      libraryReference,
+      libraryNode,
+    );
+
+    ast.CompilationUnit definingUnit;
+    for (var unitSource in libraryUnits.keys) {
+      var unit = libraryUnits[unitSource];
+      definingUnit ??= unit;
+
+      var tokensResult = TokensWriter().writeTokens(
+        unit.beginToken,
+        unit.endToken,
+      );
+      var tokensContext = tokensResult.toContext();
+
+      var unitContext = LinkedUnitContext(
+        linker.bundleContext,
+        tokensContext,
+      );
+
+      var writer = AstBinaryWriter(linker.linkingBundleContext, tokensContext);
+      var unitNode = writer.writeNode(unit);
+
+      builder.units.add(
+        UnitBuilder(unitSource.uri, unitContext, unitNode),
+      );
+
+      libraryNode.units.add(
+        LinkedNodeUnitBuilder(
+          uriStr: '${unitSource.uri}',
+          tokens: tokensResult.tokens,
+          node: unitNode,
+        ),
+      );
+
+      if (libraryUriStr == 'dart:core') {
+        for (var declaration in unitNode.compilationUnit_declarations) {
+          if (declaration.kind == LinkedNodeKind.classDeclaration) {
+            var nameNode = declaration.namedCompilationUnitMember_name;
+            if (unitContext.getSimpleName(nameNode) == 'Object') {
+              declaration.classDeclaration_isDartObject = true;
             }
           }
-
-          var implementsClause = node.classOrMixinDeclaration_implementsClause;
-          if (implementsClause != null) {
-            for (var typeName in implementsClause.implementsClause_interfaces) {
-              _resolveTypeName(unit.context, typeName);
-            }
-          }
-
-          // TODO(scheglov) type parameters
-          assert(node.classOrMixinDeclaration_typeParameters == null);
-        } else {
-          // TODO(scheglov) implement
-          throw UnimplementedError();
         }
       }
     }
-  }
 
-  int _referenceIndex(Reference reference) {
-    if (reference.index == null) {
-      reference.index = linker.references.length;
-      linker.references.add(reference);
-    }
-    return reference.index;
-  }
-
-  void _resolveTypeName(LinkedUnitContext context, LinkedNodeBuilder typeName) {
-    var identifier = typeName.typeName_name;
-    if (identifier.kind == LinkedNodeKind.simpleIdentifier) {
-      var name = context.getSimpleName(identifier);
-      var reference = exportScope.lookup(name).reference;
-      var referenceIndex = _referenceIndex(reference);
-      identifier.simpleIdentifier_element = referenceIndex;
-      if (reference.isClass) {
-        typeName.typeName_type = LinkedNodeTypeBuilder(
-          kind: LinkedNodeTypeKind.interface,
-          interfaceClass: referenceIndex,
-        );
-        // TODO(scheglov) type arguments
-      } else {
-        // TODO(scheglov) set Object? keep unresolved?
-        throw UnimplementedError();
+    for (var directive in definingUnit.directives) {
+      if (directive is ast.LibraryDirective) {
+        var name = directive.name;
+        libraryNode.name = name.components.map((id) => id.name).join('.');
+        libraryNode.nameOffset = name.offset;
+        libraryNode.nameLength = name.length;
+        break;
       }
-    } else {
-      // TODO(scheglov) implement
-      throw UnimplementedError();
     }
+
+    linker.linkingLibraries.add(libraryNode);
+    linker.builders[builder.uri] = builder;
   }
 }
+
+class UnitBuilder {
+  final Uri uri;
+  final LinkedUnitContext context;
+  final LinkedNode node;
+
+  UnitBuilder(this.uri, this.context, this.node);
+}
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index e24fc84..aec825a 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -2,140 +2,193 @@
 // 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 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit;
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/ast_binary_writer.dart';
-import 'package:analyzer/src/summary2/builder/library_builder.dart';
+import 'package:analyzer/src/summary/summary_sdk.dart';
 import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
 import 'package:analyzer/src/summary2/linked_bundle_context.dart';
-import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
+import 'package:analyzer/src/summary2/linking_bundle_context.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 
 LinkResult link(
-  Reference rootReference,
+  AnalysisOptions analysisOptions,
+  SourceFactory sourceFactory,
+  List<LinkedNodeBundle> inputs,
   Map<Source, Map<Source, CompilationUnit>> unitMap,
 ) {
-  var linker = Linker(rootReference);
-  linker.link(unitMap);
-  return LinkResult(linker.references, linker.libraryResults);
-}
-
-class LibraryLinkResult {
-  final Source source;
-  final Map<Source, UnitLinkResult> units;
-
-  LibraryLinkResult(this.source, this.units);
+  var linker = Linker(analysisOptions, sourceFactory);
+  linker.link(inputs, unitMap);
+  return LinkResult(linker.linkingBundle);
 }
 
 class Linker {
-  final Reference rootReference;
+  final Reference rootReference = Reference.root();
+  LinkedElementFactory elementFactory;
 
-  /// References used in all libraries being linked.
-  /// Element references in [LinkedNode]s are indexes in this list.
-  final List<Reference> references = [null];
+  LinkingBundleContext linkingBundleContext;
+  List<LinkedNodeLibraryBuilder> linkingLibraries = [];
+  LinkedNodeBundleBuilder linkingBundle;
+  LinkedBundleContext bundleContext;
 
-  /// The output results.
-  var libraryResults = <Source, LibraryLinkResult>{};
+  /// Libraries that are being linked.
+  final Map<Uri, SourceLibraryBuilder> builders = {};
 
-  /// Libraries that are being linked, or are already linked.
-  final Map<Uri, LibraryBuilder> builders = {};
+  _AnalysisContextForLinking analysisContext;
+  TypeProvider typeProvider;
+  Dart2TypeSystem typeSystem;
+  InheritanceManager2 inheritance;
 
-  Linker(this.rootReference);
+  Linker(AnalysisOptions analysisOptions, SourceFactory sourceFactory) {
+    var dynamicRef = rootReference.getChild('dart:core').getChild('dynamic');
+    dynamicRef.element = DynamicElementImpl.instance;
 
-  void addBuilder(LibraryBuilder builder) {
-    builders[builder.uri] = builder;
+    linkingBundleContext = LinkingBundleContext(dynamicRef);
+
+    analysisContext = _AnalysisContextForLinking(
+      analysisOptions,
+      sourceFactory,
+    );
+
+    elementFactory = LinkedElementFactory(
+      analysisContext,
+      _AnalysisSessionForLinking(),
+      rootReference,
+    );
+
+    linkingBundle = LinkedNodeBundleBuilder(
+      references: linkingBundleContext.referencesBuilder,
+      libraries: linkingLibraries,
+    );
+
+    bundleContext = LinkedBundleContext(
+      elementFactory,
+      linkingBundle.references,
+    );
   }
 
-  void addSyntheticConstructors() {
+  void link(List<LinkedNodeBundle> inputs,
+      Map<Source, Map<Source, CompilationUnit>> unitMap) {
+    for (var input in inputs) {
+      elementFactory.addBundle(input);
+    }
+
+    for (var librarySource in unitMap.keys) {
+      SourceLibraryBuilder.build(this, librarySource, unitMap[librarySource]);
+    }
+
+    // Add libraries being linked, so we can ask for their elements as well.
+    elementFactory.addBundle(linkingBundle, context: bundleContext);
+
+    _buildOutlines();
+  }
+
+  void _addSyntheticConstructors() {
     for (var library in builders.values) {
-      if (library is SourceLibraryBuilder) {
-        library.addSyntheticConstructors();
-      }
+      library.addSyntheticConstructors();
     }
   }
 
-  void buildOutlines() {
-    computeLibraryScopes();
-    resolveTypes();
-    addSyntheticConstructors();
+  void _buildOutlines() {
+    _computeLibraryScopes();
+    _addSyntheticConstructors();
+    _createTypeSystem();
+    _resolveTypes();
+    _performTopLevelInference();
+    _resolveMetadata();
   }
 
-  void computeLibraryScopes() {
-    for (var uri in builders.keys) {
-      var library = builders[uri];
+  void _computeLibraryScopes() {
+    for (var library in builders.values) {
+      library.addLocalDeclarations();
+    }
+
+    for (var library in builders.values) {
       library.buildInitialExportScope();
     }
 
+    for (var library in builders.values) {
+      library.addImportsToScope();
+    }
+
+    for (var library in builders.values) {
+      library.storeExportScope();
+    }
+
     // TODO(scheglov) process imports and exports
   }
 
-  void link(Map<Source, Map<Source, CompilationUnit>> unitMap) {
-    var linkedBundleContext = LinkedBundleContext(references);
-    for (var librarySource in unitMap.keys) {
-      var libraryUriStr = librarySource.uri.toString();
-      var libraryReference = rootReference.getChild(libraryUriStr);
+  void _createTypeSystem() {
+    var coreRef = rootReference.getChild('dart:core');
+    var coreLib = elementFactory.elementOfReference(coreRef);
+    typeProvider = SummaryTypeProvider()..initializeCore(coreLib);
+    analysisContext.typeProvider = typeProvider;
 
-      var unitResults = <Source, UnitLinkResult>{};
-      libraryResults[librarySource] = LibraryLinkResult(
-        librarySource,
-        unitResults,
-      );
+    typeSystem = Dart2TypeSystem(typeProvider);
+    analysisContext.typeSystem = typeSystem;
 
-      var libraryBuilder = SourceLibraryBuilder(
-        this,
-        linkedBundleContext,
-        librarySource.uri,
-        libraryReference,
-      );
-      addBuilder(libraryBuilder);
-
-      var libraryUnits = unitMap[librarySource];
-      for (var unitSource in libraryUnits.keys) {
-        var unit = libraryUnits[unitSource];
-
-        var writer = AstBinaryWriter();
-        var unitData = writer.writeNode(unit);
-
-        var unitLinkResult = UnitLinkResult(writer.tokens, unitData);
-        unitResults[unitSource] = unitLinkResult;
-
-        var linkedUnitContext = LinkedUnitContext(
-          linkedBundleContext,
-          writer.tokens,
-        );
-        libraryBuilder.addUnit(linkedUnitContext, unitData);
-      }
-
-      libraryBuilder.addLocalDeclarations();
-    }
-
-    buildOutlines();
+    inheritance = InheritanceManager2(typeSystem);
   }
 
-  void resolveTypes() {
-    for (var uri in builders.keys) {
-      var library = builders[uri];
-      if (library is SourceLibraryBuilder) {
-        library.resolveTypes();
-      }
+  void _performTopLevelInference() {
+    for (var library in builders.values) {
+      library.performTopLevelInference();
+    }
+  }
+
+  void _resolveMetadata() {
+    for (var library in builders.values) {
+      library.resolveMetadata();
+    }
+  }
+
+  void _resolveTypes() {
+    for (var library in builders.values) {
+      library.resolveTypes();
     }
   }
 }
 
 class LinkResult {
-  /// Element references in [LinkedNode]s are indexes in this list.
-  final List<Reference> references;
+  final LinkedNodeBundleBuilder bundle;
 
-  final Map<Source, LibraryLinkResult> libraries;
-
-  LinkResult(this.references, this.libraries);
+  LinkResult(this.bundle);
 }
 
-class UnitLinkResult {
-  final UnlinkedTokensBuilder tokens;
-  final LinkedNodeBuilder node;
+class _AnalysisContextForLinking implements InternalAnalysisContext {
+  @override
+  final AnalysisOptions analysisOptions;
 
-  UnitLinkResult(this.tokens, this.node);
+  @override
+  final SourceFactory sourceFactory;
+
+  @override
+  TypeProvider typeProvider;
+
+  @override
+  TypeSystem typeSystem;
+
+  _AnalysisContextForLinking(this.analysisOptions, this.sourceFactory);
+
+  @override
+  Namespace getPublicNamespace(LibraryElement library) {
+    // TODO(scheglov) Not sure if this method of AnalysisContext is useful.
+    var builder = new NamespaceBuilder();
+    return builder.createPublicNamespaceForLibrary(library);
+  }
+
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+class _AnalysisSessionForLinking implements AnalysisSession {
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
diff --git a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
index 2b1d0ed..fbaf454 100644
--- a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
@@ -2,24 +2,107 @@
 // 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 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 
 /// The context of a linked bundle, with shared references.
 class LinkedBundleContext {
-  final List<Reference> references;
+  final LinkedElementFactory elementFactory;
+  final LinkedNodeReferences referencesData;
+  final List<Reference> _references;
 
-  LinkedBundleContext(this.references);
+  LinkedBundleContext(this.elementFactory, this.referencesData)
+      : _references = List<Reference>.filled(referencesData.name.length, null,
+            growable: true);
+
+  T elementOfIndex<T extends Element>(int index) {
+    var reference = referenceOfIndex(index);
+    return elementFactory.elementOfReference(reference);
+  }
+
+  List<T> elementsOfIndexes<T extends Element>(List<int> indexList) {
+    var result = List<T>(indexList.length);
+    for (var i = 0; i < indexList.length; ++i) {
+      var index = indexList[i];
+      result[i] = elementOfIndex(index);
+    }
+    return result;
+  }
 
   InterfaceType getInterfaceType(LinkedNodeType linkedType) {
-    if (linkedType.kind == LinkedNodeTypeKind.interface) {
-      var element = references[linkedType.interfaceClass].element;
-      // TODO(scheglov) type arguments
-      assert(linkedType.interfaceTypeArguments.isEmpty);
-      return InterfaceTypeImpl.explicit(element, []);
+    var type = getType(linkedType);
+    if (type is InterfaceType && !type.element.isEnum) {
+      return type;
     }
     return null;
   }
+
+  DartType getType(LinkedNodeType linkedType) {
+    var kind = linkedType.kind;
+    if (kind == LinkedNodeTypeKind.dynamic_) {
+      return DynamicTypeImpl.instance;
+    } else if (kind == LinkedNodeTypeKind.function) {
+      var returnType = getType(linkedType.functionReturnType);
+      var typeParameters = linkedType.functionTypeParameters
+          .map(referenceOfIndex)
+          .map(elementFactory.elementOfReference)
+          .cast<TypeParameterElement>()
+          .toList();
+      var formalParameters = linkedType.functionFormalParameters
+          .map(referenceOfIndex)
+          .map(elementFactory.elementOfReference)
+          .cast<ParameterElement>()
+          .toList();
+      // TODO(scheglov) Rework this to purely synthetic types.
+      return FunctionElementImpl.synthetic(formalParameters, returnType).type;
+    } else if (kind == LinkedNodeTypeKind.interface) {
+      var reference = referenceOfIndex(linkedType.interfaceClass);
+      Element element = elementFactory.elementOfReference(reference);
+      return InterfaceTypeImpl.explicit(
+        element,
+        linkedType.interfaceTypeArguments.map(getType).toList(),
+      );
+    } else if (kind == LinkedNodeTypeKind.typeParameter) {
+      var reference = referenceOfIndex(linkedType.typeParameterParameter);
+      Element element = elementFactory.elementOfReference(reference);
+      return TypeParameterTypeImpl(element);
+    } else if (kind == LinkedNodeTypeKind.void_) {
+      return VoidTypeImpl.instance;
+    } else {
+      throw UnimplementedError('$kind');
+    }
+  }
+
+  Reference referenceOfIndex(int index) {
+    // When we are linking a bundle, we add new references.
+    // So, grow the list of references when we have data for them.
+    if (index >= _references.length) {
+      if (referencesData.name.length > _references.length) {
+        _references.length = referencesData.name.length;
+      }
+    }
+
+    var reference = _references[index];
+    if (reference != null) return reference;
+
+    if (index == 0) {
+      reference = elementFactory.rootReference;
+      _references[index] = reference;
+      return reference;
+    }
+
+    var parentIndex = referencesData.parent[index];
+    var parent = referenceOfIndex(parentIndex);
+
+    var name = referencesData.name[index];
+    reference = parent.getChild(name);
+    _references[index] = reference;
+
+    return reference;
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
new file mode 100644
index 0000000..7653ed6
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -0,0 +1,299 @@
+// Copyright (c) 2019, 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 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/linked_bundle_context.dart';
+import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/tokens_context.dart';
+
+class LinkedElementFactory {
+  final AnalysisContext analysisContext;
+  final AnalysisSession analysisSession;
+  final Reference rootReference;
+  final Map<String, _Library> libraryMap = {};
+
+  LinkedElementFactory(
+      this.analysisContext, this.analysisSession, this.rootReference);
+
+  void addBundle(LinkedNodeBundle bundle, {LinkedBundleContext context}) {
+    context ??= LinkedBundleContext(this, bundle.references);
+    for (var library in bundle.libraries) {
+      libraryMap[library.uriStr] = _Library(context, library);
+    }
+  }
+
+  Element elementOfReference(Reference reference) {
+    if (reference.element != null) {
+      return reference.element;
+    }
+    if (reference.parent == null) {
+      return null;
+    }
+
+    return _ElementRequest(this, reference).elementOfReference(reference);
+  }
+
+  List<Reference> exportsOfLibrary(String uriStr) {
+    var library = libraryMap[uriStr];
+    var exportIndexList = library.node.exports;
+    var exportReferences = List<Reference>(exportIndexList.length);
+    for (var i = 0; i < exportIndexList.length; ++i) {
+      var index = exportIndexList[i];
+      var reference = library.context.referenceOfIndex(index);
+      exportReferences[i] = reference;
+    }
+    return exportReferences;
+  }
+
+  LibraryElementImpl libraryOfUri(String uriStr) {
+    var reference = rootReference.getChild(uriStr);
+    return elementOfReference(reference);
+  }
+}
+
+class _ElementRequest {
+  final LinkedElementFactory elementFactory;
+  final Reference input;
+
+  _ElementRequest(this.elementFactory, this.input);
+
+  ElementImpl elementOfReference(Reference reference) {
+    if (reference.element != null) {
+      return reference.element;
+    }
+
+    var parent2 = reference.parent.parent;
+    if (parent2 == null) {
+      return _createLibraryElement(reference);
+    }
+
+    var parentName = reference.parent.name;
+
+    if (parentName == '@class') {
+      var unit = elementOfReference(parent2);
+      return _class(unit, reference);
+    }
+
+    if (parentName == '@constructor') {
+      var class_ = elementOfReference(parent2);
+      return _constructor(class_, reference);
+    }
+
+    if (parentName == '@function') {
+      CompilationUnitElementImpl enclosing = elementOfReference(parent2);
+      return _function(enclosing, reference);
+    }
+
+    if (parentName == '@getter') {
+      var enclosing = elementOfReference(parent2);
+      return _getter(enclosing, reference);
+    }
+
+    if (parentName == '@method') {
+      var enclosing = elementOfReference(parent2);
+      return _method(enclosing, reference);
+    }
+
+    if (parentName == '@parameter') {
+      ExecutableElementImpl enclosing = elementOfReference(parent2);
+      return _parameter(enclosing, reference);
+    }
+
+    if (parentName == '@typeAlias') {
+      var unit = elementOfReference(parent2);
+      return _typeAlias(unit, reference);
+    }
+
+    if (parentName == '@typeParameter') {
+      var enclosing = elementOfReference(parent2) as TypeParameterizedElement;
+      return _typeParameter(enclosing, reference);
+    }
+
+    if (parentName == '@unit') {
+      elementOfReference(parent2);
+      // Creating a library fills all its units.
+      assert(reference.element != null);
+      return reference.element;
+    }
+
+    // TODO(scheglov) support other elements
+    throw StateError('Not found: $input');
+  }
+
+  ClassElementImpl _class(
+      CompilationUnitElementImpl unit, Reference reference) {
+    if (reference.node == null) {
+      _indexUnitDeclarations(unit);
+      assert(reference.node != 0, '$reference');
+    }
+    return reference.element = ClassElementImpl.forLinkedNode(
+      unit,
+      reference,
+      reference.node,
+    );
+  }
+
+  ConstructorElementImpl _constructor(
+      ClassElementImpl class_, Reference reference) {
+    return reference.element = ConstructorElementImpl.forLinkedNode(
+      reference,
+      reference.node,
+      class_,
+    );
+  }
+
+  LibraryElementImpl _createLibraryElement(Reference reference) {
+    var uriStr = reference.name;
+
+    var sourceFactory = elementFactory.analysisContext.sourceFactory;
+    var librarySource = sourceFactory.forUri(uriStr);
+
+    var libraryData = elementFactory.libraryMap[uriStr];
+    var node = libraryData.node;
+    var hasName = node.name.isNotEmpty;
+
+    var definingUnitData = node.units[0];
+    var definingUnitContext = LinkedUnitContext(
+      libraryData.context,
+      TokensContext(definingUnitData.tokens),
+    );
+
+    var libraryElement = LibraryElementImpl.forLinkedNode(
+      elementFactory.analysisContext,
+      elementFactory.analysisSession,
+      node.name,
+      hasName ? node.nameOffset : -1,
+      node.name.length,
+      definingUnitContext,
+      reference,
+      definingUnitData.node,
+    );
+
+    var units = <CompilationUnitElementImpl>[];
+    var unitContainerRef = reference.getChild('@unit');
+    for (var unitData in node.units) {
+      var unitSource = sourceFactory.forUri(unitData.uriStr);
+      var tokensContext = TokensContext(unitData.tokens);
+      var unitElement = CompilationUnitElementImpl.forLinkedNode(
+        libraryElement,
+        LinkedUnitContext(libraryData.context, tokensContext),
+        unitContainerRef.getChild(unitData.uriStr),
+        unitData.node,
+      );
+      unitElement.source = unitSource;
+      unitElement.librarySource = librarySource;
+      units.add(unitElement);
+      unitContainerRef.getChild(unitData.uriStr).element = unitElement;
+    }
+
+    libraryElement.definingCompilationUnit = units[0];
+    libraryElement.parts = units.skip(1).toList();
+    return reference.element = libraryElement;
+  }
+
+  Element _function(CompilationUnitElementImpl enclosing, Reference reference) {
+    enclosing.functions;
+    assert(reference.element != null);
+    return reference.element;
+  }
+
+  PropertyAccessorElementImpl _getter(
+      ElementImpl enclosing, Reference reference) {
+    if (enclosing is ClassElementImpl) {
+      enclosing.accessors;
+      // Requesting accessors sets elements for accessors and fields.
+      assert(reference.element != null);
+      return reference.element;
+    }
+    if (enclosing is CompilationUnitElementImpl) {
+      enclosing.accessors;
+      // Requesting accessors sets elements for accessors and variables.
+      assert(reference.element != null);
+      return reference.element;
+    }
+    // Only classes and units have accessors.
+    throw StateError('${enclosing.runtimeType}');
+  }
+
+  void _indexUnitDeclarations(CompilationUnitElementImpl unit) {
+    var context = unit.linkedContext;
+    var unitRef = unit.reference;
+    var classRef = unitRef.getChild('@class');
+    var enumRef = unitRef.getChild('@class');
+    var functionRef = unitRef.getChild('@function');
+    var typeAliasRef = unitRef.getChild('@typeAlias');
+    var variableRef = unitRef.getChild('@variable');
+    for (var declaration in unit.linkedNode.compilationUnit_declarations) {
+      var kind = declaration.kind;
+      if (kind == LinkedNodeKind.classDeclaration ||
+          kind == LinkedNodeKind.classTypeAlias) {
+        var name = context.getUnitMemberName(declaration);
+        classRef.getChild(name).node = declaration;
+      } else if (kind == LinkedNodeKind.enumDeclaration) {
+        var name = context.getUnitMemberName(declaration);
+        enumRef.getChild(name).node = declaration;
+      } else if (kind == LinkedNodeKind.functionDeclaration) {
+        var name = context.getUnitMemberName(declaration);
+        functionRef.getChild(name).node = declaration;
+      } else if (kind == LinkedNodeKind.functionTypeAlias) {
+        var name = context.getUnitMemberName(declaration);
+        typeAliasRef.getChild(name).node = declaration;
+      } else if (kind == LinkedNodeKind.topLevelVariableDeclaration) {
+        var variables = declaration.topLevelVariableDeclaration_variableList;
+        for (var variable in variables.variableDeclarationList_variables) {
+          var name = context.getSimpleName(variable.variableDeclaration_name);
+          variableRef.getChild(name).node = variable;
+        }
+      } else {
+        throw UnimplementedError('$kind');
+      }
+    }
+  }
+
+  MethodElementImpl _method(ClassElementImpl enclosing, Reference reference) {
+    enclosing.methods;
+    // Requesting methods sets elements for all of them.
+    assert(reference.element != null);
+    return reference.element;
+  }
+
+  Element _parameter(ExecutableElementImpl enclosing, Reference reference) {
+    enclosing.parameters;
+    assert(reference.element != null);
+    return reference.element;
+  }
+
+  GenericTypeAliasElementImpl _typeAlias(
+      CompilationUnitElementImpl unit, Reference reference) {
+    if (reference.node == null) {
+      _indexUnitDeclarations(unit);
+      assert(reference.node != 0, '$reference');
+    }
+    return reference.element = GenericTypeAliasElementImpl.forLinkedNode(
+      unit,
+      reference,
+      reference.node,
+    );
+  }
+
+  Element _typeParameter(
+      TypeParameterizedElement enclosing, Reference reference) {
+    enclosing.typeParameters;
+    // Requesting type parameters sets elements for all their references.
+    assert(reference.element != null);
+    return reference.element;
+  }
+}
+
+class _Library {
+  final LinkedBundleContext context;
+  final LinkedNodeLibrary node;
+
+  _Library(this.context, this.node);
+}
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index f7869e1..b1bb1f4 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -2,16 +2,37 @@
 // 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 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/ast_binary_reader.dart';
 import 'package:analyzer/src/summary2/linked_bundle_context.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/tokens_context.dart';
 
 /// The context of a unit - the context of the bundle, and the unit tokens.
 class LinkedUnitContext {
   final LinkedBundleContext bundleContext;
-  final UnlinkedTokens tokens;
+  final TokensContext tokensContext;
 
-  LinkedUnitContext(this.bundleContext, this.tokens);
+  LinkedUnitContext(this.bundleContext, this.tokensContext);
+
+  Iterable<LinkedNode> classFields(LinkedNode class_) sync* {
+    for (var declaration in class_.classOrMixinDeclaration_members) {
+      if (declaration.kind == LinkedNodeKind.fieldDeclaration) {
+        var variableList = declaration.fieldDeclaration_fields;
+        for (var field in variableList.variableDeclarationList_variables) {
+          yield field;
+        }
+      }
+    }
+  }
+
+  String getCommentText(LinkedNode comment) {
+    if (comment == null) return null;
+
+    return comment.comment_tokens.map(getTokenLexeme).join('\n');
+  }
 
   String getConstructorDeclarationName(LinkedNode node) {
     var name = node.constructorDeclaration_name;
@@ -21,15 +42,343 @@
     return '';
   }
 
+  String getFormalParameterName(LinkedNode node) {
+    return getSimpleName(node.normalFormalParameter_identifier);
+  }
+
+  List<LinkedNode> getFormalParameters(LinkedNode node) {
+    LinkedNode parameterList;
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.constructorDeclaration) {
+      parameterList = node.constructorDeclaration_parameters;
+    } else if (kind == LinkedNodeKind.functionDeclaration) {
+      parameterList = node.functionDeclaration_functionExpression
+          .functionExpression_formalParameters;
+    } else if (kind == LinkedNodeKind.functionTypeAlias) {
+      parameterList = node.functionTypeAlias_formalParameters;
+    } else if (kind == LinkedNodeKind.methodDeclaration) {
+      parameterList = node.methodDeclaration_formalParameters;
+    } else {
+      throw UnimplementedError('$kind');
+    }
+    return parameterList?.formalParameterList_parameters;
+  }
+
+  LinkedNode getImplementsClause(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.classDeclaration) {
+      return node.classOrMixinDeclaration_implementsClause;
+    } else if (kind == LinkedNodeKind.classTypeAlias) {
+      return node.classTypeAlias_implementsClause;
+    } else {
+      throw UnimplementedError('$kind');
+    }
+  }
+
   InterfaceType getInterfaceType(LinkedNodeType linkedType) {
     return bundleContext.getInterfaceType(linkedType);
   }
 
+  List<LinkedNode> getMetadataOrEmpty(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.classDeclaration ||
+        kind == LinkedNodeKind.classTypeAlias ||
+        kind == LinkedNodeKind.constructorDeclaration ||
+        kind == LinkedNodeKind.enumConstantDeclaration ||
+        kind == LinkedNodeKind.enumDeclaration ||
+        kind == LinkedNodeKind.functionDeclaration ||
+        kind == LinkedNodeKind.functionTypeAlias ||
+        kind == LinkedNodeKind.methodDeclaration ||
+        kind == LinkedNodeKind.mixinDeclaration ||
+        kind == LinkedNodeKind.variableDeclaration) {
+      return node.annotatedNode_metadata;
+    }
+    if (kind == LinkedNodeKind.fieldFormalParameter ||
+        kind == LinkedNodeKind.functionTypedFormalParameter ||
+        kind == LinkedNodeKind.simpleFormalParameter) {
+      return node.normalFormalParameter_metadata;
+    }
+    return const <LinkedNode>[];
+  }
+
+  String getMethodName(LinkedNode node) {
+    return getSimpleName(node.methodDeclaration_name);
+  }
+
+  DartType getReturnType(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.functionDeclaration) {
+      return getType(node.functionDeclaration_returnType2);
+    } else if (kind == LinkedNodeKind.methodDeclaration) {
+      return getType(node.methodDeclaration_returnType2);
+    } else {
+      throw UnimplementedError('$kind');
+    }
+  }
+
   String getSimpleName(LinkedNode node) {
-    return tokens.lexeme[node.simpleIdentifier_token];
+    return getTokenLexeme(node.simpleIdentifier_token);
+  }
+
+  int getSimpleOffset(LinkedNode node) {
+    return tokensContext.offset(node.simpleIdentifier_token);
+  }
+
+  String getStringContent(LinkedNode node) {
+    return node.simpleStringLiteral_value;
+  }
+
+  String getTokenLexeme(int token) {
+    return tokensContext.lexeme(token);
+  }
+
+  DartType getType(LinkedNodeType linkedType) {
+    return bundleContext.getType(linkedType);
+  }
+
+  DartType getTypeAnnotationType(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.typeName) {
+      return getType(node.typeName_type);
+    } else {
+      throw UnimplementedError('$kind');
+    }
+  }
+
+  List<LinkedNode> getTypeParameters(LinkedNode node) {
+    LinkedNode typeParameterList;
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.classTypeAlias) {
+      typeParameterList = node.classTypeAlias_typeParameters;
+    } else if (kind == LinkedNodeKind.classDeclaration ||
+        kind == LinkedNodeKind.mixinDeclaration) {
+      typeParameterList = node.classOrMixinDeclaration_typeParameters;
+    } else if (kind == LinkedNodeKind.constructorDeclaration) {
+      return const [];
+    } else if (kind == LinkedNodeKind.functionDeclaration) {
+      return getTypeParameters(node.functionDeclaration_functionExpression);
+    } else if (kind == LinkedNodeKind.functionExpression) {
+      typeParameterList = node.functionExpression_typeParameters;
+    } else if (kind == LinkedNodeKind.functionTypeAlias) {
+      typeParameterList = node.functionTypeAlias_typeParameters;
+    } else if (kind == LinkedNodeKind.methodDeclaration) {
+      typeParameterList = node.methodDeclaration_typeParameters;
+    } else {
+      throw UnimplementedError('$kind');
+    }
+    return typeParameterList?.typeParameterList_typeParameters;
   }
 
   String getUnitMemberName(LinkedNode node) {
     return getSimpleName(node.namedCompilationUnitMember_name);
   }
+
+  String getVariableName(LinkedNode node) {
+    return getSimpleName(node.variableDeclaration_name);
+  }
+
+  bool isAbstract(LinkedNode node) {
+    return node.kind == LinkedNodeKind.methodDeclaration &&
+        node.methodDeclaration_body.kind == LinkedNodeKind.emptyFunctionBody;
+  }
+
+  bool isAsynchronous(LinkedNode node) {
+    LinkedNode body = _getFunctionBody(node);
+    if (body.kind == LinkedNodeKind.blockFunctionBody) {
+      return body.blockFunctionBody_keyword != 0;
+    } else if (body.kind == LinkedNodeKind.emptyFunctionBody) {
+      return false;
+    } else {
+      return body.expressionFunctionBody_keyword != 0;
+    }
+  }
+
+  bool isConst(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.variableDeclaration) {
+      return node.variableDeclaration_declaration.isConst;
+    }
+    throw UnimplementedError('$kind');
+  }
+
+  bool isConstKeyword(int token) {
+    return tokensContext.type(token) == UnlinkedTokenType.CONST;
+  }
+
+  bool isConstVariableList(LinkedNode node) {
+    return isConstKeyword(node.variableDeclarationList_keyword);
+  }
+
+  bool isExternal(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.constructorDeclaration) {
+      return node.constructorDeclaration_externalKeyword != 0;
+    } else if (kind == LinkedNodeKind.functionDeclaration) {
+      return node.functionDeclaration_externalKeyword != 0;
+    } else if (kind == LinkedNodeKind.methodDeclaration) {
+      return node.methodDeclaration_externalKeyword != 0;
+    } else {
+      throw UnimplementedError('$kind');
+    }
+  }
+
+  bool isFinal(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.enumConstantDeclaration) {
+      return false;
+    }
+    if (kind == LinkedNodeKind.variableDeclaration) {
+      return node.variableDeclaration_declaration.isFinal;
+    }
+    throw UnimplementedError('$kind');
+  }
+
+  bool isFinalKeyword(int token) {
+    return tokensContext.type(token) == UnlinkedTokenType.FINAL;
+  }
+
+  bool isFinalVariableList(LinkedNode node) {
+    return isFinalKeyword(node.variableDeclarationList_keyword);
+  }
+
+  bool isFunction(LinkedNode node) {
+    return node.kind == LinkedNodeKind.functionDeclaration;
+  }
+
+  bool isGenerator(LinkedNode node) {
+    LinkedNode body = _getFunctionBody(node);
+    if (body.kind == LinkedNodeKind.blockFunctionBody) {
+      return body.blockFunctionBody_star != 0;
+    }
+    return false;
+  }
+
+  bool isGetter(LinkedNode node) {
+    return isGetterMethod(node) || isGetterFunction(node);
+  }
+
+  bool isGetterFunction(LinkedNode node) {
+    return isFunction(node) &&
+        _isGetToken(node.functionDeclaration_propertyKeyword);
+  }
+
+  bool isGetterMethod(LinkedNode node) {
+    return isMethod(node) &&
+        _isGetToken(node.methodDeclaration_propertyKeyword);
+  }
+
+  bool isLibraryKeyword(int token) {
+    return tokensContext.type(token) == UnlinkedTokenType.LIBRARY;
+  }
+
+  bool isMethod(LinkedNode node) {
+    return node.kind == LinkedNodeKind.methodDeclaration;
+  }
+
+  bool isSetter(LinkedNode node) {
+    return isSetterMethod(node) || isSetterFunction(node);
+  }
+
+  bool isSetterFunction(LinkedNode node) {
+    return isFunction(node) &&
+        _isSetToken(node.functionDeclaration_propertyKeyword);
+  }
+
+  bool isSetterMethod(LinkedNode node) {
+    return isMethod(node) &&
+        _isSetToken(node.methodDeclaration_propertyKeyword);
+  }
+
+  bool isStatic(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.functionDeclaration) {
+      return true;
+    } else if (kind == LinkedNodeKind.methodDeclaration) {
+      return node.methodDeclaration_modifierKeyword != 0;
+    } else if (kind == LinkedNodeKind.variableDeclaration) {
+      return node.variableDeclaration_declaration.isStatic;
+    }
+    throw UnimplementedError('$kind');
+  }
+
+  void loadClassMemberReferences(Reference reference) {
+    var node = reference.node;
+    if (node.kind != LinkedNodeKind.classDeclaration &&
+        node.kind != LinkedNodeKind.mixinDeclaration) {
+      return;
+    }
+
+    var constructorContainerRef = reference.getChild('@constructor');
+    var fieldContainerRef = reference.getChild('@field');
+    var methodContainerRef = reference.getChild('@method');
+    var getterContainerRef = reference.getChild('@getter');
+    var setterContainerRef = reference.getChild('@setter');
+    for (var member in node.classOrMixinDeclaration_members) {
+      if (member.kind == LinkedNodeKind.constructorDeclaration) {
+        var name = getConstructorDeclarationName(member);
+        constructorContainerRef.getChild(name).node = member;
+      } else if (member.kind == LinkedNodeKind.fieldDeclaration) {
+        var variableList = member.fieldDeclaration_fields;
+        for (var field in variableList.variableDeclarationList_variables) {
+          var name = getSimpleName(field.variableDeclaration_name);
+          fieldContainerRef.getChild(name).node = field;
+        }
+      } else if (member.kind == LinkedNodeKind.methodDeclaration) {
+        var name = getSimpleName(member.methodDeclaration_name);
+        var propertyKeyword = member.methodDeclaration_propertyKeyword;
+        if (_isGetToken(propertyKeyword)) {
+          getterContainerRef.getChild(name).node = member;
+        } else if (_isSetToken(propertyKeyword)) {
+          setterContainerRef.getChild(name).node = member;
+        } else {
+          methodContainerRef.getChild(name).node = member;
+        }
+      }
+    }
+  }
+
+  Expression readInitializer(LinkedNode linkedNode) {
+    if (linkedNode.kind == LinkedNodeKind.defaultFormalParameter) {
+      return readNode(linkedNode.defaultFormalParameter_defaultValue);
+    }
+    return readNode(linkedNode.variableDeclaration_initializer);
+  }
+
+  AstNode readNode(LinkedNode linkedNode) {
+    var reader = AstBinaryReader(this);
+    return reader.readNode(linkedNode);
+  }
+
+  Iterable<LinkedNode> topLevelVariables(LinkedNode unit) sync* {
+    for (var declaration in unit.compilationUnit_declarations) {
+      if (declaration.kind == LinkedNodeKind.topLevelVariableDeclaration) {
+        var variableList = declaration.topLevelVariableDeclaration_variableList;
+        for (var variable in variableList.variableDeclarationList_variables) {
+          yield variable;
+        }
+      }
+    }
+  }
+
+  LinkedNode _getFunctionBody(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.constructorDeclaration) {
+      return node.constructorDeclaration_body;
+    } else if (kind == LinkedNodeKind.functionDeclaration) {
+      return node
+          .functionDeclaration_functionExpression.functionExpression_body;
+    } else if (kind == LinkedNodeKind.methodDeclaration) {
+      return node.methodDeclaration_body;
+    } else {
+      throw UnimplementedError('$kind');
+    }
+  }
+
+  bool _isGetToken(int token) {
+    return tokensContext.type(token) == UnlinkedTokenType.GET;
+  }
+
+  bool _isSetToken(int token) {
+    return tokensContext.type(token) == UnlinkedTokenType.SET;
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
new file mode 100644
index 0000000..50b9b92
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2019, 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 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+
+class LinkingBundleContext {
+  /// The `dynamic` class is declared in `dart:core`, but is not a class.
+  /// Also, it is static, so we cannot set `reference` for it.
+  /// So, we have to push it in a separate way.
+  final Reference dynamicReference;
+
+  /// References used in all libraries being linked.
+  /// Element references in nodes are indexes in this list.
+  final List<Reference> references = [null];
+
+  /// Data about [references].
+  final LinkedNodeReferencesBuilder referencesBuilder =
+      LinkedNodeReferencesBuilder(
+    parent: [0],
+    name: [''],
+  );
+
+  LinkingBundleContext(this.dynamicReference);
+
+  int indexOfReference(Reference reference) {
+    if (reference.parent == null) return 0;
+    if (reference.index != null) return reference.index;
+
+    var parentIndex = indexOfReference(reference.parent);
+    referencesBuilder.parent.add(parentIndex);
+    referencesBuilder.name.add(reference.name);
+
+    reference.index = references.length;
+    references.add(reference);
+    return reference.index;
+  }
+
+  LinkedNodeTypeBuilder writeType(DartType type) {
+    if (type == null) return null;
+
+    if (type.isBottom) {
+      return LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.bottom,
+      );
+    } else if (type.isDynamic) {
+      return LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.dynamic_,
+      );
+    } else if (type is FunctionType) {
+      return LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.function,
+        functionFormalParameters: _getReferences(type.parameters),
+        functionReturnType: writeType(type.returnType),
+        functionTypeParameters: _getReferences(type.typeParameters),
+      );
+    } else if (type is InterfaceType) {
+      return LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.interface,
+        interfaceClass: _getReferenceIndex(type.element),
+        interfaceTypeArguments: type.typeArguments.map(writeType).toList(),
+      );
+    } else if (type is TypeParameterType) {
+      return LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.typeParameter,
+        typeParameterParameter: _getReferenceIndex(type.element),
+      );
+    } else if (type is VoidType) {
+      return LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.void_,
+      );
+    } else {
+      throw UnimplementedError('(${type.runtimeType}) $type');
+    }
+  }
+
+  int _getReferenceIndex(Element element) {
+    if (element == null) return 0;
+
+    var reference = (element as ElementImpl).reference;
+    return indexOfReference(reference);
+  }
+
+  List<int> _getReferences(List<Element> elements) {
+    var result = List<int>(elements.length);
+    for (var i = 0; i < elements.length; ++i) {
+      var element = elements[i];
+      result[i] = _getReferenceIndex(element);
+    }
+    return result;
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/metadata_resolver.dart b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
new file mode 100644
index 0000000..2030086
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
@@ -0,0 +1,145 @@
+// Copyright (c) 2019, 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 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/standard_ast_factory.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/ast_binary_reader.dart';
+import 'package:analyzer/src/summary2/ast_resolver.dart';
+import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
+import 'package:analyzer/src/summary2/link.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+
+class MetadataResolver {
+  AstResolver _astResolver;
+
+  MetadataResolver(Linker linker, Reference libraryRef) {
+    _astResolver = AstResolver(linker, libraryRef);
+  }
+
+  void resolve(UnitBuilder unit) {
+    var unitDeclarations = unit.node.compilationUnit_declarations;
+    for (LinkedNodeBuilder unitDeclaration in unitDeclarations) {
+      var kind = unitDeclaration.kind;
+      if (_isAnnotatedNode(kind)) {
+        _annotatedNode(
+          unit,
+          unitDeclaration,
+        );
+      }
+      if (kind == LinkedNodeKind.classDeclaration) {
+        _class(unit, unitDeclaration);
+      } else if (kind == LinkedNodeKind.enumDeclaration) {
+        _enumDeclaration(unit, unitDeclaration);
+      } else if (kind == LinkedNodeKind.functionDeclaration) {
+        var function = unitDeclaration.functionDeclaration_functionExpression;
+        _formalParameterList(
+          unit,
+          function.functionExpression_formalParameters,
+        );
+      } else if (kind == LinkedNodeKind.topLevelVariableDeclaration) {
+        _variables(
+          unit,
+          unitDeclaration,
+          unitDeclaration.topLevelVariableDeclaration_variableList,
+        );
+      }
+    }
+  }
+
+  void _annotatedNode(UnitBuilder unit, LinkedNodeBuilder node) {
+    var unresolved = node.annotatedNode_metadata;
+    var resolved = _list(unit, unresolved);
+    node.annotatedNode_metadata = resolved;
+  }
+
+  void _class(UnitBuilder unit, LinkedNodeBuilder unitDeclaration) {
+    var members = unitDeclaration.classOrMixinDeclaration_members;
+    for (var classMember in members) {
+      var kind = classMember.kind;
+      if (_isAnnotatedNode(kind)) {
+        _annotatedNode(unit, classMember);
+      }
+      if (kind == LinkedNodeKind.fieldDeclaration) {
+        _variables(
+          unit,
+          classMember,
+          classMember.fieldDeclaration_fields,
+        );
+      } else if (kind == LinkedNodeKind.methodDeclaration) {
+        _formalParameterList(
+          unit,
+          classMember.methodDeclaration_formalParameters,
+        );
+      }
+    }
+  }
+
+  void _enumDeclaration(UnitBuilder unit, LinkedNodeBuilder node) {
+    for (var constant in node.enumDeclaration_constants) {
+      var kind = constant.kind;
+      if (kind == LinkedNodeKind.enumConstantDeclaration) {
+        _annotatedNode(unit, constant);
+      }
+    }
+  }
+
+  void _formalParameterList(UnitBuilder unit, LinkedNodeBuilder node) {
+    if (node == null) return;
+
+    for (var parameter in node.formalParameterList_parameters) {
+      if (parameter.kind == LinkedNodeKind.defaultFormalParameter) {
+        var actual = parameter.defaultFormalParameter_parameter;
+        var unresolved = actual.normalFormalParameter_metadata;
+        var resolved = _list(unit, unresolved);
+        actual.normalFormalParameter_metadata = resolved;
+      } else {
+        var unresolved = parameter.normalFormalParameter_metadata;
+        var resolved = _list(unit, unresolved);
+        parameter.normalFormalParameter_metadata = resolved;
+      }
+    }
+  }
+
+  List<LinkedNodeBuilder> _list(UnitBuilder unit, List<LinkedNode> unresolved) {
+    var resolved = List<LinkedNodeBuilder>(unresolved.length);
+    for (var i = 0; i < unresolved.length; ++i) {
+      var unresolvedNode = unresolved[i];
+
+      var reader = AstBinaryReader(unit.context);
+      var ast = reader.readNode(unresolvedNode) as Annotation;
+      ast.elementAnnotation = ElementAnnotationImpl(null);
+
+      // Set some parent, so that resolver does not bail out.
+      astFactory.libraryDirective(null, [ast], null, null, null);
+
+      var resolvedNode = _astResolver.resolve(unit, ast);
+      resolved[i] = resolvedNode;
+    }
+    return resolved;
+  }
+
+  /// Resolve annotations of the [declaration] (field or top-level variable),
+  /// and set them as metadata for each variable in the [variableList].
+  void _variables(UnitBuilder unit, LinkedNodeBuilder declaration,
+      LinkedNodeBuilder variableList) {
+    for (var variable in variableList.variableDeclarationList_variables) {
+      var unresolved = declaration.annotatedNode_metadata;
+      var resolved = _list(unit, unresolved);
+      variable.annotatedNode_metadata = resolved;
+    }
+  }
+
+  static bool _isAnnotatedNode(LinkedNodeKind kind) {
+    return kind == LinkedNodeKind.classDeclaration ||
+        kind == LinkedNodeKind.classTypeAlias ||
+        kind == LinkedNodeKind.constructorDeclaration ||
+        kind == LinkedNodeKind.enumDeclaration ||
+        kind == LinkedNodeKind.functionDeclaration ||
+        kind == LinkedNodeKind.functionTypeAlias ||
+        kind == LinkedNodeKind.methodDeclaration;
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/reference.dart b/pkg/analyzer/lib/src/summary2/reference.dart
index 6045db9..c89239d 100644
--- a/pkg/analyzer/lib/src/summary2/reference.dart
+++ b/pkg/analyzer/lib/src/summary2/reference.dart
@@ -48,6 +48,14 @@
 
   bool get isClass => parent != null && parent.name == '@class';
 
+  bool get isEnum => parent != null && parent.name == '@enum';
+
+  bool get isGenericTypeAlias => parent != null && parent.name == '@typeAlias';
+
+  bool get isTypeParameter => parent != null && parent.name == '@typeParameter';
+
+  int get numOfChildren => _children != null ? _children.length : 0;
+
   /// Return the child with the given name, or `null` if does not exist.
   Reference operator [](String name) {
     return _children != null ? _children[name] : null;
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
new file mode 100644
index 0000000..f044c1b
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -0,0 +1,463 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
+import 'package:analyzer/src/summary2/declaration.dart';
+import 'package:analyzer/src/summary2/linking_bundle_context.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/scope.dart';
+
+/// Recursive visitor of [LinkedNode]s that resolves explicit type annotations
+/// in outlines.  This includes resolving element references in identifiers
+/// in type annotation, and setting [LinkedNodeType]s for corresponding type
+/// annotation nodes.
+///
+/// Declarations that have type annotations, e.g. return types of methods, get
+/// the corresponding type set (so, if there is an explicit type annotation,
+/// the type is set, otherwise we keep it empty, so we will attempt to infer
+/// it later).
+class ReferenceResolver {
+  final LinkingBundleContext linkingBundleContext;
+  final UnitBuilder unit;
+
+  /// TODO(scheglov) Update scope with local scopes (formal / type parameters).
+  Scope scope;
+
+  Reference reference;
+
+  ReferenceResolver(
+    this.linkingBundleContext,
+    this.unit,
+    this.scope,
+    this.reference,
+  );
+
+  LinkedNodeTypeBuilder get _dynamicType {
+    return LinkedNodeTypeBuilder(
+      kind: LinkedNodeTypeKind.dynamic_,
+    );
+  }
+
+  void resolve() {
+    _node(unit.node);
+  }
+
+  void _classDeclaration(LinkedNodeBuilder node) {
+    var name = unit.context.getUnitMemberName(node);
+    reference = reference.getChild('@class').getChild(name);
+
+    var typeParameters = node.classOrMixinDeclaration_typeParameters;
+    _withTypeParameters(typeParameters, () {
+      var extendsClause = node.classDeclaration_extendsClause;
+      if (extendsClause != null) {
+        _typeName(extendsClause.extendsClause_superclass);
+      }
+
+      _nodeList(
+        node.classDeclaration_withClause?.withClause_mixinTypes,
+      );
+
+      _nodeList(
+        node.classOrMixinDeclaration_implementsClause
+            ?.implementsClause_interfaces,
+      );
+
+      for (var field in node.classOrMixinDeclaration_members) {
+        if (field.kind != LinkedNodeKind.constructorDeclaration) {
+          _node(field);
+        }
+      }
+      for (var field in node.classOrMixinDeclaration_members) {
+        if (field.kind == LinkedNodeKind.constructorDeclaration) {
+          _node(field);
+        }
+      }
+    });
+
+    reference = reference.parent.parent;
+  }
+
+  void _classTypeAlias(LinkedNodeBuilder node) {
+    var name = unit.context.getUnitMemberName(node);
+    reference = reference.getChild('@class').getChild(name);
+
+    var typeParameters = node.classTypeAlias_typeParameters;
+    _withTypeParameters(typeParameters, () {
+      var superclass = node.classTypeAlias_superclass;
+      if (superclass != null) {
+        _typeName(superclass);
+      }
+
+      _nodeList(
+        node.classTypeAlias_withClause?.withClause_mixinTypes,
+      );
+
+      _nodeList(
+        node.classTypeAlias_implementsClause?.implementsClause_interfaces,
+      );
+    });
+
+    reference = reference.parent.parent;
+  }
+
+  void _compilationUnit(LinkedNodeBuilder node) {
+    _nodeList(node.compilationUnit_directives);
+    _nodeList(node.compilationUnit_declarations);
+  }
+
+  void _constructorDeclaration(LinkedNodeBuilder node) {
+    _node(node.constructorDeclaration_parameters);
+  }
+
+  void _enumConstantDeclaration(LinkedNodeBuilder node) {}
+
+  void _enumDeclaration(LinkedNodeBuilder node) {
+    _nodeList(node.enumDeclaration_constants);
+  }
+
+  void _fieldDeclaration(LinkedNodeBuilder node) {
+    _node(node.fieldDeclaration_fields);
+  }
+
+  void _fieldFormalParameter(LinkedNodeBuilder node) {
+    var typeNode = node.fieldFormalParameter_type;
+    if (typeNode != null) {
+      _node(typeNode);
+      node.fieldFormalParameter_type2 = _getTypeAnnotationType(typeNode);
+    }
+
+    var formalParameters = node.fieldFormalParameter_formalParameters;
+    if (formalParameters != null) {
+      _node(formalParameters);
+      throw 'incomplete';
+    }
+  }
+
+  void _formalParameters(LinkedNodeBuilder node) {
+    for (var parameter in node.formalParameterList_parameters) {
+      _node(parameter);
+    }
+  }
+
+  void _functionDeclaration(LinkedNodeBuilder node) {
+    var name = unit.context.getUnitMemberName(node);
+    reference = reference.getChild('@function').getChild(name);
+
+    var function = node.functionDeclaration_functionExpression;
+    var typeParameters = function.functionExpression_typeParameters;
+    _withTypeParameters(typeParameters, () {
+      var returnType = node.functionDeclaration_returnType;
+      if (returnType != null) {
+        _node(returnType);
+        node.functionDeclaration_returnType2 =
+            _getTypeAnnotationType(returnType);
+      } else {
+        node.functionDeclaration_returnType2 = _dynamicType;
+      }
+
+      _node(function.functionExpression_formalParameters);
+    });
+
+    reference = reference.parent.parent;
+  }
+
+  void _functionExpression(LinkedNodeBuilder node) {
+    var typeParameters = node.functionExpression_typeParameters;
+    _withTypeParameters(typeParameters, () {
+      _node(node.functionExpression_formalParameters);
+    });
+  }
+
+  void _functionTypeAlias(LinkedNodeBuilder node) {
+    var name = unit.context.getUnitMemberName(node);
+    reference = reference.getChild('@typeAlias').getChild(name);
+
+    var typeParameters = node.functionTypeAlias_typeParameters;
+    _withTypeParameters(typeParameters, () {
+      var returnType = node.functionTypeAlias_returnType;
+      if (returnType != null) {
+        _node(returnType);
+        node.functionTypeAlias_returnType2 = _getTypeAnnotationType(returnType);
+      } else {
+        node.functionTypeAlias_returnType2 = _dynamicType;
+      }
+
+      _node(node.functionTypeAlias_formalParameters);
+    });
+
+    reference = reference.parent.parent;
+  }
+
+  void _genericFunctionType(LinkedNodeBuilder node) {
+    reference = reference.getChild('@function');
+
+    var name = '${reference.numOfChildren}';
+    reference = reference.getChild(name);
+
+    var typeParameters = node.genericFunctionType_typeParameters;
+    _withTypeParameters(typeParameters, () {
+      var returnType = node.genericFunctionType_returnType;
+      if (returnType != null) {
+        _node(returnType);
+        node.genericFunctionType_returnType2 =
+            _getTypeAnnotationType(returnType);
+      } else {
+        node.genericFunctionType_returnType2 = _dynamicType;
+      }
+
+      _node(node.genericFunctionType_formalParameters);
+    });
+
+    reference = reference.parent.parent;
+  }
+
+  void _genericTypeAlias(LinkedNodeBuilder node) {
+    var name = unit.context.getSimpleName(
+      node.namedCompilationUnitMember_name,
+    );
+    reference = reference.getChild('@typeAlias').getChild(name);
+
+    var typeParameters = node.genericTypeAlias_typeParameters;
+    _withTypeParameters(typeParameters, () {
+      _node(node.genericTypeAlias_functionType);
+    });
+
+    reference = reference.parent.parent;
+  }
+
+  LinkedNodeTypeBuilder _getTypeAnnotationType(LinkedNodeBuilder node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.typeName) {
+      return node.typeName_type;
+    } else {
+      throw UnimplementedError('$kind');
+    }
+  }
+
+  void _importDirective(LinkedNodeBuilder node) {}
+
+  void _libraryDirective(LinkedNodeBuilder node) {}
+
+  void _methodDeclaration(LinkedNodeBuilder node) {
+    var name = unit.context.getMethodName(node);
+    reference = reference.getChild('@method').getChild(name);
+
+    var typeParameters = node.methodDeclaration_typeParameters;
+    _withTypeParameters(typeParameters, () {
+      var returnType = node.methodDeclaration_returnType;
+      if (returnType != null) {
+        _node(returnType);
+        node.methodDeclaration_returnType2 = _getTypeAnnotationType(returnType);
+      }
+
+      _node(node.methodDeclaration_formalParameters);
+    });
+
+    reference = reference.parent.parent;
+  }
+
+  void _node(LinkedNodeBuilder node) {
+    if (node == null) return;
+
+    if (node.kind == LinkedNodeKind.classDeclaration) {
+      _classDeclaration(node);
+    } else if (node.kind == LinkedNodeKind.classTypeAlias) {
+      _classTypeAlias(node);
+    } else if (node.kind == LinkedNodeKind.compilationUnit) {
+      _compilationUnit(node);
+    } else if (node.kind == LinkedNodeKind.constructorDeclaration) {
+      _constructorDeclaration(node);
+    } else if (node.kind == LinkedNodeKind.defaultFormalParameter) {
+      _node(node.defaultFormalParameter_parameter);
+    } else if (node.kind == LinkedNodeKind.enumDeclaration) {
+      _enumDeclaration(node);
+    } else if (node.kind == LinkedNodeKind.enumConstantDeclaration) {
+      _enumConstantDeclaration(node);
+    } else if (node.kind == LinkedNodeKind.fieldDeclaration) {
+      _fieldDeclaration(node);
+    } else if (node.kind == LinkedNodeKind.fieldFormalParameter) {
+      _fieldFormalParameter(node);
+    } else if (node.kind == LinkedNodeKind.formalParameterList) {
+      _formalParameters(node);
+    } else if (node.kind == LinkedNodeKind.functionDeclaration) {
+      _functionDeclaration(node);
+    } else if (node.kind == LinkedNodeKind.functionExpression) {
+      _functionExpression(node);
+    } else if (node.kind == LinkedNodeKind.functionTypeAlias) {
+      _functionTypeAlias(node);
+    } else if (node.kind == LinkedNodeKind.genericFunctionType) {
+      _genericFunctionType(node);
+    } else if (node.kind == LinkedNodeKind.genericTypeAlias) {
+      _genericTypeAlias(node);
+    } else if (node.kind == LinkedNodeKind.importDirective) {
+      _importDirective(node);
+    } else if (node.kind == LinkedNodeKind.libraryDirective) {
+      _libraryDirective(node);
+    } else if (node.kind == LinkedNodeKind.methodDeclaration) {
+      _methodDeclaration(node);
+    } else if (node.kind == LinkedNodeKind.simpleFormalParameter) {
+      _simpleFormalParameter(node);
+    } else if (node.kind == LinkedNodeKind.topLevelVariableDeclaration) {
+      _topLevelVariableDeclaration(node);
+    } else if (node.kind == LinkedNodeKind.typeArgumentList) {
+      _typeArgumentList(node);
+    } else if (node.kind == LinkedNodeKind.typeName) {
+      _typeName(node);
+    } else if (node.kind == LinkedNodeKind.typeParameter) {
+      _typeParameter(node);
+    } else if (node.kind == LinkedNodeKind.typeParameterList) {
+      _typeParameterList(node);
+    } else if (node.kind == LinkedNodeKind.variableDeclarationList) {
+      _variableDeclarationList(node);
+    } else {
+      // TODO(scheglov) implement
+      throw UnimplementedError('${node.kind}');
+    }
+  }
+
+  void _nodeList(List<LinkedNode> nodeList) {
+    if (nodeList == null) return;
+
+    for (var i = 0; i < nodeList.length; ++i) {
+      var node = nodeList[i];
+      _node(node);
+    }
+  }
+
+  void _simpleFormalParameter(LinkedNodeBuilder node) {
+    var typeNode = node.simpleFormalParameter_type;
+    if (typeNode != null) {
+      _node(typeNode);
+      node.simpleFormalParameter_type2 = _getTypeAnnotationType(typeNode);
+    } else {
+      // TODO(scheglov) might be inferred
+      node.simpleFormalParameter_type2 = _dynamicType;
+    }
+
+    if (node.normalFormalParameter_covariantKeyword != 0) {
+      node.normalFormalParameter_isCovariant = true;
+    } else {
+      // TODO(scheglov) might be inferred
+    }
+  }
+
+  void _topLevelVariableDeclaration(LinkedNodeBuilder node) {
+    _node(node.topLevelVariableDeclaration_variableList);
+  }
+
+  void _typeArgumentList(LinkedNodeBuilder node) {
+    for (var typeArgument in node.typeArgumentList_arguments) {
+      _typeName(typeArgument);
+    }
+  }
+
+  void _typeName(LinkedNodeBuilder node) {
+    if (node == null) return;
+
+    var identifier = node.typeName_name;
+    if (identifier.kind == LinkedNodeKind.simpleIdentifier) {
+      var name = unit.context.getSimpleName(identifier);
+
+      if (name == 'void') {
+        node.typeName_type = LinkedNodeTypeBuilder(
+          kind: LinkedNodeTypeKind.void_,
+        );
+        return;
+      }
+
+      var declaration = scope.lookup(name);
+      if (declaration == null) {
+        identifier.simpleIdentifier_element = 0;
+        node.typeName_type = _dynamicType;
+        return;
+      }
+
+      var reference = declaration.reference;
+      var referenceIndex = linkingBundleContext.indexOfReference(reference);
+      identifier.simpleIdentifier_element = referenceIndex;
+
+      var typeArguments = const <LinkedNodeTypeBuilder>[];
+      var typeArgumentList = node.typeName_typeArguments;
+      if (typeArgumentList != null) {
+        _node(typeArgumentList);
+        typeArguments = typeArgumentList.typeArgumentList_arguments
+            .map((node) => _getTypeAnnotationType(node))
+            .toList();
+      }
+
+      if (reference.isClass) {
+        node.typeName_type = LinkedNodeTypeBuilder(
+          kind: LinkedNodeTypeKind.interface,
+          interfaceClass: referenceIndex,
+          interfaceTypeArguments: typeArguments,
+        );
+      } else if (reference.isEnum) {
+        node.typeName_type = LinkedNodeTypeBuilder(
+          kind: LinkedNodeTypeKind.interface,
+          interfaceClass: referenceIndex,
+        );
+      } else if (reference.isTypeParameter) {
+        node.typeName_type = LinkedNodeTypeBuilder(
+          kind: LinkedNodeTypeKind.typeParameter,
+          typeParameterParameter: referenceIndex,
+        );
+      } else {
+        // TODO(scheglov) set Object? keep unresolved?
+        throw UnimplementedError();
+      }
+    } else {
+      // TODO(scheglov) implement
+      throw UnimplementedError();
+    }
+  }
+
+  void _typeParameter(LinkedNodeBuilder node) {
+    _node(node.typeParameter_bound);
+    // TODO(scheglov) set Object bound if no explicit?
+  }
+
+  void _typeParameterList(LinkedNodeBuilder node) {
+    for (var typeParameter in node.typeParameterList_typeParameters) {
+      _node(typeParameter);
+    }
+  }
+
+  void _variableDeclarationList(LinkedNodeBuilder node) {
+    var typeNode = node.variableDeclarationList_type;
+    if (typeNode != null) {
+      _node(typeNode);
+      for (var field in node.variableDeclarationList_variables) {
+        field.variableDeclaration_type2 = _getTypeAnnotationType(typeNode);
+      }
+    }
+  }
+
+  /// Enter the type parameters scope, visit them, and run [f].
+  void _withTypeParameters(LinkedNode typeParameterList, void f()) {
+    if (typeParameterList == null) {
+      f();
+      return;
+    }
+
+    scope = Scope(this.scope, {});
+
+    var containerRef = this.reference.getChild('@typeParameter');
+    var typeParameters = typeParameterList.typeParameterList_typeParameters;
+    for (var typeParameter in typeParameters) {
+      var name = unit.context.getSimpleName(typeParameter.typeParameter_name);
+      var reference = containerRef.getChild(name);
+      reference.node = typeParameter;
+      scope.declare(name, Declaration(name, reference));
+    }
+
+    _node(typeParameterList);
+    f();
+
+    if (typeParameterList != null) {
+      scope = scope.parent;
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/scope.dart b/pkg/analyzer/lib/src/summary2/scope.dart
index 6917dea..30f7419 100644
--- a/pkg/analyzer/lib/src/summary2/scope.dart
+++ b/pkg/analyzer/lib/src/summary2/scope.dart
@@ -21,6 +21,10 @@
   }
 
   Declaration lookup(String name) {
-    return map[name];
+    var declaration = map[name];
+    if (declaration != null) return declaration;
+
+    if (parent == null) return null;
+    return parent.lookup(name);
   }
 }
diff --git a/pkg/analyzer/lib/src/summary2/tokens_context.dart b/pkg/analyzer/lib/src/summary2/tokens_context.dart
new file mode 100644
index 0000000..36b9d5a
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/tokens_context.dart
@@ -0,0 +1,395 @@
+// Copyright (c) 2019, 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 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/tokens_writer.dart';
+
+/// The context for reading or writing tokens.
+///
+/// Tokens cannot be compared, so tokens for [indexOfToken] must be previously
+/// received from [tokenOfIndex], or the context must be created from a
+/// [TokensResult] (the result of writing previously parsed tokens).
+class TokensContext {
+  final UnlinkedTokens _tokens;
+  final List<Token> _indexToToken;
+  final Map<Token, int> _tokenToIndex;
+
+  TokensContext(this._tokens)
+      : _indexToToken = List<Token>(_tokens.type.length),
+        _tokenToIndex = Map.identity();
+
+  TokensContext.fromResult(
+      this._tokens, this._indexToToken, this._tokenToIndex);
+
+  /// TODO(scheglov) Not used yet, maybe remove.
+  int addSyntheticToken(
+      UnlinkedTokenKind kind, UnlinkedTokenType type, String lexeme) {
+    var index = _tokens.kind.length;
+    UnlinkedTokensBuilder tokens = _tokens;
+    tokens.kind.add(kind);
+    tokens.lexeme.add(lexeme);
+    tokens.offset.add(0);
+    tokens.length.add(0);
+    tokens.type.add(type);
+    tokens.next.add(0);
+    tokens.endGroup.add(0);
+    tokens.precedingComment.add(0);
+    tokens.isSynthetic.add(true);
+    return index;
+  }
+
+  int indexOfToken(Token token) {
+    if (token == null) return 0;
+
+    var index = _tokenToIndex[token];
+    if (index == null) {
+      throw StateError('Unexpected token: $token');
+    }
+    return index;
+  }
+
+  String lexeme(int index) {
+    return _tokens.lexeme[index];
+  }
+
+  int offset(int index) {
+    return _tokens.offset[index];
+  }
+
+  Token tokenOfIndex(int index) {
+    if (index == 0) return null;
+
+    var token = _indexToToken[index];
+    if (token == null) {
+      var kind = _tokens.kind[index];
+      switch (kind) {
+        case UnlinkedTokenKind.nothing:
+          return null;
+        case UnlinkedTokenKind.comment:
+          return CommentToken(
+            _binaryToAstTokenType(_tokens.type[index]),
+            _tokens.lexeme[index],
+            _tokens.offset[index],
+          );
+        case UnlinkedTokenKind.keyword:
+          return KeywordToken(
+            _binaryToAstTokenType(_tokens.type[index]),
+            _tokens.offset[index],
+            _getCommentToken(_tokens.precedingComment[index]),
+          );
+        case UnlinkedTokenKind.simple:
+          return SimpleToken(
+            _binaryToAstTokenType(_tokens.type[index]),
+            _tokens.offset[index],
+            _getCommentToken(_tokens.precedingComment[index]),
+          );
+        case UnlinkedTokenKind.string:
+          return StringToken(
+            _binaryToAstTokenType(_tokens.type[index]),
+            _tokens.lexeme[index],
+            _tokens.offset[index],
+            _getCommentToken(_tokens.precedingComment[index]),
+          );
+        default:
+          throw UnimplementedError('Token kind: $kind');
+      }
+    }
+    return token;
+  }
+
+  UnlinkedTokenType type(int index) {
+    return _tokens.type[index];
+  }
+
+  CommentToken _getCommentToken(int index) {
+    var result = tokenOfIndex(index);
+    var token = result;
+    while (true) {
+      index = _tokens.next[index];
+      if (index == 0) return result;
+
+      var nextToken = tokenOfIndex(index);
+      token.next = nextToken;
+      token = nextToken;
+    }
+  }
+
+  static TokenType _binaryToAstTokenType(UnlinkedTokenType type) {
+    switch (type) {
+      case UnlinkedTokenType.ABSTRACT:
+        return Keyword.ABSTRACT;
+      case UnlinkedTokenType.AMPERSAND:
+        return TokenType.AMPERSAND;
+      case UnlinkedTokenType.AMPERSAND_AMPERSAND:
+        return TokenType.AMPERSAND_AMPERSAND;
+      case UnlinkedTokenType.AMPERSAND_EQ:
+        return TokenType.AMPERSAND_EQ;
+      case UnlinkedTokenType.AS:
+        return TokenType.AS;
+      case UnlinkedTokenType.ASSERT:
+        return Keyword.ASSERT;
+      case UnlinkedTokenType.ASYNC:
+        return Keyword.ASYNC;
+      case UnlinkedTokenType.AT:
+        return TokenType.AT;
+      case UnlinkedTokenType.AWAIT:
+        return Keyword.AWAIT;
+      case UnlinkedTokenType.BACKPING:
+        return TokenType.BACKPING;
+      case UnlinkedTokenType.BACKSLASH:
+        return TokenType.BACKSLASH;
+      case UnlinkedTokenType.BANG:
+        return TokenType.BANG;
+      case UnlinkedTokenType.BANG_EQ:
+        return TokenType.BANG_EQ;
+      case UnlinkedTokenType.BAR:
+        return TokenType.BAR;
+      case UnlinkedTokenType.BAR_BAR:
+        return TokenType.BAR_BAR;
+      case UnlinkedTokenType.BAR_EQ:
+        return TokenType.BAR_EQ;
+      case UnlinkedTokenType.BREAK:
+        return Keyword.BREAK;
+      case UnlinkedTokenType.CARET:
+        return TokenType.CARET;
+      case UnlinkedTokenType.CARET_EQ:
+        return TokenType.CARET_EQ;
+      case UnlinkedTokenType.CASE:
+        return Keyword.CASE;
+      case UnlinkedTokenType.CATCH:
+        return Keyword.CATCH;
+      case UnlinkedTokenType.CLASS:
+        return Keyword.CLASS;
+      case UnlinkedTokenType.CLOSE_CURLY_BRACKET:
+        return TokenType.CLOSE_CURLY_BRACKET;
+      case UnlinkedTokenType.CLOSE_PAREN:
+        return TokenType.CLOSE_PAREN;
+      case UnlinkedTokenType.CLOSE_SQUARE_BRACKET:
+        return TokenType.CLOSE_SQUARE_BRACKET;
+      case UnlinkedTokenType.COLON:
+        return TokenType.COLON;
+      case UnlinkedTokenType.COMMA:
+        return TokenType.COMMA;
+      case UnlinkedTokenType.CONST:
+        return Keyword.CONST;
+      case UnlinkedTokenType.CONTINUE:
+        return Keyword.CONTINUE;
+      case UnlinkedTokenType.COVARIANT:
+        return Keyword.COVARIANT;
+      case UnlinkedTokenType.DEFAULT:
+        return Keyword.DEFAULT;
+      case UnlinkedTokenType.DEFERRED:
+        return Keyword.DEFERRED;
+      case UnlinkedTokenType.DO:
+        return Keyword.DO;
+      case UnlinkedTokenType.DOUBLE:
+        return TokenType.DOUBLE;
+      case UnlinkedTokenType.DYNAMIC:
+        return Keyword.DYNAMIC;
+      case UnlinkedTokenType.ELSE:
+        return Keyword.ELSE;
+      case UnlinkedTokenType.ENUM:
+        return Keyword.ENUM;
+      case UnlinkedTokenType.EOF:
+        return TokenType.EOF;
+      case UnlinkedTokenType.EQ:
+        return TokenType.EQ;
+      case UnlinkedTokenType.EQ_EQ:
+        return TokenType.EQ_EQ;
+      case UnlinkedTokenType.EXPORT:
+        return Keyword.EXPORT;
+      case UnlinkedTokenType.EXTENDS:
+        return Keyword.EXTENDS;
+      case UnlinkedTokenType.EXTERNAL:
+        return Keyword.EXTERNAL;
+      case UnlinkedTokenType.FACTORY:
+        return Keyword.FACTORY;
+      case UnlinkedTokenType.FALSE:
+        return Keyword.FALSE;
+      case UnlinkedTokenType.FINAL:
+        return Keyword.FINAL;
+      case UnlinkedTokenType.FINALLY:
+        return Keyword.FINALLY;
+      case UnlinkedTokenType.FOR:
+        return Keyword.FOR;
+      case UnlinkedTokenType.FUNCTION:
+        return TokenType.FUNCTION;
+      case UnlinkedTokenType.FUNCTION_KEYWORD:
+        return Keyword.FUNCTION;
+      case UnlinkedTokenType.GET:
+        return Keyword.GET;
+      case UnlinkedTokenType.GT:
+        return TokenType.GT;
+      case UnlinkedTokenType.GT_EQ:
+        return TokenType.GT_EQ;
+      case UnlinkedTokenType.GT_GT:
+        return TokenType.GT_GT;
+      case UnlinkedTokenType.GT_GT_EQ:
+        return TokenType.GT_GT_EQ;
+      case UnlinkedTokenType.HASH:
+        return TokenType.HASH;
+      case UnlinkedTokenType.HEXADECIMAL:
+        return TokenType.HEXADECIMAL;
+      case UnlinkedTokenType.HIDE:
+        return Keyword.HIDE;
+      case UnlinkedTokenType.IDENTIFIER:
+        return TokenType.IDENTIFIER;
+      case UnlinkedTokenType.IF:
+        return Keyword.IF;
+      case UnlinkedTokenType.IMPLEMENTS:
+        return Keyword.IMPLEMENTS;
+      case UnlinkedTokenType.IMPORT:
+        return Keyword.IMPORT;
+      case UnlinkedTokenType.IN:
+        return Keyword.IN;
+      case UnlinkedTokenType.INDEX:
+        return TokenType.INDEX;
+      case UnlinkedTokenType.INDEX_EQ:
+        return TokenType.INDEX_EQ;
+      case UnlinkedTokenType.INT:
+        return TokenType.INT;
+      case UnlinkedTokenType.INTERFACE:
+        return Keyword.INTERFACE;
+      case UnlinkedTokenType.IS:
+        return TokenType.IS;
+      case UnlinkedTokenType.LIBRARY:
+        return Keyword.LIBRARY;
+      case UnlinkedTokenType.LT:
+        return TokenType.LT;
+      case UnlinkedTokenType.LT_EQ:
+        return TokenType.LT_EQ;
+      case UnlinkedTokenType.LT_LT:
+        return TokenType.LT_LT;
+      case UnlinkedTokenType.LT_LT_EQ:
+        return TokenType.LT_LT_EQ;
+      case UnlinkedTokenType.MINUS:
+        return TokenType.MINUS;
+      case UnlinkedTokenType.MINUS_EQ:
+        return TokenType.MINUS_EQ;
+      case UnlinkedTokenType.MINUS_MINUS:
+        return TokenType.MINUS_MINUS;
+      case UnlinkedTokenType.MIXIN:
+        return Keyword.MIXIN;
+      case UnlinkedTokenType.MULTI_LINE_COMMENT:
+        return TokenType.MULTI_LINE_COMMENT;
+      case UnlinkedTokenType.NATIVE:
+        return Keyword.NATIVE;
+      case UnlinkedTokenType.NEW:
+        return Keyword.NEW;
+      case UnlinkedTokenType.NULL:
+        return Keyword.NULL;
+      case UnlinkedTokenType.OF:
+        return Keyword.OF;
+      case UnlinkedTokenType.ON:
+        return Keyword.ON;
+      case UnlinkedTokenType.OPEN_CURLY_BRACKET:
+        return TokenType.OPEN_CURLY_BRACKET;
+      case UnlinkedTokenType.OPEN_PAREN:
+        return TokenType.OPEN_PAREN;
+      case UnlinkedTokenType.OPEN_SQUARE_BRACKET:
+        return TokenType.OPEN_SQUARE_BRACKET;
+      case UnlinkedTokenType.OPERATOR:
+        return Keyword.OPERATOR;
+      case UnlinkedTokenType.PART:
+        return Keyword.PART;
+      case UnlinkedTokenType.PATCH:
+        return Keyword.PATCH;
+      case UnlinkedTokenType.PERCENT:
+        return TokenType.PERCENT;
+      case UnlinkedTokenType.PERCENT_EQ:
+        return TokenType.PERCENT_EQ;
+      case UnlinkedTokenType.PERIOD:
+        return TokenType.PERIOD;
+      case UnlinkedTokenType.PERIOD_PERIOD:
+        return TokenType.PERIOD_PERIOD;
+      case UnlinkedTokenType.PERIOD_PERIOD_PERIOD:
+        return TokenType.PERIOD_PERIOD_PERIOD;
+      case UnlinkedTokenType.PERIOD_PERIOD_PERIOD_QUESTION:
+        return TokenType.PERIOD_PERIOD_PERIOD_QUESTION;
+      case UnlinkedTokenType.PLUS:
+        return TokenType.PLUS;
+      case UnlinkedTokenType.PLUS_EQ:
+        return TokenType.PLUS_EQ;
+      case UnlinkedTokenType.PLUS_PLUS:
+        return TokenType.PLUS_PLUS;
+      case UnlinkedTokenType.QUESTION:
+        return TokenType.QUESTION;
+      case UnlinkedTokenType.QUESTION_PERIOD:
+        return TokenType.QUESTION_PERIOD;
+      case UnlinkedTokenType.QUESTION_QUESTION:
+        return TokenType.QUESTION_QUESTION;
+      case UnlinkedTokenType.QUESTION_QUESTION_EQ:
+        return TokenType.QUESTION_QUESTION_EQ;
+      case UnlinkedTokenType.RETHROW:
+        return Keyword.RETHROW;
+      case UnlinkedTokenType.RETURN:
+        return Keyword.RETURN;
+      case UnlinkedTokenType.SCRIPT_TAG:
+        return TokenType.SCRIPT_TAG;
+      case UnlinkedTokenType.SEMICOLON:
+        return TokenType.SEMICOLON;
+      case UnlinkedTokenType.SET:
+        return Keyword.SET;
+      case UnlinkedTokenType.SHOW:
+        return Keyword.SHOW;
+      case UnlinkedTokenType.SINGLE_LINE_COMMENT:
+        return TokenType.SINGLE_LINE_COMMENT;
+      case UnlinkedTokenType.SLASH:
+        return TokenType.SLASH;
+      case UnlinkedTokenType.SLASH_EQ:
+        return TokenType.SLASH_EQ;
+      case UnlinkedTokenType.SOURCE:
+        return Keyword.SOURCE;
+      case UnlinkedTokenType.STAR:
+        return TokenType.STAR;
+      case UnlinkedTokenType.STAR_EQ:
+        return TokenType.STAR_EQ;
+      case UnlinkedTokenType.STATIC:
+        return Keyword.STATIC;
+      case UnlinkedTokenType.STRING:
+        return TokenType.STRING;
+      case UnlinkedTokenType.STRING_INTERPOLATION_EXPRESSION:
+        return TokenType.STRING_INTERPOLATION_EXPRESSION;
+      case UnlinkedTokenType.STRING_INTERPOLATION_IDENTIFIER:
+        return TokenType.STRING_INTERPOLATION_IDENTIFIER;
+      case UnlinkedTokenType.SUPER:
+        return Keyword.SUPER;
+      case UnlinkedTokenType.SWITCH:
+        return Keyword.SWITCH;
+      case UnlinkedTokenType.SYNC:
+        return Keyword.SYNC;
+      case UnlinkedTokenType.THIS:
+        return Keyword.THIS;
+      case UnlinkedTokenType.THROW:
+        return Keyword.THROW;
+      case UnlinkedTokenType.TILDE:
+        return TokenType.TILDE;
+      case UnlinkedTokenType.TILDE_SLASH:
+        return TokenType.TILDE_SLASH;
+      case UnlinkedTokenType.TILDE_SLASH_EQ:
+        return TokenType.TILDE_SLASH_EQ;
+      case UnlinkedTokenType.TRUE:
+        return Keyword.TRUE;
+      case UnlinkedTokenType.TRY:
+        return Keyword.TRY;
+      case UnlinkedTokenType.TYPEDEF:
+        return Keyword.TYPEDEF;
+      case UnlinkedTokenType.VAR:
+        return Keyword.VAR;
+      case UnlinkedTokenType.VOID:
+        return Keyword.VOID;
+      case UnlinkedTokenType.WHILE:
+        return Keyword.WHILE;
+      case UnlinkedTokenType.WITH:
+        return Keyword.WITH;
+      case UnlinkedTokenType.YIELD:
+        return Keyword.YIELD;
+      default:
+        throw StateError('Unexpected type: $type');
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/tokens_writer.dart b/pkg/analyzer/lib/src/summary2/tokens_writer.dart
new file mode 100644
index 0000000..3a9e989
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/tokens_writer.dart
@@ -0,0 +1,445 @@
+// Copyright (c) 2019, 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 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/tokens_context.dart';
+import 'package:meta/meta.dart';
+
+/// The result of writing a sequence of tokens.
+class TokensResult {
+  final UnlinkedTokensBuilder tokens;
+  final List<Token> _indexToToken;
+  final Map<Token, int> _tokenToIndex;
+
+  TokensResult(this.tokens, this._indexToToken, this._tokenToIndex);
+
+  TokensContext toContext() {
+    return TokensContext.fromResult(tokens, _indexToToken, _tokenToIndex);
+  }
+}
+
+class TokensWriter {
+  final UnlinkedTokensBuilder _tokens = UnlinkedTokensBuilder();
+  final List<Token> _indexToToken = [];
+  final Map<Token, int> _tokenToIndex = Map.identity();
+
+  TokensWriter() {
+    _addToken(
+      null,
+      isSynthetic: true,
+      kind: UnlinkedTokenKind.nothing,
+      length: 0,
+      lexeme: '',
+      offset: 0,
+      precedingComment: 0,
+      type: UnlinkedTokenType.NOTHING,
+    );
+  }
+
+  /// Write all the tokens from the [first] to the [last] inclusively.
+  TokensResult writeTokens(Token first, Token last) {
+    if (first is CommentToken) {
+      first = (first as CommentToken).parent;
+    }
+
+    var endGroupToBeginIndexMap = <Token, int>{};
+    var previousIndex = 0;
+    for (var token = first;; token = token.next) {
+      var index = _writeToken(token);
+
+      if (previousIndex != 0) {
+        _tokens.next[previousIndex] = index;
+      }
+      previousIndex = index;
+
+      if (token.endGroup != null) {
+        endGroupToBeginIndexMap[token.endGroup] = index;
+      }
+
+      var beginIndex = endGroupToBeginIndexMap[token];
+      if (beginIndex != null) {
+        _tokens.endGroup[beginIndex] = index;
+      }
+
+      if (token == last) break;
+    }
+
+    return TokensResult(_tokens, _indexToToken, _tokenToIndex);
+  }
+
+  int _addToken(
+    Token token, {
+    @required bool isSynthetic,
+    @required UnlinkedTokenKind kind,
+    @required int length,
+    @required String lexeme,
+    @required int offset,
+    @required int precedingComment,
+    @required UnlinkedTokenType type,
+  }) {
+    _tokens.endGroup.add(0);
+    _tokens.isSynthetic.add(isSynthetic);
+    _tokens.kind.add(kind);
+    _tokens.length.add(length);
+    _tokens.lexeme.add(lexeme);
+    _tokens.next.add(0);
+    _tokens.offset.add(offset);
+    _tokens.precedingComment.add(precedingComment);
+    _tokens.type.add(type);
+
+    var index = _indexToToken.length;
+    _indexToToken.add(token);
+    _tokenToIndex[token] = index;
+    return index;
+  }
+
+  int _writeCommentToken(CommentToken token) {
+    if (token == null) return 0;
+
+    int firstIndex = null;
+    var previousIndex = 0;
+    while (token != null) {
+      var index = _addToken(
+        token,
+        isSynthetic: false,
+        kind: UnlinkedTokenKind.comment,
+        length: token.length,
+        lexeme: token.lexeme,
+        offset: token.offset,
+        precedingComment: 0,
+        type: _astToBinaryTokenType(token.type),
+      );
+      firstIndex ??= index;
+
+      if (previousIndex != 0) {
+        _tokens.next[previousIndex] = index;
+      }
+      previousIndex = index;
+
+      token = token.next;
+    }
+
+    return firstIndex;
+  }
+
+  int _writeToken(Token token) {
+    assert(_tokenToIndex[token] == null);
+
+    var commentIndex = _writeCommentToken(token.precedingComments);
+
+    if (token is KeywordToken) {
+      return _addToken(
+        token,
+        isSynthetic: token.isSynthetic,
+        kind: UnlinkedTokenKind.keyword,
+        lexeme: token.lexeme,
+        offset: token.offset,
+        length: token.length,
+        precedingComment: commentIndex,
+        type: _astToBinaryTokenType(token.type),
+      );
+    } else if (token is StringToken) {
+      return _addToken(
+        token,
+        isSynthetic: token.isSynthetic,
+        kind: UnlinkedTokenKind.string,
+        lexeme: token.lexeme,
+        offset: token.offset,
+        length: token.length,
+        precedingComment: commentIndex,
+        type: _astToBinaryTokenType(token.type),
+      );
+    } else if (token is SimpleToken) {
+      return _addToken(
+        token,
+        isSynthetic: token.isSynthetic,
+        kind: UnlinkedTokenKind.simple,
+        lexeme: token.lexeme,
+        offset: token.offset,
+        length: token.length,
+        precedingComment: commentIndex,
+        type: _astToBinaryTokenType(token.type),
+      );
+    } else {
+      throw UnimplementedError('(${token.runtimeType}) $token');
+    }
+  }
+
+  static UnlinkedTokenType _astToBinaryTokenType(TokenType type) {
+    if (type == Keyword.ABSTRACT) {
+      return UnlinkedTokenType.ABSTRACT;
+    } else if (type == TokenType.AMPERSAND) {
+      return UnlinkedTokenType.AMPERSAND;
+    } else if (type == TokenType.AMPERSAND_AMPERSAND) {
+      return UnlinkedTokenType.AMPERSAND_AMPERSAND;
+    } else if (type == TokenType.AMPERSAND_EQ) {
+      return UnlinkedTokenType.AMPERSAND_EQ;
+    } else if (type == TokenType.AS) {
+      return UnlinkedTokenType.AS;
+    } else if (type == Keyword.ASSERT) {
+      return UnlinkedTokenType.ASSERT;
+    } else if (type == Keyword.ASYNC) {
+      return UnlinkedTokenType.ASYNC;
+    } else if (type == TokenType.AT) {
+      return UnlinkedTokenType.AT;
+    } else if (type == Keyword.AWAIT) {
+      return UnlinkedTokenType.AWAIT;
+    } else if (type == TokenType.BACKPING) {
+      return UnlinkedTokenType.BACKPING;
+    } else if (type == TokenType.BACKSLASH) {
+      return UnlinkedTokenType.BACKSLASH;
+    } else if (type == TokenType.BANG) {
+      return UnlinkedTokenType.BANG;
+    } else if (type == TokenType.BANG_EQ) {
+      return UnlinkedTokenType.BANG_EQ;
+    } else if (type == TokenType.BAR) {
+      return UnlinkedTokenType.BAR;
+    } else if (type == TokenType.BAR_BAR) {
+      return UnlinkedTokenType.BAR_BAR;
+    } else if (type == TokenType.BAR_EQ) {
+      return UnlinkedTokenType.BAR_EQ;
+    } else if (type == Keyword.BREAK) {
+      return UnlinkedTokenType.BREAK;
+    } else if (type == TokenType.CARET) {
+      return UnlinkedTokenType.CARET;
+    } else if (type == TokenType.CARET_EQ) {
+      return UnlinkedTokenType.CARET_EQ;
+    } else if (type == Keyword.CASE) {
+      return UnlinkedTokenType.CASE;
+    } else if (type == Keyword.CATCH) {
+      return UnlinkedTokenType.CATCH;
+    } else if (type == Keyword.CLASS) {
+      return UnlinkedTokenType.CLASS;
+    } else if (type == TokenType.CLOSE_CURLY_BRACKET) {
+      return UnlinkedTokenType.CLOSE_CURLY_BRACKET;
+    } else if (type == TokenType.CLOSE_PAREN) {
+      return UnlinkedTokenType.CLOSE_PAREN;
+    } else if (type == TokenType.CLOSE_SQUARE_BRACKET) {
+      return UnlinkedTokenType.CLOSE_SQUARE_BRACKET;
+    } else if (type == TokenType.COLON) {
+      return UnlinkedTokenType.COLON;
+    } else if (type == TokenType.COMMA) {
+      return UnlinkedTokenType.COMMA;
+    } else if (type == Keyword.CONST) {
+      return UnlinkedTokenType.CONST;
+    } else if (type == Keyword.CONTINUE) {
+      return UnlinkedTokenType.CONTINUE;
+    } else if (type == Keyword.COVARIANT) {
+      return UnlinkedTokenType.COVARIANT;
+    } else if (type == Keyword.DEFAULT) {
+      return UnlinkedTokenType.DEFAULT;
+    } else if (type == Keyword.DEFERRED) {
+      return UnlinkedTokenType.DEFERRED;
+    } else if (type == Keyword.DO) {
+      return UnlinkedTokenType.DO;
+    } else if (type == TokenType.DOUBLE) {
+      return UnlinkedTokenType.DOUBLE;
+    } else if (type == Keyword.DYNAMIC) {
+      return UnlinkedTokenType.DYNAMIC;
+    } else if (type == Keyword.ELSE) {
+      return UnlinkedTokenType.ELSE;
+    } else if (type == Keyword.ENUM) {
+      return UnlinkedTokenType.ENUM;
+    } else if (type == TokenType.EOF) {
+      return UnlinkedTokenType.EOF;
+    } else if (type == TokenType.EQ) {
+      return UnlinkedTokenType.EQ;
+    } else if (type == TokenType.EQ_EQ) {
+      return UnlinkedTokenType.EQ_EQ;
+    } else if (type == Keyword.EXPORT) {
+      return UnlinkedTokenType.EXPORT;
+    } else if (type == Keyword.EXTENDS) {
+      return UnlinkedTokenType.EXTENDS;
+    } else if (type == Keyword.EXTERNAL) {
+      return UnlinkedTokenType.EXTERNAL;
+    } else if (type == Keyword.FACTORY) {
+      return UnlinkedTokenType.FACTORY;
+    } else if (type == Keyword.FALSE) {
+      return UnlinkedTokenType.FALSE;
+    } else if (type == Keyword.FINAL) {
+      return UnlinkedTokenType.FINAL;
+    } else if (type == Keyword.FINALLY) {
+      return UnlinkedTokenType.FINALLY;
+    } else if (type == Keyword.FOR) {
+      return UnlinkedTokenType.FOR;
+    } else if (type == Keyword.FUNCTION) {
+      return UnlinkedTokenType.FUNCTION_KEYWORD;
+    } else if (type == TokenType.FUNCTION) {
+      return UnlinkedTokenType.FUNCTION;
+    } else if (type == Keyword.GET) {
+      return UnlinkedTokenType.GET;
+    } else if (type == TokenType.GT) {
+      return UnlinkedTokenType.GT;
+    } else if (type == TokenType.GT_EQ) {
+      return UnlinkedTokenType.GT_EQ;
+    } else if (type == TokenType.GT_GT) {
+      return UnlinkedTokenType.GT_GT;
+    } else if (type == TokenType.GT_GT_EQ) {
+      return UnlinkedTokenType.GT_GT_EQ;
+    } else if (type == TokenType.HASH) {
+      return UnlinkedTokenType.HASH;
+    } else if (type == TokenType.HEXADECIMAL) {
+      return UnlinkedTokenType.HEXADECIMAL;
+    } else if (type == Keyword.HIDE) {
+      return UnlinkedTokenType.HIDE;
+    } else if (type == TokenType.IDENTIFIER) {
+      return UnlinkedTokenType.IDENTIFIER;
+    } else if (type == Keyword.IF) {
+      return UnlinkedTokenType.IF;
+    } else if (type == Keyword.IMPLEMENTS) {
+      return UnlinkedTokenType.IMPLEMENTS;
+    } else if (type == Keyword.IMPORT) {
+      return UnlinkedTokenType.IMPORT;
+    } else if (type == Keyword.IN) {
+      return UnlinkedTokenType.IN;
+    } else if (type == TokenType.INDEX) {
+      return UnlinkedTokenType.INDEX;
+    } else if (type == TokenType.INDEX_EQ) {
+      return UnlinkedTokenType.INDEX_EQ;
+    } else if (type == TokenType.INT) {
+      return UnlinkedTokenType.INT;
+    } else if (type == Keyword.INTERFACE) {
+      return UnlinkedTokenType.INTERFACE;
+    } else if (type == TokenType.IS) {
+      return UnlinkedTokenType.IS;
+    } else if (type == Keyword.LIBRARY) {
+      return UnlinkedTokenType.LIBRARY;
+    } else if (type == TokenType.LT) {
+      return UnlinkedTokenType.LT;
+    } else if (type == TokenType.LT_EQ) {
+      return UnlinkedTokenType.LT_EQ;
+    } else if (type == TokenType.LT_LT) {
+      return UnlinkedTokenType.LT_LT;
+    } else if (type == TokenType.LT_LT_EQ) {
+      return UnlinkedTokenType.LT_LT_EQ;
+    } else if (type == TokenType.MINUS) {
+      return UnlinkedTokenType.MINUS;
+    } else if (type == TokenType.MINUS_EQ) {
+      return UnlinkedTokenType.MINUS_EQ;
+    } else if (type == TokenType.MINUS_MINUS) {
+      return UnlinkedTokenType.MINUS_MINUS;
+    } else if (type == Keyword.MIXIN) {
+      return UnlinkedTokenType.MIXIN;
+    } else if (type == TokenType.MULTI_LINE_COMMENT) {
+      return UnlinkedTokenType.MULTI_LINE_COMMENT;
+    } else if (type == Keyword.NATIVE) {
+      return UnlinkedTokenType.NATIVE;
+    } else if (type == Keyword.NEW) {
+      return UnlinkedTokenType.NEW;
+    } else if (type == Keyword.NULL) {
+      return UnlinkedTokenType.NULL;
+    } else if (type == Keyword.OF) {
+      return UnlinkedTokenType.OF;
+    } else if (type == Keyword.ON) {
+      return UnlinkedTokenType.ON;
+    } else if (type == TokenType.OPEN_CURLY_BRACKET) {
+      return UnlinkedTokenType.OPEN_CURLY_BRACKET;
+    } else if (type == TokenType.OPEN_PAREN) {
+      return UnlinkedTokenType.OPEN_PAREN;
+    } else if (type == TokenType.OPEN_SQUARE_BRACKET) {
+      return UnlinkedTokenType.OPEN_SQUARE_BRACKET;
+    } else if (type == Keyword.OPERATOR) {
+      return UnlinkedTokenType.OPERATOR;
+    } else if (type == Keyword.PART) {
+      return UnlinkedTokenType.PART;
+    } else if (type == Keyword.PATCH) {
+      return UnlinkedTokenType.PATCH;
+    } else if (type == TokenType.PERCENT) {
+      return UnlinkedTokenType.PERCENT;
+    } else if (type == TokenType.PERCENT_EQ) {
+      return UnlinkedTokenType.PERCENT_EQ;
+    } else if (type == TokenType.PERIOD) {
+      return UnlinkedTokenType.PERIOD;
+    } else if (type == TokenType.PERIOD_PERIOD) {
+      return UnlinkedTokenType.PERIOD_PERIOD;
+    } else if (type == TokenType.PERIOD_PERIOD_PERIOD) {
+      return UnlinkedTokenType.PERIOD_PERIOD_PERIOD;
+    } else if (type == TokenType.PERIOD_PERIOD_PERIOD_QUESTION) {
+      return UnlinkedTokenType.PERIOD_PERIOD_PERIOD_QUESTION;
+    } else if (type == TokenType.PLUS) {
+      return UnlinkedTokenType.PLUS;
+    } else if (type == TokenType.PLUS_EQ) {
+      return UnlinkedTokenType.PLUS_EQ;
+    } else if (type == TokenType.PLUS_PLUS) {
+      return UnlinkedTokenType.PLUS_PLUS;
+    } else if (type == TokenType.QUESTION) {
+      return UnlinkedTokenType.QUESTION;
+    } else if (type == TokenType.QUESTION_PERIOD) {
+      return UnlinkedTokenType.QUESTION_PERIOD;
+    } else if (type == TokenType.QUESTION_QUESTION) {
+      return UnlinkedTokenType.QUESTION_QUESTION;
+    } else if (type == TokenType.QUESTION_QUESTION_EQ) {
+      return UnlinkedTokenType.QUESTION_QUESTION_EQ;
+    } else if (type == Keyword.RETHROW) {
+      return UnlinkedTokenType.RETHROW;
+    } else if (type == Keyword.RETURN) {
+      return UnlinkedTokenType.RETURN;
+    } else if (type == TokenType.SCRIPT_TAG) {
+      return UnlinkedTokenType.SCRIPT_TAG;
+    } else if (type == TokenType.SEMICOLON) {
+      return UnlinkedTokenType.SEMICOLON;
+    } else if (type == Keyword.SET) {
+      return UnlinkedTokenType.SET;
+    } else if (type == Keyword.SHOW) {
+      return UnlinkedTokenType.SHOW;
+    } else if (type == TokenType.SINGLE_LINE_COMMENT) {
+      return UnlinkedTokenType.SINGLE_LINE_COMMENT;
+    } else if (type == TokenType.SLASH) {
+      return UnlinkedTokenType.SLASH;
+    } else if (type == TokenType.SLASH_EQ) {
+      return UnlinkedTokenType.SLASH_EQ;
+    } else if (type == Keyword.SOURCE) {
+      return UnlinkedTokenType.SOURCE;
+    } else if (type == TokenType.STAR) {
+      return UnlinkedTokenType.STAR;
+    } else if (type == TokenType.STAR_EQ) {
+      return UnlinkedTokenType.STAR_EQ;
+    } else if (type == Keyword.STATIC) {
+      return UnlinkedTokenType.STATIC;
+    } else if (type == TokenType.STRING) {
+      return UnlinkedTokenType.STRING;
+    } else if (type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
+      return UnlinkedTokenType.STRING_INTERPOLATION_EXPRESSION;
+    } else if (type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
+      return UnlinkedTokenType.STRING_INTERPOLATION_IDENTIFIER;
+    } else if (type == Keyword.SUPER) {
+      return UnlinkedTokenType.SUPER;
+    } else if (type == Keyword.SWITCH) {
+      return UnlinkedTokenType.SWITCH;
+    } else if (type == Keyword.SYNC) {
+      return UnlinkedTokenType.SYNC;
+    } else if (type == Keyword.THIS) {
+      return UnlinkedTokenType.THIS;
+    } else if (type == Keyword.THROW) {
+      return UnlinkedTokenType.THROW;
+    } else if (type == TokenType.TILDE) {
+      return UnlinkedTokenType.TILDE;
+    } else if (type == TokenType.TILDE_SLASH) {
+      return UnlinkedTokenType.TILDE_SLASH;
+    } else if (type == TokenType.TILDE_SLASH_EQ) {
+      return UnlinkedTokenType.TILDE_SLASH_EQ;
+    } else if (type == Keyword.TRUE) {
+      return UnlinkedTokenType.TRUE;
+    } else if (type == Keyword.TRY) {
+      return UnlinkedTokenType.TRY;
+    } else if (type == Keyword.TYPEDEF) {
+      return UnlinkedTokenType.TYPEDEF;
+    } else if (type == Keyword.VAR) {
+      return UnlinkedTokenType.VAR;
+    } else if (type == Keyword.VOID) {
+      return UnlinkedTokenType.VOID;
+    } else if (type == Keyword.WHILE) {
+      return UnlinkedTokenType.WHILE;
+    } else if (type == Keyword.WITH) {
+      return UnlinkedTokenType.WITH;
+    } else if (type == Keyword.YIELD) {
+      return UnlinkedTokenType.YIELD;
+    } else {
+      throw StateError('Unexpected type: $type');
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
new file mode 100644
index 0000000..def0f8d
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -0,0 +1,176 @@
+// Copyright (c) 2019, 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 'package:analyzer/dart/ast/standard_ast_factory.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/ast_resolver.dart';
+import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
+import 'package:analyzer/src/summary2/link.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+
+DartType _dynamicIfNull(DartType type) {
+  if (type == null || type.isBottom || type.isDartCoreNull) {
+    return DynamicTypeImpl.instance;
+  }
+  return type;
+}
+
+class TopLevelInference {
+  final Linker linker;
+  final Reference libraryRef;
+  final UnitBuilder unit;
+
+  TopLevelInference(this.linker, this.libraryRef, this.unit);
+
+  void infer() {
+    _inferFieldsTemporary();
+    _inferConstructorFieldFormals();
+  }
+
+  void _inferConstructorFieldFormals() {
+    _visitClassList((unitDeclaration) {
+      var members = unitDeclaration.classOrMixinDeclaration_members;
+
+      var fields = <String, LinkedNodeType>{};
+      _visitClassFields(unitDeclaration, (field) {
+        var name = unit.context.getVariableName(field);
+        var type = field.variableDeclaration_type2;
+        if (type == null) {
+          throw StateError('Field $name should have a type.');
+        }
+        fields[name] = type;
+      });
+
+      for (var member in members) {
+        if (member.kind == LinkedNodeKind.constructorDeclaration) {
+          for (var parameter in member.constructorDeclaration_parameters
+              .formalParameterList_parameters) {
+            if (parameter.kind == LinkedNodeKind.fieldFormalParameter &&
+                parameter.fieldFormalParameter_type2 == null) {
+              var name = unit.context.getSimpleName(
+                parameter.normalFormalParameter_identifier,
+              );
+              var type = fields[name];
+              if (type == null) {
+                type = LinkedNodeTypeBuilder(
+                  kind: LinkedNodeTypeKind.dynamic_,
+                );
+              }
+              parameter.fieldFormalParameter_type2 = type;
+            }
+          }
+        }
+      }
+    });
+  }
+
+  void _inferFieldsTemporary() {
+    var unitDeclarations = unit.node.compilationUnit_declarations;
+    for (LinkedNodeBuilder unitDeclaration in unitDeclarations) {
+      if (unitDeclaration.kind == LinkedNodeKind.classDeclaration) {
+        _visitClassFields(unitDeclaration, (field) {
+          var name = unit.context.getVariableName(field);
+          // TODO(scheglov) Use inheritance
+          if (field.variableDeclaration_type2 == null) {
+            field.variableDeclaration_type2 = LinkedNodeTypeBuilder(
+              kind: LinkedNodeTypeKind.dynamic_,
+            );
+          }
+        });
+
+        var members = unitDeclaration.classOrMixinDeclaration_members;
+        for (var member in members) {
+          if (member.kind == LinkedNodeKind.methodDeclaration) {
+            // TODO(scheglov) Use inheritance
+            if (member.methodDeclaration_returnType2 == null) {
+              if (unit.context.isSetter(member)) {
+                member.methodDeclaration_returnType2 = LinkedNodeTypeBuilder(
+                  kind: LinkedNodeTypeKind.void_,
+                );
+              } else {
+                member.methodDeclaration_returnType2 = LinkedNodeTypeBuilder(
+                  kind: LinkedNodeTypeKind.dynamic_,
+                );
+              }
+            }
+          }
+        }
+      } else if (unitDeclaration.kind == LinkedNodeKind.functionDeclaration) {
+        if (unit.context.isSetter(unitDeclaration)) {
+          unitDeclaration.functionDeclaration_returnType2 =
+              LinkedNodeTypeBuilder(
+            kind: LinkedNodeTypeKind.void_,
+          );
+        }
+      } else if (unitDeclaration.kind ==
+          LinkedNodeKind.topLevelVariableDeclaration) {
+        var variableList =
+            unitDeclaration.topLevelVariableDeclaration_variableList;
+        for (var variable in variableList.variableDeclarationList_variables) {
+          // TODO(scheglov) infer in the correct order
+          if (variable.variableDeclaration_type2 == null ||
+              unit.context.isConst(variable)) {
+            _inferVariableTypeFromInitializerTemporary(variable);
+          }
+        }
+      }
+    }
+  }
+
+  void _inferVariableTypeFromInitializerTemporary(LinkedNodeBuilder node) {
+    var unresolvedNode = node.variableDeclaration_initializer;
+
+    if (unresolvedNode == null) {
+      node.variableDeclaration_type2 = LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.dynamic_,
+      );
+      return;
+    }
+
+    var expression = unit.context.readInitializer(node);
+    astFactory.expressionFunctionBody(null, null, expression, null);
+
+    // TODO(scheglov) can be shared for the whole library
+    var astResolver = AstResolver(linker, libraryRef);
+
+    var resolvedNode = astResolver.resolve(unit, expression);
+    node.variableDeclaration_initializer = resolvedNode;
+
+    if (node.variableDeclaration_type2 == null) {
+      var initializerType = expression.staticType;
+      initializerType = _dynamicIfNull(initializerType);
+
+      var linkingBundleContext = linker.linkingBundleContext;
+      node.variableDeclaration_type2 = linkingBundleContext.writeType(
+        initializerType,
+      );
+    }
+  }
+
+  void _visitClassFields(
+      LinkedNode class_, void Function(LinkedNodeBuilder) f) {
+    var members = class_.classOrMixinDeclaration_members;
+
+    for (var member in members) {
+      if (member.kind == LinkedNodeKind.fieldDeclaration) {
+        var variableList = member.fieldDeclaration_fields;
+        for (var field in variableList.variableDeclarationList_variables) {
+          f(field);
+        }
+      }
+    }
+  }
+
+  void _visitClassList(void Function(LinkedNodeBuilder) f) {
+    var unitDeclarations = unit.node.compilationUnit_declarations;
+    for (LinkedNodeBuilder unitDeclaration in unitDeclarations) {
+      if (unitDeclaration.kind == LinkedNodeKind.classDeclaration) {
+        f(unitDeclaration);
+      }
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/task/api/dart.dart b/pkg/analyzer/lib/src/task/api/dart.dart
index f1f19e6..82f6bfc 100644
--- a/pkg/analyzer/lib/src/task/api/dart.dart
+++ b/pkg/analyzer/lib/src/task/api/dart.dart
@@ -9,7 +9,6 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
 import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/dart.dart';
 
 /**
  * The analysis errors associated with a [Source] representing a compilation
@@ -89,8 +88,7 @@
  * The result is only available for [Source]s representing a compilation unit.
  */
 final ResultDescriptor<CompilationUnit> PARSED_UNIT =
-    new ResultDescriptor<CompilationUnit>('PARSED_UNIT', null,
-        cachingPolicy: AST_CACHING_POLICY);
+    new ResultDescriptor<CompilationUnit>('PARSED_UNIT', null);
 
 /**
  * The resolved [CompilationUnit] associated with a compilation unit, with
@@ -99,8 +97,7 @@
  * The result is only available for [LibrarySpecificUnit]s.
  */
 final ResultDescriptor<CompilationUnit> RESOLVED_UNIT =
-    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT', null,
-        cachingPolicy: AST_CACHING_POLICY);
+    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT', null);
 
 /**
  * The kind of a [Source].
@@ -116,9 +113,8 @@
  *
  * The result is only available for [Source]s representing a compilation unit.
  */
-final ResultDescriptor<Token> TOKEN_STREAM = new ResultDescriptor<Token>(
-    'TOKEN_STREAM', null,
-    cachingPolicy: TOKEN_STREAM_CACHING_POLICY);
+final ResultDescriptor<Token> TOKEN_STREAM =
+    new ResultDescriptor<Token>('TOKEN_STREAM', null);
 
 /**
  * The sources of the Dart files that a library consists of.
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
deleted file mode 100644
index 47c7c65..0000000
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ /dev/null
@@ -1,5778 +0,0 @@
-// Copyright (c) 2015, 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';
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/standard_resolution_map.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/source/line_info.dart';
-import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/dart/ast/ast.dart'
-    show
-        CompilationUnitImpl,
-        NamespaceDirectiveImpl,
-        UriBasedDirectiveImpl,
-        UriValidationCode;
-import 'package:analyzer/src/dart/ast/utilities.dart';
-import 'package:analyzer/src/dart/constant/constant_verifier.dart';
-import 'package:analyzer/src/dart/element/builder.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
-import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:analyzer/src/dart/sdk/patch.dart';
-import 'package:analyzer/src/dart/sdk/sdk.dart';
-import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/error/inheritance_override.dart';
-import 'package:analyzer/src/error/pending_error.dart';
-import 'package:analyzer/src/generated/constant.dart';
-import 'package:analyzer/src/generated/declaration_resolver.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/error_verifier.dart';
-import 'package:analyzer/src/generated/incremental_resolver.dart';
-import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/plugin/engine_plugin.dart';
-import 'package:analyzer/src/services/lint.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/api/general.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/driver.dart';
-import 'package:analyzer/src/task/general.dart';
-import 'package:analyzer/src/task/inputs.dart';
-import 'package:analyzer/src/task/model.dart';
-import 'package:analyzer/src/task/strong/checker.dart';
-import 'package:analyzer/src/task/strong_mode.dart';
-
-/**
- * The [ResultCachingPolicy] for ASTs.
- */
-const ResultCachingPolicy AST_CACHING_POLICY =
-    const SimpleResultCachingPolicy(1024 * 64, 32);
-
-/**
- * The [ResultCachingPolicy] for lists of [ConstantEvaluationTarget]s.
- */
-const ResultCachingPolicy CONSTANT_EVALUATION_TARGET_LIST_POLICY =
-    const SimpleResultCachingPolicy(-1, -1);
-
-/**
- * The [ResultCachingPolicy] for [ConstantEvaluationTarget]s.
- */
-const ResultCachingPolicy CONSTANT_EVALUATION_TARGET_POLICY =
-    const SimpleResultCachingPolicy(-1, -1);
-
-/**
- * The [ResultCachingPolicy] for [Element]s.
- */
-const ResultCachingPolicy ELEMENT_CACHING_POLICY =
-    const SimpleResultCachingPolicy(-1, -1);
-
-/**
- * The [ResultCachingPolicy] for [TOKEN_STREAM].
- */
-const ResultCachingPolicy TOKEN_STREAM_CACHING_POLICY =
-    const SimpleResultCachingPolicy(1, 1);
-
-/**
- * The [ResultCachingPolicy] for [UsedImportedElements]s.
- */
-const ResultCachingPolicy USED_IMPORTED_ELEMENTS_POLICY =
-    const SimpleResultCachingPolicy(-1, -1);
-
-/**
- * The [ResultCachingPolicy] for [UsedLocalElements]s.
- */
-const ResultCachingPolicy USED_LOCAL_ELEMENTS_POLICY =
-    const SimpleResultCachingPolicy(-1, -1);
-
-/**
- * The errors produced while building a library's directives.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<AnalysisError> BUILD_DIRECTIVES_ERRORS =
-    new ListResultDescriptor<AnalysisError>(
-        'BUILD_DIRECTIVES_ERRORS', AnalysisError.NO_ERRORS);
-/**
- * The errors produced while building a library element.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<AnalysisError> BUILD_LIBRARY_ERRORS =
-    new ListResultDescriptor<AnalysisError>(
-        'BUILD_LIBRARY_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * A list of the [ConstantEvaluationTarget]s defined in a unit.  This includes
- * constants defined at top level, statically inside classes, and local to
- * functions, as well as constant constructors, annotations, and default values
- * of parameters.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<ConstantEvaluationTarget>
-    COMPILATION_UNIT_CONSTANTS =
-    new ListResultDescriptor<ConstantEvaluationTarget>(
-        'COMPILATION_UNIT_CONSTANTS', null,
-        cachingPolicy: CONSTANT_EVALUATION_TARGET_LIST_POLICY);
-
-/**
- * The element model associated with a single compilation unit.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnitElement> COMPILATION_UNIT_ELEMENT =
-    new ResultDescriptor<CompilationUnitElement>(
-        'COMPILATION_UNIT_ELEMENT', null,
-        cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The list of [ConstantEvaluationTarget]s on which the target constant element
- * depends.
- *
- * The result is only available for targets representing a
- * [ConstantEvaluationTarget] (i.e. a constant variable declaration, a constant
- * constructor, or a parameter element with a default value).
- */
-final ListResultDescriptor<ConstantEvaluationTarget> CONSTANT_DEPENDENCIES =
-    new ListResultDescriptor<ConstantEvaluationTarget>(
-        'CONSTANT_DEPENDENCIES', const <ConstantEvaluationTarget>[]);
-
-/**
- * The flag specifying that the target constant element expression AST is
- * resolved, i.e. identifiers have all required elements set.
- *
- * The result is only available for targets representing a
- * [ConstantEvaluationTarget] (i.e. a constant variable declaration, a constant
- * constructor, or a parameter element with a default value).
- */
-final ResultDescriptor<bool> CONSTANT_EXPRESSION_RESOLVED =
-    new ResultDescriptor<bool>('CONSTANT_EXPRESSION_RESOLVED', false);
-
-/**
- * The list of [ConstantEvaluationTarget]s on which constant expressions of a
- * unit depend.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<ConstantEvaluationTarget>
-    CONSTANT_EXPRESSIONS_DEPENDENCIES =
-    new ListResultDescriptor<ConstantEvaluationTarget>(
-        'CONSTANT_EXPRESSIONS_DEPENDENCIES',
-        const <ConstantEvaluationTarget>[]);
-
-/**
- * A [ConstantEvaluationTarget] that has been successfully constant-evaluated.
- *
- * TODO(paulberry): is ELEMENT_CACHING_POLICY the correct caching policy?
- *
- * The result is only available for [ConstantEvaluationTarget]s.
- *
- */
-final ResultDescriptor<ConstantEvaluationTarget> CONSTANT_VALUE =
-    new ResultDescriptor<ConstantEvaluationTarget>('CONSTANT_VALUE', null,
-        cachingPolicy: CONSTANT_EVALUATION_TARGET_POLICY);
-
-/**
- * The sources representing the libraries that include a given source as a part.
- *
- * The result is only available for [Source]s representing a compilation unit.
- */
-final ListResultDescriptor<Source> CONTAINING_LIBRARIES =
-    new ListResultDescriptor<Source>('CONTAINING_LIBRARIES', const <Source>[]);
-
-/**
- * The flag specifying that [RESOLVED_UNIT] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT =
-    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT1] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT1 =
-    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT1', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT10] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT10 =
-    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT10', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT11] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT11 =
-    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT11', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT12] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT12 =
-    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT12', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT2] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT2 =
-    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT2', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT3] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT3 =
-    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT3', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT4] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT4 =
-    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT4', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT5] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT5 =
-    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT5', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT6] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT6 =
-    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT6', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT7] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT7 =
-    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT7', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT8] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT8 =
-    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT8', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT9] has been been computed for this
- * compilation unit (without requiring that the AST for it still be in cache).
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<bool> CREATED_RESOLVED_UNIT9 =
-    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT9', false);
-
-/**
- * All [AnalysisError]s results for [Source]s.
- */
-final List<ListResultDescriptor<AnalysisError>> ERROR_SOURCE_RESULTS =
-    <ListResultDescriptor<AnalysisError>>[
-  BUILD_DIRECTIVES_ERRORS,
-  BUILD_LIBRARY_ERRORS,
-  PARSE_ERRORS,
-  SCAN_ERRORS,
-];
-
-/**
- * All [AnalysisError]s results in for [LibrarySpecificUnit]s.
- */
-final List<ListResultDescriptor<AnalysisError>> ERROR_UNIT_RESULTS =
-    <ListResultDescriptor<AnalysisError>>[
-  HINTS,
-  LIBRARY_UNIT_ERRORS,
-  LINTS,
-  RESOLVE_DIRECTIVES_ERRORS,
-  RESOLVE_TYPE_BOUNDS_ERRORS,
-  RESOLVE_TYPE_NAMES_ERRORS,
-  RESOLVE_UNIT_ERRORS,
-  STRONG_MODE_ERRORS,
-  VARIABLE_REFERENCE_ERRORS,
-  VERIFY_ERRORS
-];
-
-/**
- * The sources representing the export closure of a library.
- * The [Source]s include only library sources, not their units.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<Source> EXPORT_SOURCE_CLOSURE =
-    new ListResultDescriptor<Source>('EXPORT_SOURCE_CLOSURE', null);
-
-/**
- * The errors produced while generating hints a compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> HINTS =
-    new ListResultDescriptor<AnalysisError>(
-        'HINT_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The ignore information for a [Source].
- */
-final ResultDescriptor<IgnoreInfo> IGNORE_INFO =
-    new ResultDescriptor<IgnoreInfo>('IGNORE_INFO', null);
-
-/**
- * A list of the [VariableElement]s whose type should be inferred that another
- * inferable static variable (the target) depends on.
- *
- * The result is only available for [VariableElement]s, and only when strong
- * mode is enabled.
- */
-final ListResultDescriptor<VariableElement>
-    INFERABLE_STATIC_VARIABLE_DEPENDENCIES =
-    new ListResultDescriptor<VariableElement>(
-        'INFERABLE_STATIC_VARIABLE_DEPENDENCIES', null);
-
-/**
- * A list of the [VariableElement]s defined in a unit whose type should be
- * inferred. This includes variables defined at the library level as well as
- * static members inside classes.
- *
- * The result is only available for [LibrarySpecificUnit]s, and only when strong
- * mode is enabled.
- */
-final ListResultDescriptor<VariableElement> INFERABLE_STATIC_VARIABLES_IN_UNIT =
-    new ListResultDescriptor<VariableElement>(
-        'INFERABLE_STATIC_VARIABLES_IN_UNIT', null);
-
-/**
- * An inferable static variable ([VariableElement]) whose type has been
- * inferred.
- *
- * The result is only available for [VariableElement]s, and only when strong
- * mode is enabled.
- */
-final ResultDescriptor<VariableElement> INFERRED_STATIC_VARIABLE =
-    new ResultDescriptor<VariableElement>('INFERRED_STATIC_VARIABLE', null,
-        cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * A list of the [LibraryElement]s that make up the strongly connected
- * component in the import/export graph in which the target resides.
- *
- * Only non-empty in strongMode.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<LibraryElement> LIBRARY_CYCLE =
-    new ListResultDescriptor<LibraryElement>('LIBRARY_CYCLE', null);
-
-/**
- * A list of the [LibrarySpecificUnit]s that comprise all of the parts and
- * libraries in the direct import/export dependencies of the library cycle
- * of the target, with the intra-component dependencies excluded.
- *
- * Only non-empty in strongMode.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<LibrarySpecificUnit> LIBRARY_CYCLE_DEPENDENCIES =
-    new ListResultDescriptor<LibrarySpecificUnit>(
-        'LIBRARY_CYCLE_DEPENDENCIES', null);
-
-/**
- * A list of the [LibrarySpecificUnit]s (including all parts) that make up
- * the strongly connected component in the import/export graph in which the
- * target resides.
- *
- * Only non-empty in strongMode.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<LibrarySpecificUnit> LIBRARY_CYCLE_UNITS =
-    new ListResultDescriptor<LibrarySpecificUnit>('LIBRARY_CYCLE_UNITS', null);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * The [LibraryElement] and its [CompilationUnitElement]s are attached to each
- * other. Directives 'library', 'part' and 'part of' are resolved.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT1 =
-    new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT1', null,
-        cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * In addition to [LIBRARY_ELEMENT1] also [LibraryElement.imports] and
- * [LibraryElement.exports] are set.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT2 =
-    new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT2', null,
-        cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * In addition to [LIBRARY_ELEMENT2] the [LibraryElement.publicNamespace] is set.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT3 =
-    new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT3', null,
-        cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * In addition to [LIBRARY_ELEMENT3] the [LibraryElement.entryPoint] is set,
- * if the library does not declare one already and one of the exported
- * libraries exports one.
- *
- * Also [LibraryElement.exportNamespace] is set.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT4 =
-    new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT4', null,
-        cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * [LIBRARY_ELEMENT5] plus resolved types type parameter bounds.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT5 =
-    new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT5', null,
-        cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * [LIBRARY_ELEMENT5] plus resolved types for every element.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT6 =
-    new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT6', null,
-        cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * [LIBRARY_ELEMENT6] plus [RESOLVED_UNIT7] for all library units.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT7 =
-    new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT7', null,
-        cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * [LIBRARY_ELEMENT7] for the library and its import/export closure.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT8 =
-    new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT8', null,
-        cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * The partial [LibraryElement] associated with a library.
- *
- * The same as a [LIBRARY_ELEMENT8].
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT9 =
-    new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT9', null,
-        cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
- * List of all `LIBRARY_ELEMENT` results.
- */
-final List<ResultDescriptor<LibraryElement>> LIBRARY_ELEMENT_RESULTS =
-    <ResultDescriptor<LibraryElement>>[
-  LIBRARY_ELEMENT1,
-  LIBRARY_ELEMENT2,
-  LIBRARY_ELEMENT3,
-  LIBRARY_ELEMENT4,
-  LIBRARY_ELEMENT5,
-  LIBRARY_ELEMENT6,
-  LIBRARY_ELEMENT7,
-  LIBRARY_ELEMENT8,
-  LIBRARY_ELEMENT9,
-  LIBRARY_ELEMENT
-];
-
-/**
- * The flag specifying whether all analysis errors are computed in a specific
- * library.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<bool> LIBRARY_ERRORS_READY =
-    new ResultDescriptor<bool>('LIBRARY_ERRORS_READY', false);
-
-/**
- * The [LibrarySpecificUnit]s that a library consists of.
- *
- * The list will include the defining unit and units for [INCLUDED_PARTS].
- * So, it is never empty or `null`.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<LibrarySpecificUnit> LIBRARY_SPECIFIC_UNITS =
-    new ListResultDescriptor<LibrarySpecificUnit>(
-        'LIBRARY_SPECIFIC_UNITS', const <LibrarySpecificUnit>[]);
-
-/**
- * The analysis errors associated with a compilation unit in a specific library.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> LIBRARY_UNIT_ERRORS =
-    new ListResultDescriptor<AnalysisError>(
-        'LIBRARY_UNIT_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The errors produced while generating lints for a compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> LINTS =
-    new ListResultDescriptor<AnalysisError>(
-        'LINT_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The errors produced while parsing a compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [Source]s representing a compilation unit.
- */
-final ListResultDescriptor<AnalysisError> PARSE_ERRORS =
-    new ListResultDescriptor<AnalysisError>(
-        'PARSE_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The list of [PendingError]s for a compilation unit.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<PendingError> PENDING_ERRORS =
-    new ListResultDescriptor<PendingError>(
-        'PENDING_ERRORS', const <PendingError>[]);
-
-/**
- * The flag specifying that [LIBRARY_ELEMENT2] is ready for a library and its
- * import/export closure.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<bool> READY_LIBRARY_ELEMENT2 =
-    new ResultDescriptor<bool>('READY_LIBRARY_ELEMENT2', false);
-
-/**
- * The flag specifying that [LIBRARY_ELEMENT6] is ready for a library and its
- * import/export closure.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<bool> READY_LIBRARY_ELEMENT6 =
-    new ResultDescriptor<bool>('READY_LIBRARY_ELEMENT6', false);
-
-/**
- * The flag specifying that [LIBRARY_ELEMENT7] is ready for a library and its
- * import/export closure.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<bool> READY_LIBRARY_ELEMENT7 =
-    new ResultDescriptor<bool>('READY_LIBRARY_ELEMENT7', false);
-
-/**
- * The flag specifying that [RESOLVED_UNIT] is ready for all of the units of a
- * library.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<bool> READY_RESOLVED_UNIT =
-    new ResultDescriptor<bool>('READY_RESOLVED_UNIT', false);
-
-/**
- * The sources of the Dart files that a library references.
- *
- * The list is the union of [IMPORTED_LIBRARIES], [EXPORTED_LIBRARIES] and
- * [UNITS] of the defining unit and [INCLUDED_PARTS]. Never empty or `null`.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<Source> REFERENCED_SOURCES =
-    new ListResultDescriptor<Source>('REFERENCED_SOURCES', const <Source>[]);
-
-/**
- * The list of [ConstantEvaluationTarget]s on which error verification depends.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<ConstantEvaluationTarget> REQUIRED_CONSTANTS =
-    new ListResultDescriptor<ConstantEvaluationTarget>(
-        'REQUIRED_CONSTANTS', const <ConstantEvaluationTarget>[]);
-
-/**
- * The errors produced while resolving a library's directives.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ListResultDescriptor<AnalysisError> RESOLVE_DIRECTIVES_ERRORS =
-    new ListResultDescriptor<AnalysisError>(
-        'RESOLVE_DIRECTIVES_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The errors produced while resolving bounds of type parameters of classes,
- * class and function aliases.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> RESOLVE_TYPE_BOUNDS_ERRORS =
-    new ListResultDescriptor<AnalysisError>(
-        'RESOLVE_TYPE_BOUNDS_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The errors produced while resolving type names.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> RESOLVE_TYPE_NAMES_ERRORS =
-    new ListResultDescriptor<AnalysisError>(
-        'RESOLVE_TYPE_NAMES_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The errors produced while resolving a full compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> RESOLVE_UNIT_ERRORS =
-    new ListResultDescriptor<AnalysisError>(
-        'RESOLVE_UNIT_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * Tasks that use this value as an input can assume that the [SimpleIdentifier]s
- * at all declaration sites have been bound to the element defined by the
- * declaration, except for the constants defined in an 'enum' declaration.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT1 =
-    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT1', null,
-        cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The resolved [CompilationUnit] associated with a compilation unit in which
- * the types of class members have been inferred in addition to everything that
- * is true of a [RESOLVED_UNIT9].
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT10 =
-    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT10', null,
-        cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The resolved [CompilationUnit] associated with a compilation unit, with
- * constants not yet resolved.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT11 =
-    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT11', null,
-        cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The resolved [CompilationUnit] associated with a compilation unit, with
- * constants resolved.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT12 =
-    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT12', null,
-        cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * In addition to what is true of a [RESOLVED_UNIT1], tasks that use this value
- * as an input can assume that its directives have been resolved.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT2 =
-    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT2', null,
-        cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * Tasks that use this value as an input can assume that the [SimpleIdentifier]s
- * at all declaration sites have been bound to the element defined by the
- * declaration, including the constants defined in an 'enum' declaration.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT3 =
-    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT3', null,
-        cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * In addition to what is true of a [RESOLVED_UNIT3], tasks that use this value
- * as an input can assume that the types associated with type bounds have been
- * resolved.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT4 =
-    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT4', null,
-        cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * In addition to what is true of a [RESOLVED_UNIT4], tasks that use this value
- * as an input can assume that the types associated with declarations have been
- * resolved. This includes the types of superclasses, mixins, interfaces,
- * fields, return types, parameters, and local variables.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT5 =
-    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT5', null,
-        cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * In addition to what is true of a [RESOLVED_UNIT5], tasks that use this value
- * as an input can assume that references to local variables and formal
- * parameters have been resolved.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT6 =
-    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT6', null,
-        cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * In addition to what is true of a [RESOLVED_UNIT6], tasks that use this value
- * as an input can assume that elements and types associated with expressions
- * outside of method bodies (essentially initializers) have been initially
- * resolved.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT7 =
-    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT7', null,
-        cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * In addition to what is true of a [RESOLVED_UNIT7], tasks that use this value
- * as an input can assume that the types of static variables have been inferred.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT8 =
-    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT8', null,
-        cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * The partially resolved [CompilationUnit] associated with a compilation unit.
- *
- * In addition to what is true of a [RESOLVED_UNIT8], tasks that use this value
- * as an input can assume that the initializers of instance variables have been
- * re-resolved.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT9 =
-    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT9', null,
-        cachingPolicy: AST_CACHING_POLICY);
-
-/**
- * List of all `RESOLVED_UNITx` results.
- */
-final List<ResultDescriptor<CompilationUnit>> RESOLVED_UNIT_RESULTS =
-    <ResultDescriptor<CompilationUnit>>[
-  RESOLVED_UNIT1,
-  RESOLVED_UNIT2,
-  RESOLVED_UNIT3,
-  RESOLVED_UNIT4,
-  RESOLVED_UNIT5,
-  RESOLVED_UNIT6,
-  RESOLVED_UNIT7,
-  RESOLVED_UNIT8,
-  RESOLVED_UNIT9,
-  RESOLVED_UNIT10,
-  RESOLVED_UNIT11,
-  RESOLVED_UNIT12,
-  RESOLVED_UNIT
-];
-
-/**
- * The errors produced while scanning a compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [Source]s representing a compilation unit.
- */
-final ListResultDescriptor<AnalysisError> SCAN_ERRORS =
-    new ListResultDescriptor<AnalysisError>(
-        'SCAN_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The errors produced while resolving a static [VariableElement] initializer.
- *
- * The result is only available for [VariableElement]s, and only when strong
- * mode is enabled.
- */
-final ListResultDescriptor<AnalysisError> STATIC_VARIABLE_RESOLUTION_ERRORS =
-    new ListResultDescriptor<AnalysisError>(
-        'STATIC_VARIABLE_RESOLUTION_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * A list of the [AnalysisError]s reported while resolving static
- * [INFERABLE_STATIC_VARIABLES_IN_UNIT] defined in a unit.
- *
- * The result is only available for [LibrarySpecificUnit]s, and only when strong
- * mode is enabled.
- */
-final ListResultDescriptor<AnalysisError>
-    STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT =
-    new ListResultDescriptor<AnalysisError>(
-        'STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT', AnalysisError.NO_ERRORS);
-
-/**
- * The additional strong mode errors produced while verifying a
- * compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnits]s representing a
- * compilation unit.
- *
- */
-final ListResultDescriptor<AnalysisError> STRONG_MODE_ERRORS =
-    new ListResultDescriptor<AnalysisError>(
-        'STRONG_MODE_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The [TypeProvider] of the [AnalysisContext].
- */
-final ResultDescriptor<TypeProvider> TYPE_PROVIDER =
-    new ResultDescriptor<TypeProvider>('TYPE_PROVIDER', null);
-
-/**
- * The [UsedImportedElements] of a [LibrarySpecificUnit].
- */
-final ResultDescriptor<UsedImportedElements> USED_IMPORTED_ELEMENTS =
-    new ResultDescriptor<UsedImportedElements>('USED_IMPORTED_ELEMENTS', null,
-        cachingPolicy: USED_IMPORTED_ELEMENTS_POLICY);
-
-/**
- * The [UsedLocalElements] of a [LibrarySpecificUnit].
- */
-final ResultDescriptor<UsedLocalElements> USED_LOCAL_ELEMENTS =
-    new ResultDescriptor<UsedLocalElements>('USED_LOCAL_ELEMENTS', null,
-        cachingPolicy: USED_LOCAL_ELEMENTS_POLICY);
-
-/**
- * The errors produced while resolving variable references in a compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> VARIABLE_REFERENCE_ERRORS =
-    new ListResultDescriptor<AnalysisError>(
-        'VARIABLE_REFERENCE_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * The errors produced while verifying a compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> VERIFY_ERRORS =
-    new ListResultDescriptor<AnalysisError>(
-        'VERIFY_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
- * Return a list of unique errors for the [Source] of the given [target].
- */
-List<AnalysisError> getTargetSourceErrors(
-    RecordingErrorListener listener, AnalysisTarget target) {
-  Source source = target.source;
-  List<AnalysisError> errors = listener.getErrorsForSource(source);
-  return getUniqueErrors(errors);
-}
-
-/**
- * Return a list of errors containing the errors from the given [errors] list
- * but with duplications removed.
- */
-List<AnalysisError> getUniqueErrors(List<AnalysisError> errors) {
-  if (errors.isEmpty) {
-    return errors;
-  }
-  return errors.toSet().toList();
-}
-
-/**
- * A task that builds a compilation unit element for a single compilation unit.
- */
-class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the input whose value is the AST for the compilation unit.
-   */
-  static const String PARSED_UNIT_INPUT_NAME = 'PARSED_UNIT_INPUT_NAME';
-
-  /**
-   * The name of the input whose value is the source line info.
-   */
-  static const String LINE_INFO_INPUT_NAME = 'LINE_INFO_INPUT_NAME';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'BuildCompilationUnitElementTask',
-      createTask,
-      buildInputs, <ResultDescriptor>[
-    COMPILATION_UNIT_CONSTANTS,
-    COMPILATION_UNIT_ELEMENT,
-    CREATED_RESOLVED_UNIT1,
-    RESOLVED_UNIT1
-  ]);
-
-  /**
-   * Initialize a newly created task to build a compilation unit element for
-   * the given [target] in the given [context].
-   */
-  BuildCompilationUnitElementTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    LibrarySpecificUnit librarySpecificUnit = target;
-    Source source = getRequiredSource();
-    CompilationUnit unit = getRequiredInput(PARSED_UNIT_INPUT_NAME);
-    LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT_NAME);
-    //
-    // Try to get the existing CompilationUnitElement.
-    //
-    CompilationUnitElement element;
-    {
-      InternalAnalysisContext internalContext =
-          context as InternalAnalysisContext;
-      AnalysisCache analysisCache = internalContext.analysisCache;
-      CacheEntry cacheEntry = internalContext.getCacheEntry(target);
-      element = analysisCache.getValue(target, COMPILATION_UNIT_ELEMENT);
-      if (element == null &&
-          internalContext.aboutToComputeResult(
-              cacheEntry, COMPILATION_UNIT_ELEMENT)) {
-        element = analysisCache.getValue(target, COMPILATION_UNIT_ELEMENT);
-      }
-    }
-    //
-    // Build or reuse CompilationUnitElement.
-    //
-    if (element == null) {
-      CompilationUnitBuilder builder = new CompilationUnitBuilder();
-      element = builder.buildCompilationUnit(
-          source, unit, librarySpecificUnit.library);
-      (element as CompilationUnitElementImpl).lineInfo = lineInfo;
-    } else {
-      new DeclarationResolver().resolve(unit, element);
-    }
-    //
-    // Prepare constants.
-    //
-    ConstantFinder constantFinder = new ConstantFinder();
-    unit.accept(constantFinder);
-    List<ConstantEvaluationTarget> constants =
-        constantFinder.constantsToCompute;
-    //
-    // Record outputs.
-    //
-    outputs[COMPILATION_UNIT_CONSTANTS] = constants;
-    outputs[COMPILATION_UNIT_ELEMENT] = element;
-    outputs[RESOLVED_UNIT1] = unit;
-    outputs[CREATED_RESOLVED_UNIT1] = true;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the given
-   * [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{
-      PARSED_UNIT_INPUT_NAME: PARSED_UNIT.of(unit.unit, flushOnAccess: true),
-      LINE_INFO_INPUT_NAME: LINE_INFO.of(unit.unit)
-    };
-  }
-
-  /**
-   * Create a [BuildCompilationUnitElementTask] based on the given [target] in
-   * the given [context].
-   */
-  static BuildCompilationUnitElementTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new BuildCompilationUnitElementTask(context, target);
-  }
-}
-
-/**
- * A task that builds imports and export directive elements for a library.
- */
-class BuildDirectiveElementsTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the input whose value is the defining [LIBRARY_ELEMENT1].
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The name of the input for [RESOLVED_UNIT1] of a library unit.
-   */
-  static const String UNIT_INPUT_NAME = 'UNIT_INPUT_NAME';
-
-  /**
-   * The input with a map from referenced sources to their modification times.
-   */
-  static const String SOURCES_MODIFICATION_TIME_INPUT_NAME =
-      'SOURCES_MODIFICATION_TIME_INPUT_NAME';
-
-  /**
-   * The input with a list of [LIBRARY_ELEMENT3]s of imported libraries.
-   */
-  static const String IMPORTS_LIBRARY_ELEMENT_INPUT_NAME =
-      'IMPORTS_LIBRARY_ELEMENT1_INPUT_NAME';
-
-  /**
-   * The input with a list of [LIBRARY_ELEMENT3]s of exported libraries.
-   */
-  static const String EXPORTS_LIBRARY_ELEMENT_INPUT_NAME =
-      'EXPORTS_LIBRARY_ELEMENT_INPUT_NAME';
-
-  /**
-   * The input with a list of [SOURCE_KIND]s of imported libraries.
-   */
-  static const String IMPORTS_SOURCE_KIND_INPUT_NAME =
-      'IMPORTS_SOURCE_KIND_INPUT_NAME';
-
-  /**
-   * The input with a list of [SOURCE_KIND]s of exported libraries.
-   */
-  static const String EXPORTS_SOURCE_KIND_INPUT_NAME =
-      'EXPORTS_SOURCE_KIND_INPUT_NAME';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'BuildDirectiveElementsTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[LIBRARY_ELEMENT2, BUILD_DIRECTIVES_ERRORS]);
-
-  BuildDirectiveElementsTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    LibraryElementImpl libraryElement = getRequiredInput(LIBRARY_INPUT);
-    CompilationUnit libraryUnit = getRequiredInput(UNIT_INPUT_NAME);
-    Map<Source, int> sourceModificationTimeMap =
-        getRequiredInput(SOURCES_MODIFICATION_TIME_INPUT_NAME);
-    Map<Source, LibraryElement> importLibraryMap =
-        getRequiredInput(IMPORTS_LIBRARY_ELEMENT_INPUT_NAME);
-    Map<Source, LibraryElement> exportLibraryMap =
-        getRequiredInput(EXPORTS_LIBRARY_ELEMENT_INPUT_NAME);
-    Map<Source, SourceKind> importSourceKindMap =
-        getRequiredInput(IMPORTS_SOURCE_KIND_INPUT_NAME);
-    Map<Source, SourceKind> exportSourceKindMap =
-        getRequiredInput(EXPORTS_SOURCE_KIND_INPUT_NAME);
-    //
-    // Try to get the existing LibraryElement.
-    //
-    LibraryElement element;
-    {
-      InternalAnalysisContext internalContext =
-          context as InternalAnalysisContext;
-      AnalysisCache analysisCache = internalContext.analysisCache;
-      CacheEntry cacheEntry = internalContext.getCacheEntry(target);
-      element = analysisCache.getValue(target, LIBRARY_ELEMENT2);
-      if (element == null &&
-          internalContext.aboutToComputeResult(cacheEntry, LIBRARY_ELEMENT2)) {
-        element = analysisCache.getValue(target, LIBRARY_ELEMENT2);
-      }
-    }
-    //
-    // Build or reuse the directive elements.
-    //
-    List<AnalysisError> errors;
-    if (element == null) {
-      DirectiveElementBuilder builder = new DirectiveElementBuilder(
-          context,
-          libraryElement,
-          sourceModificationTimeMap,
-          importLibraryMap,
-          importSourceKindMap,
-          exportLibraryMap,
-          exportSourceKindMap);
-      libraryUnit.accept(builder);
-      // See the commentary in the computation of the LIBRARY_CYCLE result
-      // for details on library cycle invalidation.
-      libraryElement.invalidateLibraryCycles();
-      errors = builder.errors;
-    } else {
-      DirectiveResolver resolver = new DirectiveResolver(
-          sourceModificationTimeMap, importSourceKindMap, exportSourceKindMap);
-      libraryUnit.accept(resolver);
-      errors = resolver.errors;
-    }
-    //
-    // Record outputs.
-    //
-    outputs[LIBRARY_ELEMENT2] = libraryElement;
-    outputs[BUILD_DIRECTIVES_ERRORS] = errors;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given library [libSource].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT1.of(source),
-      UNIT_INPUT_NAME:
-          RESOLVED_UNIT1.of(new LibrarySpecificUnit(source, source)),
-      SOURCES_MODIFICATION_TIME_INPUT_NAME:
-          REFERENCED_SOURCES.of(source).toMapOf(MODIFICATION_TIME),
-      IMPORTS_LIBRARY_ELEMENT_INPUT_NAME:
-          IMPORTED_LIBRARIES.of(source).toMapOf(LIBRARY_ELEMENT1),
-      EXPORTS_LIBRARY_ELEMENT_INPUT_NAME:
-          EXPORTED_LIBRARIES.of(source).toMapOf(LIBRARY_ELEMENT1),
-      IMPORTS_SOURCE_KIND_INPUT_NAME:
-          IMPORTED_LIBRARIES.of(source).toMapOf(SOURCE_KIND),
-      EXPORTS_SOURCE_KIND_INPUT_NAME:
-          EXPORTED_LIBRARIES.of(source).toMapOf(SOURCE_KIND)
-    };
-  }
-
-  /**
-   * Create a [BuildDirectiveElementsTask] based on the given [target] in
-   * the given [context].
-   */
-  static BuildDirectiveElementsTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new BuildDirectiveElementsTask(context, target);
-  }
-}
-
-/**
- * A task that builds the elements representing the members of enum
- * declarations.
- */
-class BuildEnumMemberElementsTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [TYPE_PROVIDER] input.
-   */
-  static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
-  /**
-   * The name of the [RESOLVED_UNIT1] input.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'BuildEnumMemberElementsTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[CREATED_RESOLVED_UNIT3, RESOLVED_UNIT3]);
-
-  BuildEnumMemberElementsTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    //
-    // Build the enum members if they have not already been created.
-    //
-    EnumDeclaration findFirstEnum() {
-      NodeList<CompilationUnitMember> members = unit.declarations;
-      int length = members.length;
-      for (int i = 0; i < length; i++) {
-        CompilationUnitMember member = members[i];
-        if (member is EnumDeclaration) {
-          return member;
-        }
-      }
-      return null;
-    }
-
-    EnumDeclaration firstEnum = findFirstEnum();
-    if (firstEnum != null &&
-        resolutionMap
-            .elementDeclaredByEnumDeclaration(firstEnum)
-            .accessors
-            .isEmpty) {
-      EnumMemberBuilder builder = new EnumMemberBuilder(typeProvider);
-      unit.accept(builder);
-    }
-    //
-    // Record outputs.
-    //
-    outputs[CREATED_RESOLVED_UNIT3] = true;
-    outputs[RESOLVED_UNIT3] = unit;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{
-      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
-      UNIT_INPUT: RESOLVED_UNIT2.of(unit)
-    };
-  }
-
-  /**
-   * Create a [BuildEnumMemberElementsTask] based on the given [target] in
-   * the given [context].
-   */
-  static BuildEnumMemberElementsTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new BuildEnumMemberElementsTask(context, target);
-  }
-}
-
-/**
- * A task that builds [EXPORT_NAMESPACE] and [LIBRARY_ELEMENT4] for a library.
- */
-class BuildExportNamespaceTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the input for [LIBRARY_ELEMENT3] of a library.
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'BuildExportNamespaceTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[LIBRARY_ELEMENT4]);
-
-  BuildExportNamespaceTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    LibraryElementImpl library = getRequiredInput(LIBRARY_INPUT);
-    //
-    // Compute export namespace.
-    //
-    library.exportNamespace = null;
-    NamespaceBuilder builder = new NamespaceBuilder();
-    Namespace namespace = builder.createExportNamespaceForLibrary(library);
-    library.exportNamespace = namespace;
-    //
-    // Update entry point.
-    //
-    if (library.entryPoint == null) {
-      Iterable<Element> exportedElements = namespace.definedNames.values;
-      library.entryPoint = exportedElements.firstWhere(
-          (element) => element is FunctionElement && element.isEntryPoint,
-          orElse: () => null);
-    }
-    //
-    // Record outputs.
-    //
-    outputs[LIBRARY_ELEMENT4] = library;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given library [libSource].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT3.of(source),
-      'exportsLibraryPublicNamespace':
-          EXPORT_SOURCE_CLOSURE.of(source).toMapOf(LIBRARY_ELEMENT3)
-    };
-  }
-
-  /**
-   * Create a [BuildExportNamespaceTask] based on the given [target] in
-   * the given [context].
-   */
-  static BuildExportNamespaceTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new BuildExportNamespaceTask(context, target);
-  }
-}
-
-/**
- * A task that builds a library element for a Dart library.
- */
-class BuildLibraryElementTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the input whose value is the defining [RESOLVED_UNIT1].
-   */
-  static const String DEFINING_UNIT_INPUT = 'DEFINING_UNIT_INPUT';
-
-  /**
-   * The name of the input whose value is a list of built [RESOLVED_UNIT1]s
-   * of the parts sourced by a library.
-   */
-  static const String PARTS_UNIT_INPUT = 'PARTS_UNIT_INPUT';
-
-  /**
-   * The name of the input whose value is the modification time of the source.
-   */
-  static const String MODIFICATION_TIME_INPUT = 'MODIFICATION_TIME_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'BuildLibraryElementTask', createTask, buildInputs, <ResultDescriptor>[
-    BUILD_LIBRARY_ERRORS,
-    LIBRARY_ELEMENT1,
-    IS_LAUNCHABLE
-  ]);
-
-  /**
-   * The constant used as an unknown common library name in parts.
-   */
-  static const String _UNKNOWN_LIBRARY_NAME = 'unknown-library-name';
-
-  /**
-   * Initialize a newly created task to build a library element for the given
-   * [target] in the given [context].
-   */
-  BuildLibraryElementTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    List<AnalysisError> errors = <AnalysisError>[];
-    //
-    // Prepare inputs.
-    //
-    Source librarySource = getRequiredSource();
-    CompilationUnit definingCompilationUnit =
-        getRequiredInput(DEFINING_UNIT_INPUT);
-    List<CompilationUnit> partUnits = getRequiredInput(PARTS_UNIT_INPUT);
-    int modificationTime = getRequiredInput(MODIFICATION_TIME_INPUT);
-    //
-    // Process inputs.
-    //
-    CompilationUnitElementImpl definingCompilationUnitElement =
-        definingCompilationUnit.declaredElement;
-    Map<Source, CompilationUnit> partUnitMap =
-        new HashMap<Source, CompilationUnit>();
-    int partLength = partUnits.length;
-    for (int i = 0; i < partLength; i++) {
-      CompilationUnit partUnit = partUnits[i];
-      Source partSource =
-          resolutionMap.elementDeclaredByCompilationUnit(partUnit).source;
-      partUnitMap[partSource] = partUnit;
-    }
-    //
-    // Update "part" directives.
-    //
-    LibraryIdentifier libraryNameNode = null;
-    String partsLibraryName = _UNKNOWN_LIBRARY_NAME;
-    Set<Source> seenPartSources = new Set<Source>();
-    FunctionElement entryPoint =
-        _findEntryPoint(definingCompilationUnitElement);
-    List<Directive> directivesToResolve = <Directive>[];
-    List<CompilationUnitElementImpl> sourcedCompilationUnits =
-        <CompilationUnitElementImpl>[];
-    NodeList<Directive> directives = definingCompilationUnit.directives;
-    int directiveLength = directives.length;
-    for (int i = 0; i < directiveLength; i++) {
-      Directive directive = directives[i];
-      if (directive is LibraryDirective) {
-        libraryNameNode = directive.name;
-        directivesToResolve.add(directive);
-      } else if (directive is PartDirective) {
-        StringLiteral partUri = directive.uri;
-        Source partSource = directive.uriSource;
-        CompilationUnit partUnit = partUnitMap[partSource];
-        if (partUnit != null) {
-          CompilationUnitElementImpl partElement = partUnit.declaredElement;
-          partElement.uriOffset = partUri.offset;
-          partElement.uriEnd = partUri.end;
-          partElement.uri = directive.uriContent;
-          //
-          // Validate that the part source is unique in the library.
-          //
-          if (!seenPartSources.add(partSource)) {
-            errors.add(new AnalysisError(
-                librarySource,
-                partUri.offset,
-                partUri.length,
-                CompileTimeErrorCode.DUPLICATE_PART,
-                [partSource.uri]));
-          }
-          //
-          // Validate that the part contains a part-of directive with the same
-          // name as the library.
-          //
-          if (context.exists(partSource)) {
-            _NameOrSource nameOrSource = _getPartLibraryNameOrUri(
-                context, partSource, partUnit, directivesToResolve);
-            if (nameOrSource == null) {
-              errors.add(new AnalysisError(
-                  librarySource,
-                  partUri.offset,
-                  partUri.length,
-                  CompileTimeErrorCode.PART_OF_NON_PART,
-                  [partUri.toSource()]));
-            } else {
-              String name = nameOrSource.name;
-              if (name != null) {
-                if (libraryNameNode == null) {
-                  if (partsLibraryName == _UNKNOWN_LIBRARY_NAME) {
-                    partsLibraryName = name;
-                  } else if (partsLibraryName != name) {
-                    partsLibraryName = null;
-                  }
-                } else if (libraryNameNode.name != name) {
-                  errors.add(new AnalysisError(
-                      librarySource,
-                      partUri.offset,
-                      partUri.length,
-                      StaticWarningCode.PART_OF_DIFFERENT_LIBRARY,
-                      [libraryNameNode.name, name]));
-                }
-              } else {
-                Source source = nameOrSource.source;
-                if (source != librarySource) {
-                  errors.add(new AnalysisError(
-                      librarySource,
-                      partUri.offset,
-                      partUri.length,
-                      StaticWarningCode.PART_OF_DIFFERENT_LIBRARY,
-                      [librarySource.uri.toString(), source.uri.toString()]));
-                }
-              }
-            }
-          }
-          if (entryPoint == null) {
-            entryPoint = _findEntryPoint(partElement);
-          }
-          directive.element = partElement;
-          sourcedCompilationUnits.add(partElement);
-        }
-      }
-    }
-    // TODO(brianwilkerson) Report the error
-    // ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART
-    //
-    // Create and populate the library element.
-    //
-    AnalysisContext owningContext = context;
-    if (context is InternalAnalysisContext) {
-      InternalAnalysisContext internalContext = context;
-      owningContext = internalContext.getContextFor(librarySource);
-    }
-    //
-    // Try to get the existing LibraryElement.
-    //
-    LibraryElementImpl libraryElement;
-    {
-      InternalAnalysisContext internalContext =
-          context as InternalAnalysisContext;
-      AnalysisCache analysisCache = internalContext.analysisCache;
-      CacheEntry cacheEntry = internalContext.getCacheEntry(target);
-      libraryElement = analysisCache.getValue(target, LIBRARY_ELEMENT1)
-          as LibraryElementImpl;
-      if (libraryElement == null &&
-          internalContext.aboutToComputeResult(cacheEntry, LIBRARY_ELEMENT1)) {
-        libraryElement = analysisCache.getValue(target, LIBRARY_ELEMENT1)
-            as LibraryElementImpl;
-      }
-    }
-    //
-    // Create a new LibraryElement.
-    //
-    if (libraryElement == null) {
-      libraryElement =
-          new LibraryElementImpl.forNode(owningContext, null, libraryNameNode);
-      libraryElement.isSynthetic = modificationTime < 0;
-      libraryElement.definingCompilationUnit = definingCompilationUnitElement;
-      libraryElement.entryPoint = entryPoint;
-      libraryElement.parts = sourcedCompilationUnits;
-      libraryElement.hasExtUri = _hasExtUri(definingCompilationUnit);
-      BuildLibraryElementUtils.patchTopLevelAccessors(libraryElement);
-      // set the library documentation to the docs associated with the first
-      // directive in the compilation unit.
-      if (definingCompilationUnit.directives.isNotEmpty) {
-        setElementDocumentationComment(
-            libraryElement, definingCompilationUnit.directives.first);
-      }
-    }
-    //
-    // Resolve the relevant directives to the library element.
-    //
-    // TODO(brianwilkerson) This updates the state of the AST structures but
-    // does not associate a new result with it.
-    //
-    int length = directivesToResolve.length;
-    for (int i = 0; i < length; i++) {
-      Directive directive = directivesToResolve[i];
-      directive.element = libraryElement;
-    }
-    //
-    // Record outputs.
-    //
-    outputs[BUILD_LIBRARY_ERRORS] = errors;
-    outputs[LIBRARY_ELEMENT1] = libraryElement;
-    outputs[IS_LAUNCHABLE] = entryPoint != null;
-  }
-
-  /**
-   * Return the top-level [FunctionElement] entry point, or `null` if the given
-   * [element] does not define an entry point.
-   */
-  FunctionElement _findEntryPoint(CompilationUnitElementImpl element) {
-    List<FunctionElement> functions = element.functions;
-    int length = functions.length;
-    for (int i = 0; i < length; i++) {
-      FunctionElement function = functions[i];
-      if (function.isEntryPoint) {
-        return function;
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Return the name of the library that the given part is declared to be a
-   * part of, or `null` if the part does not contain a part-of directive.
-   */
-  _NameOrSource _getPartLibraryNameOrUri(
-      AnalysisContext context,
-      Source partSource,
-      CompilationUnit partUnit,
-      List<Directive> directivesToResolve) {
-    NodeList<Directive> directives = partUnit.directives;
-    int length = directives.length;
-    for (int i = 0; i < length; i++) {
-      Directive directive = directives[i];
-      if (directive is PartOfDirective) {
-        directivesToResolve.add(directive);
-        LibraryIdentifier libraryName = directive.libraryName;
-        if (libraryName != null) {
-          return new _NameOrSource(libraryName.name, null);
-        }
-        String uri = directive.uri?.stringValue;
-        if (uri != null) {
-          Source librarySource =
-              context.sourceFactory.resolveUri(partSource, uri);
-          if (librarySource != null) {
-            return new _NameOrSource(null, librarySource);
-          }
-        }
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Return `true` if the given compilation [unit] contains at least one
-   * import directive with a `dart-ext:` URI.
-   */
-  bool _hasExtUri(CompilationUnit unit) {
-    NodeList<Directive> directives = unit.directives;
-    int length = directives.length;
-    for (int i = 0; i < length; i++) {
-      Directive directive = directives[i];
-      if (directive is ImportDirective) {
-        if (DartUriResolver.isDartExtUri(directive.uriContent)) {
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the given
-   * [libSource].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
-      DEFINING_UNIT_INPUT:
-          RESOLVED_UNIT1.of(new LibrarySpecificUnit(source, source)),
-      PARTS_UNIT_INPUT: INCLUDED_PARTS.of(source).toList((Source unit) {
-        return RESOLVED_UNIT1.of(new LibrarySpecificUnit(source, unit));
-      }),
-      MODIFICATION_TIME_INPUT: MODIFICATION_TIME.of(source)
-    };
-  }
-
-  /**
-   * Create a [BuildLibraryElementTask] based on the given [target] in the
-   * given [context].
-   */
-  static BuildLibraryElementTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new BuildLibraryElementTask(context, target);
-  }
-}
-
-/**
- * A task that builds [PUBLIC_NAMESPACE] for a library.
- */
-class BuildPublicNamespaceTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the input for [LIBRARY_ELEMENT2] of a library.
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'BuildPublicNamespaceTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[LIBRARY_ELEMENT3]);
-
-  BuildPublicNamespaceTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    LibraryElementImpl library = getRequiredInput(LIBRARY_INPUT);
-    NamespaceBuilder builder = new NamespaceBuilder();
-    library.publicNamespace = builder.createPublicNamespaceForLibrary(library);
-    outputs[LIBRARY_ELEMENT3] = library;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given library [libSource].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{LIBRARY_INPUT: LIBRARY_ELEMENT2.of(source)};
-  }
-
-  /**
-   * Create a [BuildPublicNamespaceTask] based on the given [target] in
-   * the given [context].
-   */
-  static BuildPublicNamespaceTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new BuildPublicNamespaceTask(context, target);
-  }
-}
-
-/**
- * A task that builds [EXPORT_SOURCE_CLOSURE] of a library.
- */
-class BuildSourceExportClosureTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the export closure.
-   */
-  static const String EXPORT_INPUT = 'EXPORT_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'BuildSourceExportClosureTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[EXPORT_SOURCE_CLOSURE]);
-
-  BuildSourceExportClosureTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    List<Source> exportClosure = getRequiredInput(EXPORT_INPUT);
-    //
-    // Record output.
-    //
-    outputs[EXPORT_SOURCE_CLOSURE] = exportClosure;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given library [libSource].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
-      EXPORT_INPUT: new _ExportSourceClosureTaskInput(source, LIBRARY_ELEMENT2)
-    };
-  }
-
-  /**
-   * Create a [BuildSourceExportClosureTask] based on the given [target] in
-   * the given [context].
-   */
-  static BuildSourceExportClosureTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new BuildSourceExportClosureTask(context, target);
-  }
-}
-
-/**
- * A task that builds [TYPE_PROVIDER] for a context.
- */
-class BuildTypeProviderTask extends SourceBasedAnalysisTask {
-  /**
-   * The [PUBLIC_NAMESPACE] input of the `dart:core` library.
-   */
-  static const String CORE_INPUT = 'CORE_INPUT';
-
-  /**
-   * The [PUBLIC_NAMESPACE] input of the `dart:async` library.
-   */
-  static const String ASYNC_INPUT = 'ASYNC_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'BuildTypeProviderTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[TYPE_PROVIDER]);
-
-  BuildTypeProviderTask(
-      InternalAnalysisContext context, AnalysisContextTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    LibraryElement coreLibrary = getRequiredInput(CORE_INPUT);
-    LibraryElement asyncLibrary = getOptionalInput(ASYNC_INPUT);
-    Namespace coreNamespace = coreLibrary.publicNamespace;
-    Namespace asyncNamespace = asyncLibrary.publicNamespace;
-    //
-    // Record outputs.
-    //
-    TypeProvider typeProvider =
-        new TypeProviderImpl.forNamespaces(coreNamespace, asyncNamespace);
-    (context as InternalAnalysisContext).typeProvider = typeProvider;
-    outputs[TYPE_PROVIDER] = typeProvider;
-  }
-
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    AnalysisContextTarget contextTarget = target;
-    SourceFactory sourceFactory = contextTarget.context.sourceFactory;
-    Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE);
-    Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
-    if (asyncSource == null) {
-      return <String, TaskInput>{CORE_INPUT: LIBRARY_ELEMENT3.of(coreSource)};
-    }
-    return <String, TaskInput>{
-      CORE_INPUT: LIBRARY_ELEMENT3.of(coreSource),
-      ASYNC_INPUT: LIBRARY_ELEMENT3.of(asyncSource)
-    };
-  }
-
-  /**
-   * Create a [BuildTypeProviderTask] based on the given [context].
-   */
-  static BuildTypeProviderTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new BuildTypeProviderTask(context, target);
-  }
-}
-
-/**
- * A task that computes [CONSTANT_DEPENDENCIES] for a constant.
- */
-class ComputeConstantDependenciesTask extends ConstantEvaluationAnalysisTask {
-  /**
-   * The name of the [TYPE_PROVIDER] input.
-   */
-  static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ComputeConstantDependenciesTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[CONSTANT_DEPENDENCIES]);
-
-  ComputeConstantDependenciesTask(
-      InternalAnalysisContext context, ConstantEvaluationTarget constant)
-      : super(context, constant);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    ConstantEvaluationTarget constant = target;
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-    //
-    // Compute dependencies.
-    //
-    List<ConstantEvaluationTarget> dependencies = <ConstantEvaluationTarget>[];
-    new ConstantEvaluationEngine(typeProvider, context.declaredVariables,
-            typeSystem: context.typeSystem)
-        .computeDependencies(constant, dependencies.add);
-    //
-    // Record outputs.
-    //
-    outputs[CONSTANT_DEPENDENCIES] = dependencies;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    return <String, TaskInput>{
-      'constantExpressionResolved': CONSTANT_EXPRESSION_RESOLVED.of(target),
-      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
-    };
-  }
-
-  /**
-   * Create a [ComputeConstantDependenciesTask] based on the given [target] in
-   * the given [context].
-   */
-  static ComputeConstantDependenciesTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ComputeConstantDependenciesTask(context, target);
-  }
-}
-
-/**
- * A task that computes the value of a constant ([CONSTANT_VALUE]) and
- * stores it in the element model.
- */
-class ComputeConstantValueTask extends ConstantEvaluationAnalysisTask {
-  /**
-   * The name of the input which ensures that dependent constants are evaluated
-   * before the target.
-   */
-  static const String DEPENDENCIES_INPUT = 'DEPENDENCIES_INPUT';
-
-  /**
-   * The name of the [TYPE_PROVIDER] input.
-   */
-  static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ComputeConstantValueTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[CONSTANT_VALUE]);
-
-  ComputeConstantValueTask(
-      InternalAnalysisContext context, ConstantEvaluationTarget constant)
-      : super(context, constant);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  bool get handlesDependencyCycles => true;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    // Note: DEPENDENCIES_INPUT is not needed.  It is merely a bookkeeping
-    // dependency to ensure that the constants that this constant depends on
-    // are computed first.
-    ConstantEvaluationTarget constant = target;
-    AnalysisContext context = constant.context;
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-    //
-    // Compute the value of the constant, or report an error if there was a
-    // cycle.
-    //
-    ConstantEvaluationEngine constantEvaluationEngine =
-        new ConstantEvaluationEngine(typeProvider, context.declaredVariables,
-            typeSystem: context.typeSystem);
-    if (dependencyCycle == null) {
-      constantEvaluationEngine.computeConstantValue(constant);
-    } else {
-      List<ConstantEvaluationTarget> constantsInCycle =
-          <ConstantEvaluationTarget>[];
-      int length = dependencyCycle.length;
-      for (int i = 0; i < length; i++) {
-        WorkItem workItem = dependencyCycle[i];
-        if (workItem.descriptor == DESCRIPTOR) {
-          AnalysisTarget target = workItem.target;
-          constantsInCycle.add(target);
-          if (target is ConstructorElementImpl) {
-            target.isCycleFree = false;
-          }
-        }
-      }
-      assert(constantsInCycle.isNotEmpty);
-      constantEvaluationEngine.generateCycleError(constantsInCycle, constant);
-    }
-    //
-    // Record outputs.
-    //
-    outputs[CONSTANT_VALUE] = constant;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the given
-   * [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    ConstantEvaluationTarget evaluationTarget = target;
-    return <String, TaskInput>{
-      DEPENDENCIES_INPUT:
-          CONSTANT_DEPENDENCIES.of(evaluationTarget).toListOf(CONSTANT_VALUE),
-      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
-    };
-  }
-
-  /**
-   * Create a [ComputeConstantValueTask] based on the given [target] in the
-   * given [context].
-   */
-  static ComputeConstantValueTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ComputeConstantValueTask(context, target);
-  }
-}
-
-/**
- * A task that computes the [INFERABLE_STATIC_VARIABLE_DEPENDENCIES] for a
- * static variable whose type should be inferred.
- */
-class ComputeInferableStaticVariableDependenciesTask
-    extends InferStaticVariableTask {
-  /**
-   * The name of the [RESOLVED_UNIT7] input.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ComputeInferableStaticVariableDependenciesTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[INFERABLE_STATIC_VARIABLE_DEPENDENCIES]);
-
-  ComputeInferableStaticVariableDependenciesTask(
-      InternalAnalysisContext context, VariableElement variable)
-      : super(context, variable);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    //
-    // Compute dependencies.
-    //
-    VariableDeclaration declaration = getDeclaration(unit);
-    VariableGatherer gatherer = new VariableGatherer(_isInferableStatic);
-    declaration.initializer.accept(gatherer);
-    //
-    // Record outputs.
-    //
-    outputs[INFERABLE_STATIC_VARIABLE_DEPENDENCIES] = gatherer.results.toList();
-  }
-
-  /**
-   * Return `true` if the given [variable] is a static variable whose type
-   * should be inferred.
-   */
-  bool _isInferableStatic(VariableElement variable) =>
-      variable.isStatic &&
-      variable.hasImplicitType &&
-      variable.initializer != null;
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    if (target is VariableElement) {
-      CompilationUnitElementImpl unit = target
-          .getAncestor((Element element) => element is CompilationUnitElement);
-      return <String, TaskInput>{
-        UNIT_INPUT: RESOLVED_UNIT7
-            .of(new LibrarySpecificUnit(unit.librarySource, unit.source))
-      };
-    }
-    throw new AnalysisException(
-        'Cannot build inputs for a ${target.runtimeType}');
-  }
-
-  /**
-   * Create a [ComputeInferableStaticVariableDependenciesTask] based on the
-   * given [target] in the given [context].
-   */
-  static ComputeInferableStaticVariableDependenciesTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ComputeInferableStaticVariableDependenciesTask(context, target);
-  }
-}
-
-/**
- * A task that computes the [LIBRARY_CYCLE] for a
- * library element.  Also computes the [LIBRARY_CYCLE_UNITS] and the
- * [LIBRARY_CYCLE_DEPENDENCIES].
- */
-class ComputeLibraryCycleTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [LIBRARY_ELEMENT2] input.
-   */
-  static const String LIBRARY_ELEMENT_INPUT = 'LIBRARY_ELEMENT_INPUT';
-
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ComputeLibraryCycleForUnitTask',
-      createTask,
-      buildInputs, <ResultDescriptor>[
-    LIBRARY_CYCLE,
-    LIBRARY_CYCLE_UNITS,
-    LIBRARY_CYCLE_DEPENDENCIES
-  ]);
-
-  ComputeLibraryCycleTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    // The computation of library cycles is necessarily non-local, since we
-    // in general have to look at all of the reachable libraries
-    // in order to find the strongly connected components.  Repeating this
-    // computation for every node would be quadratic.  The libraryCycle getter
-    // will avoid this by computing the library cycles for every reachable
-    // library and recording it in the element model.  This means that this
-    // task implicitly produces the output for many other targets.  This
-    // can't be expressed in the task model right now: instead, we just
-    // run tasks for those other targets, and they pick up the recorded
-    // version off of the element model.  Unfortunately, this means that
-    // the task model will not handle the invalidation of the recorded
-    // results for us.  Instead, we must explicitly invalidate the recorded
-    // library cycle information when we add or subtract edges from the
-    // import/export graph.  Any update that changes the
-    // import/export graph will induce a recomputation of the LIBRARY_ELEMENT2
-    // result for the changed node. This recomputation is responsible for
-    // conservatively invalidating the library cycle information recorded
-    // in the element model.  The LIBRARY_CYCLE results that have been cached
-    // by the task model are conservatively invalidated by the
-    // IMPORT_EXPORT_SOURCE_CLOSURE dependency below.  If anything reachable
-    // from a node is changed, its LIBRARY_CYCLE results will be re-computed
-    // here (possibly re-using the result from the element model if invalidation
-    // did not cause it to be erased).  In summary, task model dependencies
-    // on the import/export source closure ensure that this method will be
-    // re-run if anything reachable from this target has been invalidated,
-    // and the invalidation code (invalidateLibraryCycles) will ensure that
-    // element model results will be re-used here only if they are still valid.
-    LibraryElement library = getRequiredInput(LIBRARY_ELEMENT_INPUT);
-    if (!LibraryElementImpl.hasResolutionCapability(
-        library, LibraryResolutionCapability.resolvedTypeNames)) {
-      List<LibraryElement> component = library.libraryCycle;
-      Set<LibraryElement> filter = component.toSet();
-      Set<CompilationUnitElement> deps = new Set<CompilationUnitElement>();
-      void addLibrary(LibraryElement l) {
-        if (!filter.contains(l)) {
-          deps.addAll(l.units);
-        }
-      }
-
-      int length = component.length;
-      for (int i = 0; i < length; i++) {
-        LibraryElement library = component[i];
-        library.importedLibraries.forEach(addLibrary);
-        library.exportedLibraries.forEach(addLibrary);
-      }
-      //
-      // Record outputs.
-      //
-      LibrarySpecificUnit unitToLSU(CompilationUnitElement unit) =>
-          new LibrarySpecificUnit(unit.librarySource, unit.source);
-      outputs[LIBRARY_CYCLE] = component;
-      outputs[LIBRARY_CYCLE_UNITS] =
-          component.expand((l) => l.units).map(unitToLSU).toList();
-      outputs[LIBRARY_CYCLE_DEPENDENCIES] = deps.map(unitToLSU).toList();
-    } else {
-      outputs[LIBRARY_CYCLE] = <LibraryElement>[];
-      outputs[LIBRARY_CYCLE_UNITS] = <LibrarySpecificUnit>[];
-      outputs[LIBRARY_CYCLE_DEPENDENCIES] = <LibrarySpecificUnit>[];
-    }
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source librarySource = target;
-    return <String, TaskInput>{
-      LIBRARY_ELEMENT_INPUT: LIBRARY_ELEMENT2.of(librarySource),
-      'resolveReachableLibraries': READY_LIBRARY_ELEMENT2.of(librarySource),
-    };
-  }
-
-  /**
-   * Create a [ComputeLibraryCycleTask] based on the
-   * given [target] in the given [context].
-   */
-  static ComputeLibraryCycleTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ComputeLibraryCycleTask(context, target);
-  }
-}
-
-/**
- * A task that builds [REQUIRED_CONSTANTS] for a unit.
- */
-class ComputeRequiredConstantsTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [RESOLVED_UNIT] input.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ComputeRequiredConstantsTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[PENDING_ERRORS, REQUIRED_CONSTANTS]);
-
-  ComputeRequiredConstantsTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    Source source = getRequiredSource();
-    //
-    // Prepare inputs.
-    //
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    //
-    // Use the ErrorVerifier to compute errors.
-    //
-    RequiredConstantsComputer computer = new RequiredConstantsComputer(source);
-    unit.accept(computer);
-    List<PendingError> pendingErrors = computer.pendingErrors;
-    List<ConstantEvaluationTarget> requiredConstants =
-        computer.requiredConstants;
-    //
-    // Record outputs.
-    //
-    outputs[PENDING_ERRORS] = pendingErrors;
-    outputs[REQUIRED_CONSTANTS] = requiredConstants;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT.of(unit)};
-  }
-
-  /**
-   * Create a [ComputeRequiredConstantsTask] based on the given [target] in
-   * the given [context].
-   */
-  static ComputeRequiredConstantsTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ComputeRequiredConstantsTask(context, target);
-  }
-}
-
-/**
- * A base class for analysis tasks whose target is expected to be a
- * [ConstantEvaluationTarget].
- */
-abstract class ConstantEvaluationAnalysisTask extends AnalysisTask {
-  /**
-   * Initialize a newly created task to perform analysis within the given
-   * [context] in order to produce results for the given [constant].
-   */
-  ConstantEvaluationAnalysisTask(
-      AnalysisContext context, ConstantEvaluationTarget constant)
-      : super(context, constant);
-
-  @override
-  String get description {
-    Source source = target.source;
-    String sourceName = source == null ? '<unknown source>' : source.fullName;
-    return '${descriptor.name} for element $target in source $sourceName';
-  }
-}
-
-/**
- * Interface for [AnalysisTarget]s for which constant evaluation can be
- * performed.
- */
-abstract class ConstantEvaluationTarget extends AnalysisTarget {
-  /**
-   * Return the [AnalysisContext] which should be used to evaluate this
-   * constant.
-   */
-  AnalysisContext get context;
-
-  /**
-   * Return whether this constant is evaluated.
-   */
-  bool get isConstantEvaluated;
-}
-
-/**
- * A task that computes a list of the libraries containing the target source.
- */
-class ContainingLibrariesTask extends SourceBasedAnalysisTask {
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ContainingLibrariesTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[CONTAINING_LIBRARIES]);
-
-  ContainingLibrariesTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    // TODO(brianwilkerson) This value can change as new libraries are analyzed
-    // so we need some way of making sure that this result is removed from the
-    // cache appropriately.
-    Source source = getRequiredSource();
-    outputs[CONTAINING_LIBRARIES] = context.getLibrariesContaining(source);
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    return <String, TaskInput>{};
-  }
-
-  /**
-   * Create a [ContainingLibrariesTask] based on the given [target] in the given
-   * [context].
-   */
-  static ContainingLibrariesTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ContainingLibrariesTask(context, target);
-  }
-}
-
-/**
- * A task that merges all of the errors for a single source into a single list
- * of errors.
- */
-class DartErrorsTask extends SourceBasedAnalysisTask {
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('DartErrorsTask',
-      createTask, buildInputs, <ResultDescriptor>[DART_ERRORS]);
-
-  /**
-   * The name of the [IGNORE_INFO_INPUT] input.
-   */
-  static const String IGNORE_INFO_INPUT = 'IGNORE_INFO_INPUT';
-
-  /**
-   * The name of the [LINE_INFO_INPUT] input.
-   */
-  static const String LINE_INFO_INPUT = 'LINE_INFO_INPUT';
-
-  DartErrorsTask(InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    List<List<AnalysisError>> errorLists = <List<AnalysisError>>[];
-    //
-    // Prepare inputs.
-    //
-    EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin;
-    List<ResultDescriptor> errorsForSource = enginePlugin.dartErrorsForSource;
-    int sourceLength = errorsForSource.length;
-    for (int i = 0; i < sourceLength; i++) {
-      ResultDescriptor result = errorsForSource[i];
-      String inputName = result.name + '_input';
-      errorLists.add(getRequiredInput(inputName));
-    }
-    List<ResultDescriptor> errorsForUnit = enginePlugin.dartErrorsForUnit;
-    int unitLength = errorsForUnit.length;
-    for (int i = 0; i < unitLength; i++) {
-      ResultDescriptor result = errorsForUnit[i];
-      String inputName = result.name + '_input';
-      Map<Source, List<AnalysisError>> errorMap = getRequiredInput(inputName);
-      for (List<AnalysisError> errors in errorMap.values) {
-        errorLists.add(errors);
-      }
-    }
-
-    //
-    // Filter ignored errors.
-    //
-    List<AnalysisError> errors =
-        _filterIgnores(AnalysisError.mergeLists(errorLists));
-
-    //
-    // Record outputs.
-    //
-    outputs[DART_ERRORS] = errors;
-  }
-
-  List<AnalysisError> _filterIgnores(List<AnalysisError> errors) {
-    if (errors.isEmpty) {
-      return errors;
-    }
-
-    IgnoreInfo ignoreInfo = getRequiredInput(IGNORE_INFO_INPUT);
-    if (!ignoreInfo.hasIgnores) {
-      return errors;
-    }
-
-    LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT);
-
-    return filterIgnored(errors, ignoreInfo, lineInfo);
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    Map<String, TaskInput> inputs = <String, TaskInput>{};
-    inputs[LINE_INFO_INPUT] = LINE_INFO.of(source);
-    inputs[IGNORE_INFO_INPUT] = IGNORE_INFO.of(source);
-    EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin;
-    // for Source
-    List<ListResultDescriptor<AnalysisError>> errorsForSource =
-        enginePlugin.dartErrorsForSource;
-    int sourceLength = errorsForSource.length;
-    for (int i = 0; i < sourceLength; i++) {
-      ListResultDescriptor<AnalysisError> result = errorsForSource[i];
-      String inputName = result.name + '_input';
-      inputs[inputName] = result.of(source);
-    }
-    // for LibrarySpecificUnit
-    List<ListResultDescriptor<AnalysisError>> errorsForUnit =
-        enginePlugin.dartErrorsForUnit;
-    int unitLength = errorsForUnit.length;
-    for (int i = 0; i < unitLength; i++) {
-      ListResultDescriptor<AnalysisError> result = errorsForUnit[i];
-      String inputName = result.name + '_input';
-      inputs[inputName] =
-          CONTAINING_LIBRARIES.of(source).toMap((Source library) {
-        LibrarySpecificUnit unit = new LibrarySpecificUnit(library, source);
-        return result.of(unit);
-      });
-    }
-    return inputs;
-  }
-
-  /**
-   * Create a [DartErrorsTask] based on the given [target] in the given
-   * [context].
-   */
-  static DartErrorsTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new DartErrorsTask(context, target);
-  }
-
-  /**
-   * Return a new list with items from [errors] which are not filtered out by
-   * the [ignoreInfo].
-   */
-  static List<AnalysisError> filterIgnored(
-      List<AnalysisError> errors, IgnoreInfo ignoreInfo, LineInfo lineInfo) {
-    if (errors.isEmpty || !ignoreInfo.hasIgnores) {
-      return errors;
-    }
-
-    bool isIgnored(AnalysisError error) {
-      int errorLine = lineInfo.getLocation(error.offset).lineNumber;
-      String errorCode = error.errorCode.name.toLowerCase();
-      return ignoreInfo.ignoredAt(errorCode, errorLine);
-    }
-
-    return errors.where((AnalysisError e) => !isIgnored(e)).toList();
-  }
-}
-
-/**
- * A task that builds [RESOLVED_UNIT12] for a unit.
- */
-class EvaluateUnitConstantsTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [RESOLVED_UNIT11] input.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  /**
-   * The name of the [CONSTANT_VALUE] input.
-   */
-  static const String CONSTANT_VALUES = 'CONSTANT_VALUES';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'EvaluateUnitConstantsTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[CREATED_RESOLVED_UNIT12, RESOLVED_UNIT12]);
-
-  EvaluateUnitConstantsTask(AnalysisContext context, LibrarySpecificUnit target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    // No actual work needs to be performed; the task manager will ensure that
-    // all constants are evaluated before this method is called.
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    outputs[RESOLVED_UNIT12] = unit;
-    outputs[CREATED_RESOLVED_UNIT12] = true;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{
-      'libraryElement': LIBRARY_ELEMENT9.of(unit.library),
-      UNIT_INPUT: RESOLVED_UNIT11.of(unit),
-      CONSTANT_VALUES:
-          COMPILATION_UNIT_CONSTANTS.of(unit).toListOf(CONSTANT_VALUE),
-      'constantExpressionsDependencies':
-          CONSTANT_EXPRESSIONS_DEPENDENCIES.of(unit).toListOf(CONSTANT_VALUE)
-    };
-  }
-
-  /**
-   * Create an [EvaluateUnitConstantsTask] based on the given [target] in
-   * the given [context].
-   */
-  static EvaluateUnitConstantsTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new EvaluateUnitConstantsTask(context, target);
-  }
-}
-
-/**
- * A task that builds [USED_IMPORTED_ELEMENTS] for a unit.
- */
-class GatherUsedImportedElementsTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [RESOLVED_UNIT11] input.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'GatherUsedImportedElementsTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[USED_IMPORTED_ELEMENTS]);
-
-  GatherUsedImportedElementsTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    CompilationUnitElement unitElement = unit.declaredElement;
-    LibraryElement libraryElement = unitElement.library;
-    //
-    // Prepare used imported elements.
-    //
-    GatherUsedImportedElementsVisitor visitor =
-        new GatherUsedImportedElementsVisitor(libraryElement);
-    unit.accept(visitor);
-    //
-    // Record outputs.
-    //
-    outputs[USED_IMPORTED_ELEMENTS] = visitor.usedElements;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT11.of(unit)};
-  }
-
-  /**
-   * Create a [GatherUsedImportedElementsTask] based on the given [target] in
-   * the given [context].
-   */
-  static GatherUsedImportedElementsTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new GatherUsedImportedElementsTask(context, target);
-  }
-}
-
-/**
- * A task that builds [USED_LOCAL_ELEMENTS] for a unit.
- */
-class GatherUsedLocalElementsTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [RESOLVED_UNIT11] input.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'GatherUsedLocalElementsTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[USED_LOCAL_ELEMENTS]);
-
-  GatherUsedLocalElementsTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    CompilationUnitElement unitElement = unit.declaredElement;
-    LibraryElement libraryElement = unitElement.library;
-    //
-    // Prepare used local elements.
-    //
-    GatherUsedLocalElementsVisitor visitor =
-        new GatherUsedLocalElementsVisitor(libraryElement);
-    unit.accept(visitor);
-    //
-    // Record outputs.
-    //
-    outputs[USED_LOCAL_ELEMENTS] = visitor.usedElements;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT11.of(unit)};
-  }
-
-  /**
-   * Create a [GatherUsedLocalElementsTask] based on the given [target] in
-   * the given [context].
-   */
-  static GatherUsedLocalElementsTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new GatherUsedLocalElementsTask(context, target);
-  }
-}
-
-/**
- * A task that generates [HINTS] for a unit.
- */
-class GenerateHintsTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [RESOLVED_UNIT11] input.
-   */
-  static const String RESOLVED_UNIT_INPUT = 'RESOLVED_UNIT';
-
-  /**
-   * The name of a list of [USED_LOCAL_ELEMENTS] for each library unit input.
-   */
-  static const String USED_LOCAL_ELEMENTS_INPUT = 'USED_LOCAL_ELEMENTS';
-
-  /**
-   * The name of a list of [USED_IMPORTED_ELEMENTS] for each library unit input.
-   */
-  static const String USED_IMPORTED_ELEMENTS_INPUT = 'USED_IMPORTED_ELEMENTS';
-
-  /**
-   * The name of the [TYPE_PROVIDER] input.
-   */
-  static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'GenerateHintsTask', createTask, buildInputs, <ResultDescriptor>[HINTS]);
-
-  GenerateHintsTask(InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    AnalysisOptions analysisOptions = context.analysisOptions;
-    if (!analysisOptions.hint) {
-      outputs[HINTS] = AnalysisError.NO_ERRORS;
-      return;
-    }
-    //
-    // Prepare collectors.
-    //
-    RecordingErrorListener errorListener = new RecordingErrorListener();
-    Source source = getRequiredSource();
-    ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
-    //
-    // Prepare inputs.
-    //
-    CompilationUnit unit = getRequiredInput(RESOLVED_UNIT_INPUT);
-    List<UsedImportedElements> usedImportedElementsList =
-        getRequiredInput(USED_IMPORTED_ELEMENTS_INPUT);
-    List<UsedLocalElements> usedLocalElementsList =
-        getRequiredInput(USED_LOCAL_ELEMENTS_INPUT);
-    CompilationUnitElement unitElement = unit.declaredElement;
-    LibraryElement libraryElement = unitElement.library;
-    TypeSystem typeSystem = context.typeSystem;
-
-    //
-    // Generate errors.
-    //
-    unit.accept(new DeadCodeVerifier(
-        errorReporter, (unit as CompilationUnitImpl).isNonNullable,
-        typeSystem: typeSystem));
-    // Verify imports.
-    {
-      ImportsVerifier verifier = new ImportsVerifier();
-      verifier.addImports(unit);
-      usedImportedElementsList.forEach(verifier.removeUsedElements);
-      verifier.generateDuplicateImportHints(errorReporter);
-      verifier.generateDuplicateShownHiddenNameHints(errorReporter);
-      verifier.generateUnusedImportHints(errorReporter);
-      verifier.generateUnusedShownNameHints(errorReporter);
-    }
-    // Unused local elements.
-    {
-      UsedLocalElements usedElements =
-          new UsedLocalElements.merge(usedLocalElementsList);
-      UnusedLocalElementsVerifier visitor =
-          new UnusedLocalElementsVerifier(errorListener, usedElements);
-      unit.accept(visitor);
-    }
-    // Dart2js analysis.
-    if (analysisOptions.dart2jsHint) {
-      unit.accept(new Dart2JSVerifier(errorReporter));
-    }
-    // Dart best practices.
-    var inheritanceManager2 = new InheritanceManager2(context.typeSystem);
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-    ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
-
-    unit.accept(new BestPracticesVerifier(
-        errorReporter, typeProvider, libraryElement,
-        typeSystem: typeSystem,
-        resourceProvider: resourceProvider,
-        analysisOptions: context.analysisOptions));
-    unit.accept(new OverrideVerifier(
-      inheritanceManager2,
-      libraryElement,
-      errorReporter,
-    ));
-    // Find to-do comments.
-    new ToDoFinder(errorReporter).findIn(unit);
-    //
-    // Record outputs.
-    //
-    outputs[HINTS] = errorListener.errors;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    Source libSource = unit.library;
-    return <String, TaskInput>{
-      RESOLVED_UNIT_INPUT: RESOLVED_UNIT.of(unit),
-      USED_LOCAL_ELEMENTS_INPUT:
-          LIBRARY_SPECIFIC_UNITS.of(libSource).toListOf(USED_LOCAL_ELEMENTS),
-      USED_IMPORTED_ELEMENTS_INPUT:
-          LIBRARY_SPECIFIC_UNITS.of(libSource).toListOf(USED_IMPORTED_ELEMENTS),
-      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
-    };
-  }
-
-  /**
-   * Create a [GenerateHintsTask] based on the given [target] in
-   * the given [context].
-   */
-  static GenerateHintsTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new GenerateHintsTask(context, target);
-  }
-}
-
-/**
- * A task that generates [LINTS] for a unit.
- */
-class GenerateLintsTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [RESOLVED_UNIT] input.
-   */
-  static const String RESOLVED_UNIT_INPUT = 'RESOLVED_UNIT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'GenerateLintsTask', createTask, buildInputs, <ResultDescriptor>[LINTS]);
-
-  GenerateLintsTask(InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    AnalysisOptions analysisOptions = context.analysisOptions;
-    if (!analysisOptions.lint) {
-      outputs[LINTS] = AnalysisError.NO_ERRORS;
-      return;
-    }
-    //
-    // Prepare collectors.
-    //
-    RecordingErrorListener errorListener = new RecordingErrorListener();
-    Source source = getRequiredSource();
-    ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
-    //
-    // Prepare inputs.
-    //
-    CompilationUnit unit = getRequiredInput(RESOLVED_UNIT_INPUT);
-    //
-    // Generate lints.
-    //
-    List<AstVisitor> visitors = <AstVisitor>[];
-    bool timeVisits = analysisOptions.enableTiming;
-    List<Linter> linters = getLints(context);
-    int length = linters.length;
-    for (int i = 0; i < length; i++) {
-      Linter linter = linters[i];
-      AstVisitor visitor = linter.getVisitor();
-      if (visitor != null) {
-        linter.reporter = errorReporter;
-        if (timeVisits) {
-          visitor = new TimedAstVisitor(visitor, lintRegistry.getTimer(linter));
-        }
-        visitors.add(visitor);
-      }
-    }
-    AstVisitor visitor = new ExceptionHandlingDelegatingAstVisitor(
-        visitors, ExceptionHandlingDelegatingAstVisitor.logException);
-    unit.accept(visitor);
-    //
-    // Record outputs.
-    //
-    outputs[LINTS] = errorListener.errors;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) =>
-      <String, TaskInput>{RESOLVED_UNIT_INPUT: RESOLVED_UNIT.of(target)};
-
-  /**
-   * Create a [GenerateLintsTask] based on the given [target] in
-   * the given [context].
-   */
-  static GenerateLintsTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new GenerateLintsTask(context, target);
-  }
-}
-
-/**
- * Information about analysis `//ignore:` and `//ignore_for_file` comments
- * within a source file.
- */
-class IgnoreInfo {
-  /**
-   *  Instance shared by all cases without matches.
-   */
-  static final IgnoreInfo _EMPTY_INFO = new IgnoreInfo();
-
-  /**
-   * A regular expression for matching 'ignore' comments.  Produces matches
-   * containing 2 groups.  For example:
-   *
-   *     * ['//ignore: error_code', 'error_code']
-   *
-   * Resulting codes may be in a list ('error_code_1,error_code2').
-   */
-  static final RegExp _IGNORE_MATCHER =
-      new RegExp(r'//+[ ]*ignore:(.*)$', multiLine: true);
-
-  /**
-   * A regular expression for matching 'ignore_for_file' comments.  Produces
-   * matches containing 2 groups.  For example:
-   *
-   *     * ['//ignore_for_file: error_code', 'error_code']
-   *
-   * Resulting codes may be in a list ('error_code_1,error_code2').
-   */
-  static final RegExp _IGNORE_FOR_FILE_MATCHER =
-      new RegExp(r'//[ ]*ignore_for_file:(.*)$', multiLine: true);
-
-  final Map<int, List<String>> _ignoreMap = new HashMap<int, List<String>>();
-
-  final Set<String> _ignoreForFileSet = new HashSet<String>();
-
-  /**
-   * Whether this info object defines any ignores.
-   */
-  bool get hasIgnores => ignores.isNotEmpty || _ignoreForFileSet.isNotEmpty;
-
-  /**
-   * Iterable of error codes ignored for the whole file.
-   */
-  Iterable<String> get ignoreForFiles => _ignoreForFileSet;
-
-  /**
-   * Map of line numbers to associated ignored error codes.
-   */
-  Map<int, Iterable<String>> get ignores => _ignoreMap;
-
-  /**
-   * Ignore this [errorCode] at [line].
-   */
-  void add(int line, String errorCode) {
-    _ignoreMap.putIfAbsent(line, () => new List<String>()).add(errorCode);
-  }
-
-  /**
-   * Ignore these [errorCodes] at [line].
-   */
-  void addAll(int line, Iterable<String> errorCodes) {
-    _ignoreMap.putIfAbsent(line, () => new List<String>()).addAll(errorCodes);
-  }
-
-  /**
-   * Ignore these [errorCodes] in the whole file.
-   */
-  void addAllForFile(Iterable<String> errorCodes) {
-    _ignoreForFileSet.addAll(errorCodes);
-  }
-
-  /**
-   * Test whether this [errorCode] is ignored at the given [line].
-   */
-  bool ignoredAt(String errorCode, int line) =>
-      _ignoreForFileSet.contains(errorCode) ||
-      _ignoreMap[line]?.contains(errorCode) == true;
-
-  /**
-   * Calculate ignores for the given [content] with line [info].
-   */
-  static IgnoreInfo calculateIgnores(String content, LineInfo info) {
-    Iterable<Match> matches = _IGNORE_MATCHER.allMatches(content);
-    Iterable<Match> fileMatches = _IGNORE_FOR_FILE_MATCHER.allMatches(content);
-    if (matches.isEmpty && fileMatches.isEmpty) {
-      return _EMPTY_INFO;
-    }
-
-    IgnoreInfo ignoreInfo = new IgnoreInfo();
-    for (Match match in matches) {
-      // See _IGNORE_MATCHER for format --- note the possibility of error lists.
-      Iterable<String> codes = match
-          .group(1)
-          .split(',')
-          .map((String code) => code.trim().toLowerCase());
-      CharacterLocation location = info.getLocation(match.start);
-      int lineNumber = location.lineNumber;
-      String beforeMatch = content.substring(
-          info.getOffsetOfLine(lineNumber - 1),
-          info.getOffsetOfLine(lineNumber - 1) + location.columnNumber - 1);
-
-      if (beforeMatch.trim().isEmpty) {
-        // The comment is on its own line, so it refers to the next line.
-        ignoreInfo.addAll(lineNumber + 1, codes);
-      } else {
-        // The comment sits next to code, so it refers to its own line.
-        ignoreInfo.addAll(lineNumber, codes);
-      }
-    }
-    for (Match match in fileMatches) {
-      Iterable<String> codes = match
-          .group(1)
-          .split(',')
-          .map((String code) => code.trim().toLowerCase());
-      ignoreInfo.addAllForFile(codes);
-    }
-    return ignoreInfo;
-  }
-}
-
-/**
- * A task that ensures that all of the inferable instance members in a
- * compilation unit have had their type inferred.
- */
-class InferInstanceMembersInUnitTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [TYPE_PROVIDER] input.
-   */
-  static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
-  /**
-   * The name of the input whose value is the [RESOLVED_UNIT8] for the
-   * compilation unit.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'InferInstanceMembersInUnitTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[CREATED_RESOLVED_UNIT10, RESOLVED_UNIT10]);
-
-  /**
-   * Initialize a newly created task to build a library element for the given
-   * [unit] in the given [context].
-   */
-  InferInstanceMembersInUnitTask(
-      InternalAnalysisContext context, LibrarySpecificUnit unit)
-      : super(context, unit);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-
-    //
-    // Infer instance members.
-    //
-    var inheritance = new InheritanceManager2(context.typeSystem);
-    InstanceMemberInferrer inferrer =
-        new InstanceMemberInferrer(typeProvider, inheritance);
-    inferrer.inferCompilationUnit(unit.declaredElement);
-    //
-    // Record outputs.
-    //
-    outputs[RESOLVED_UNIT10] = unit;
-    outputs[CREATED_RESOLVED_UNIT10] = true;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the given
-   * [libSource].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{
-      UNIT_INPUT: RESOLVED_UNIT9.of(unit),
-      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
-      // In strong mode, add additional dependencies to enforce inference
-      // ordering.
-
-      // Require that field re-resolution be complete for all units in the
-      // current library cycle.
-      'orderLibraryCycleTasks':
-          LIBRARY_CYCLE_UNITS.of(unit.library).toListOf(CREATED_RESOLVED_UNIT9),
-      // Require that full inference be complete for all dependencies of the
-      // current library cycle.
-      'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES
-          .of(unit.library)
-          .toListOf(CREATED_RESOLVED_UNIT10)
-    };
-  }
-
-  /**
-   * Create a [InferInstanceMembersInUnitTask] based on the given [target] in
-   * the given [context].
-   */
-  static InferInstanceMembersInUnitTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new InferInstanceMembersInUnitTask(context, target);
-  }
-}
-
-/**
- * An abstract class that defines utility methods that are useful for tasks
- * operating on static variables.
- */
-abstract class InferStaticVariableTask extends ConstantEvaluationAnalysisTask {
-  InferStaticVariableTask(
-      InternalAnalysisContext context, VariableElement variable)
-      : super(context, variable);
-
-  /**
-   * Return the declaration of the target within the given compilation [unit].
-   * Throw an exception if the declaration cannot be found.
-   */
-  VariableDeclaration getDeclaration(CompilationUnit unit) {
-    VariableElement variable = target;
-    int offset = variable.nameOffset;
-    AstNode node = new NodeLocator2(offset).searchWithin(unit);
-    if (node == null) {
-      Source variableSource = variable.source;
-      Source unitSource =
-          resolutionMap.elementDeclaredByCompilationUnit(unit).source;
-      if (variableSource != unitSource) {
-        throw new AnalysisException(
-            "Failed to find the AST node for the variable "
-            "${variable.displayName} at $offset in $variableSource "
-            "because we were looking in $unitSource");
-      }
-      throw new AnalysisException(
-          "Failed to find the AST node for the variable "
-          "${variable.displayName} at $offset in $variableSource");
-    }
-    VariableDeclaration declaration =
-        node.thisOrAncestorOfType<VariableDeclaration>();
-    if (declaration == null || declaration.name != node) {
-      Source variableSource = variable.source;
-      Source unitSource =
-          resolutionMap.elementDeclaredByCompilationUnit(unit).source;
-      if (variableSource != unitSource) {
-        if (declaration == null) {
-          throw new AnalysisException(
-              "Failed to find the declaration of the variable "
-              "${variable.displayName} at $offset in $variableSource "
-              "because the node was not in a variable declaration "
-              "possibly because we were looking in $unitSource");
-        }
-        throw new AnalysisException(
-            "Failed to find the declaration of the variable "
-            "${variable.displayName} at $offset in $variableSource "
-            "because we were looking in $unitSource");
-      }
-      if (declaration == null) {
-        throw new AnalysisException(
-            "Failed to find the declaration of the variable "
-            "${variable.displayName} at $offset in $variableSource "
-            "because the node was not in a variable declaration");
-      }
-      throw new AnalysisException(
-          "Failed to find the declaration of the variable "
-          "${variable.displayName} at $offset in $variableSource "
-          "because the node was not the name in a variable declaration");
-    }
-    return declaration;
-  }
-}
-
-/**
- * A task that ensures that all of the inferable static variables in a
- * compilation unit have had their type inferred.
- */
-class InferStaticVariableTypesInUnitTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the input whose value is the [RESOLVED_UNIT8] for the
-   * compilation unit.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  /**
-   * The name of the [STATIC_VARIABLE_RESOLUTION_ERRORS] for all static
-   * variables in the compilation unit.
-   */
-  static const String ERRORS_LIST_INPUT = 'INFERRED_VARIABLES_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'InferStaticVariableTypesInUnitTask',
-      createTask,
-      buildInputs, <ResultDescriptor>[
-    CREATED_RESOLVED_UNIT8,
-    RESOLVED_UNIT8,
-    STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT
-  ]);
-
-  /**
-   * Initialize a newly created task to build a library element for the given
-   * [unit] in the given [context].
-   */
-  InferStaticVariableTypesInUnitTask(
-      InternalAnalysisContext context, LibrarySpecificUnit unit)
-      : super(context, unit);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    List<List<AnalysisError>> errorLists = getRequiredInput(ERRORS_LIST_INPUT);
-    //
-    // Record outputs. There is no additional work to be done at this time
-    // because the work has implicitly been done by virtue of the task model
-    // preparing all of the inputs.
-    //
-    outputs[RESOLVED_UNIT8] = unit;
-    outputs[CREATED_RESOLVED_UNIT8] = true;
-    outputs[STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT] =
-        AnalysisError.mergeLists(errorLists);
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the given
-   * [libSource].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{
-      'inferredTypes': INFERABLE_STATIC_VARIABLES_IN_UNIT
-          .of(unit)
-          .toListOf(INFERRED_STATIC_VARIABLE),
-      ERRORS_LIST_INPUT: INFERABLE_STATIC_VARIABLES_IN_UNIT
-          .of(unit)
-          .toListOf(STATIC_VARIABLE_RESOLUTION_ERRORS),
-      UNIT_INPUT: RESOLVED_UNIT7.of(unit)
-    };
-  }
-
-  /**
-   * Create a [InferStaticVariableTypesInUnitTask] based on the given [target]
-   * in the given [context].
-   */
-  static InferStaticVariableTypesInUnitTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new InferStaticVariableTypesInUnitTask(context, target);
-  }
-}
-
-/**
- * A task that computes the type of an inferable static variable and
- * stores it in the element model.
- */
-class InferStaticVariableTypeTask extends InferStaticVariableTask {
-  /**
-   * The name of the input which ensures that dependent values have their type
-   * inferred before the target.
-   */
-  static const String DEPENDENCIES_INPUT = 'DEPENDENCIES_INPUT';
-
-  /**
-   * The name of the [TYPE_PROVIDER] input.
-   */
-  static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
-  /**
-   * The name of the [RESOLVED_UNIT8] input.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'InferStaticVariableTypeTask',
-      createTask,
-      buildInputs, <ResultDescriptor>[
-    INFERRED_STATIC_VARIABLE,
-    STATIC_VARIABLE_RESOLUTION_ERRORS
-  ]);
-
-  InferStaticVariableTypeTask(
-      InternalAnalysisContext context, VariableElement variable)
-      : super(context, variable);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  bool get handlesDependencyCycles => true;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    // Note: DEPENDENCIES_INPUT is not needed.  It is merely a bookkeeping
-    // dependency to ensure that the variables that this variable references
-    // have types inferred before inferring the type of this variable.
-    //
-    VariableElementImpl variable = target;
-
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-    var inheritance = new InheritanceManager2(context.typeSystem);
-
-    // If we're not in a dependency cycle, and we have no type annotation,
-    // re-resolve the right hand side and do inference.
-    List<AnalysisError> errors = AnalysisError.NO_ERRORS;
-    if (dependencyCycle == null && variable.hasImplicitType) {
-      VariableDeclaration declaration = getDeclaration(unit);
-      //
-      // Re-resolve the variable's initializer so that the inferred types
-      // of other variables will be propagated.
-      //
-      RecordingErrorListener errorListener = new RecordingErrorListener();
-      Expression initializer = declaration.initializer;
-
-      ResolutionContext resolutionContext =
-          ResolutionContextBuilder.contextFor(initializer);
-      ResolverVisitor visitor = new ResolverVisitor(inheritance,
-          variable.library, variable.source, typeProvider, errorListener,
-          nameScope: resolutionContext.scope);
-      if (resolutionContext.enclosingClassDeclaration != null) {
-        visitor.prepareToResolveMembersInClass(
-            resolutionContext.enclosingClassDeclaration);
-      }
-      initializer.accept(visitor);
-      DartType newType = initializer.staticType;
-      if (newType == null || newType.isBottom || newType.isDartCoreNull) {
-        newType = typeProvider.dynamicType;
-      }
-
-      //
-      // Record the type of the variable.
-      //
-      setFieldType(variable, newType);
-      errors = getUniqueErrors(errorListener.errors);
-    } else {
-      // TODO(brianwilkerson) For now we simply don't infer any type for
-      // variables or fields involved in a cycle. We could try to be smarter
-      // by re-resolving the initializer in a context in which the types of all
-      // of the variables in the cycle are assumed to be `null`, but it isn't
-      // clear to me that this would produce better results often enough to
-      // warrant the extra effort.
-    }
-    //
-    // Record outputs.
-    //
-    outputs[INFERRED_STATIC_VARIABLE] = variable;
-    outputs[STATIC_VARIABLE_RESOLUTION_ERRORS] = errors;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the given
-   * [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    VariableElement variable = target;
-    LibrarySpecificUnit unit =
-        new LibrarySpecificUnit(variable.library.source, variable.source);
-    return <String, TaskInput>{
-      DEPENDENCIES_INPUT: INFERABLE_STATIC_VARIABLE_DEPENDENCIES
-          .of(variable)
-          .toListOf(INFERRED_STATIC_VARIABLE),
-      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
-      UNIT_INPUT: RESOLVED_UNIT7.of(unit),
-      // In strong mode, add additional dependencies to enforce inference
-      // ordering.
-
-      // Require that full inference be complete for all dependencies of the
-      // current library cycle.
-      'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES
-          .of(unit.library)
-          .toListOf(CREATED_RESOLVED_UNIT10)
-    };
-  }
-
-  /**
-   * Create a [InferStaticVariableTypeTask] based on the given [target] in the
-   * given [context].
-   */
-  static InferStaticVariableTypeTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new InferStaticVariableTypeTask(context, target);
-  }
-}
-
-/**
- * A task computes all of the errors of all of the units for a single
- * library source and sets the [LIBRARY_ERRORS_READY] flag.
- */
-class LibraryErrorsReadyTask extends SourceBasedAnalysisTask {
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'LibraryErrorsReadyTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[LIBRARY_ERRORS_READY]);
-
-  LibraryErrorsReadyTask(InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    outputs[LIBRARY_ERRORS_READY] = true;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
-      'allErrors': UNITS.of(source).toListOf(DART_ERRORS),
-      'libraryElement': LIBRARY_ELEMENT.of(source)
-    };
-  }
-
-  /**
-   * Create a [LibraryErrorsReadyTask] based on the given [target] in the given
-   * [context].
-   */
-  static LibraryErrorsReadyTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new LibraryErrorsReadyTask(context, target);
-  }
-}
-
-/**
- * A task that merges all of the errors for a single source into a single list
- * of errors.
- */
-class LibraryUnitErrorsTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [BUILD_DIRECTIVES_ERRORS] input.
-   */
-  static const String BUILD_DIRECTIVES_ERRORS_INPUT = 'BUILD_DIRECTIVES_ERRORS';
-
-  /**
-   * The name of the [BUILD_LIBRARY_ERRORS] input.
-   */
-  static const String BUILD_LIBRARY_ERRORS_INPUT = 'BUILD_LIBRARY_ERRORS';
-
-  /**
-   * The name of the [HINTS] input.
-   */
-  static const String HINTS_INPUT = 'HINTS';
-
-  /**
-   * The name of the [LINTS] input.
-   */
-  static const String LINTS_INPUT = 'LINTS';
-
-  /**
-   * The name of the [STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT] input.
-   */
-  static const String STATIC_VARIABLE_RESOLUTION_ERRORS_INPUT =
-      'STATIC_VARIABLE_RESOLUTION_ERRORS_INPUT';
-
-  /**
-   * The name of the [RESOLVE_DIRECTIVES_ERRORS] input.
-   */
-  static const String RESOLVE_DIRECTIVES_ERRORS_INPUT =
-      'RESOLVE_DIRECTIVES_ERRORS';
-
-  /**
-   * The name of the [STRONG_MODE_ERRORS] input.
-   */
-  static const String STRONG_MODE_ERRORS_INPUT = 'STRONG_MODE_ERRORS';
-
-  /**
-   * The name of the [RESOLVE_TYPE_NAMES_ERRORS] input.
-   */
-  static const String RESOLVE_TYPE_NAMES_ERRORS_INPUT =
-      'RESOLVE_TYPE_NAMES_ERRORS';
-
-  /**
-   * The name of the [RESOLVE_TYPE_BOUNDS_ERRORS] input.
-   */
-  static const String RESOLVE_TYPE_NAMES_ERRORS2_INPUT =
-      'RESOLVE_TYPE_NAMES_ERRORS2';
-
-  /**
-   * The name of the [RESOLVE_UNIT_ERRORS] input.
-   */
-  static const String RESOLVE_UNIT_ERRORS_INPUT = 'RESOLVE_UNIT_ERRORS';
-
-  /**
-   * The name of the [VARIABLE_REFERENCE_ERRORS] input.
-   */
-  static const String VARIABLE_REFERENCE_ERRORS_INPUT =
-      'VARIABLE_REFERENCE_ERRORS';
-
-  /**
-   * The name of the [VERIFY_ERRORS] input.
-   */
-  static const String VERIFY_ERRORS_INPUT = 'VERIFY_ERRORS';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'LibraryUnitErrorsTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[LIBRARY_UNIT_ERRORS]);
-
-  LibraryUnitErrorsTask(InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    List<List<AnalysisError>> errorLists = <List<AnalysisError>>[];
-    errorLists.add(getRequiredInput(BUILD_DIRECTIVES_ERRORS_INPUT));
-    errorLists.add(getRequiredInput(BUILD_LIBRARY_ERRORS_INPUT));
-    errorLists.add(getRequiredInput(HINTS_INPUT));
-    errorLists.add(getRequiredInput(LINTS_INPUT));
-    errorLists.add(getRequiredInput(RESOLVE_DIRECTIVES_ERRORS_INPUT));
-    errorLists.add(getRequiredInput(RESOLVE_TYPE_NAMES_ERRORS_INPUT));
-    errorLists.add(getRequiredInput(RESOLVE_TYPE_NAMES_ERRORS2_INPUT));
-    errorLists.add(getRequiredInput(RESOLVE_UNIT_ERRORS_INPUT));
-    errorLists.add(getRequiredInput(STATIC_VARIABLE_RESOLUTION_ERRORS_INPUT));
-    errorLists.add(getRequiredInput(STRONG_MODE_ERRORS_INPUT));
-    errorLists.add(getRequiredInput(VARIABLE_REFERENCE_ERRORS_INPUT));
-    errorLists.add(getRequiredInput(VERIFY_ERRORS_INPUT));
-    //
-    // Record outputs.
-    //
-    outputs[LIBRARY_UNIT_ERRORS] = AnalysisError.mergeLists(errorLists);
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [unit].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    Map<String, TaskInput> inputs = <String, TaskInput>{
-      HINTS_INPUT: HINTS.of(unit),
-      LINTS_INPUT: LINTS.of(unit),
-      RESOLVE_DIRECTIVES_ERRORS_INPUT: RESOLVE_DIRECTIVES_ERRORS.of(unit),
-      RESOLVE_TYPE_NAMES_ERRORS_INPUT: RESOLVE_TYPE_NAMES_ERRORS.of(unit),
-      RESOLVE_TYPE_NAMES_ERRORS2_INPUT: RESOLVE_TYPE_BOUNDS_ERRORS.of(unit),
-      RESOLVE_UNIT_ERRORS_INPUT: RESOLVE_UNIT_ERRORS.of(unit),
-      STATIC_VARIABLE_RESOLUTION_ERRORS_INPUT:
-          STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT.of(unit),
-      STRONG_MODE_ERRORS_INPUT: STRONG_MODE_ERRORS.of(unit),
-      VARIABLE_REFERENCE_ERRORS_INPUT: VARIABLE_REFERENCE_ERRORS.of(unit),
-      VERIFY_ERRORS_INPUT: VERIFY_ERRORS.of(unit)
-    };
-    Source source = unit.source;
-    if (unit.library == source) {
-      inputs[BUILD_DIRECTIVES_ERRORS_INPUT] =
-          BUILD_DIRECTIVES_ERRORS.of(source);
-      inputs[BUILD_LIBRARY_ERRORS_INPUT] = BUILD_LIBRARY_ERRORS.of(source);
-    } else {
-      inputs[BUILD_DIRECTIVES_ERRORS_INPUT] =
-          new ConstantTaskInput(AnalysisError.NO_ERRORS);
-      inputs[BUILD_LIBRARY_ERRORS_INPUT] =
-          new ConstantTaskInput(AnalysisError.NO_ERRORS);
-    }
-    return inputs;
-  }
-
-  /**
-   * Create a [LibraryUnitErrorsTask] based on the given [target] in the given
-   * [context].
-   */
-  static LibraryUnitErrorsTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new LibraryUnitErrorsTask(context, target);
-  }
-}
-
-/**
- * A task that parses the content of a Dart file, producing an AST structure,
- * any lexical errors found in the process, the kind of the file (library or
- * part), and several lists based on the AST.
- */
-class ParseDartTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the input whose value is the line information produced for the
-   * file.
-   */
-  static const String LINE_INFO_INPUT_NAME = 'LINE_INFO_INPUT_NAME';
-
-  /**
-   * The name of the input whose value is the modification time of the file.
-   */
-  static const String MODIFICATION_TIME_INPUT_NAME =
-      'MODIFICATION_TIME_INPUT_NAME';
-
-  /**
-   * The name of the input whose value is the token stream produced for the file.
-   */
-  static const String TOKEN_STREAM_INPUT_NAME = 'TOKEN_STREAM_INPUT_NAME';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ParseDartTask', createTask, buildInputs, <ResultDescriptor>[
-    EXPLICITLY_IMPORTED_LIBRARIES,
-    EXPORTED_LIBRARIES,
-    IMPORTED_LIBRARIES,
-    INCLUDED_PARTS,
-    LIBRARY_SPECIFIC_UNITS,
-    PARSE_ERRORS,
-    PARSED_UNIT,
-    REFERENCED_SOURCES,
-    SOURCE_KIND,
-    UNITS,
-  ]);
-
-  /**
-   * The source that is being parsed.
-   */
-  Source _source;
-
-  /**
-   * The [ErrorReporter] to report errors to.
-   */
-  ErrorReporter _errorReporter;
-
-  /**
-   * Initialize a newly created task to parse the content of the Dart file
-   * associated with the given [target] in the given [context].
-   */
-  ParseDartTask(InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    _source = getRequiredSource();
-    LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT_NAME);
-    int modificationTime = getRequiredInput(MODIFICATION_TIME_INPUT_NAME);
-    Token tokenStream = getRequiredInput(TOKEN_STREAM_INPUT_NAME);
-
-    RecordingErrorListener errorListener = new RecordingErrorListener();
-    _errorReporter = new ErrorReporter(errorListener, _source);
-
-    AnalysisOptions options = context.analysisOptions;
-    Parser parser =
-        new Parser(_source, errorListener, useFasta: options.useFastaParser);
-    parser.parseFunctionBodies =
-        options.analyzeFunctionBodiesPredicate(_source);
-    parser.enableOptionalNewAndConst = true;
-    CompilationUnit unit = parser.parseCompilationUnit(tokenStream);
-    unit.lineInfo = lineInfo;
-
-    if (options.patchPaths.isNotEmpty && _source.uri.scheme == 'dart') {
-      var resourceProvider =
-          (context.sourceFactory.dartSdk as FolderBasedDartSdk)
-              .resourceProvider;
-      new SdkPatcher().patch(resourceProvider,
-          context.analysisOptions.patchPaths, errorListener, _source, unit);
-    }
-
-    bool hasNonPartOfDirective = false;
-    bool hasPartOfDirective = false;
-    HashSet<Source> explicitlyImportedSourceSet = new HashSet<Source>();
-    HashSet<Source> exportedSourceSet = new HashSet<Source>();
-    HashSet<Source> includedSourceSet = new HashSet<Source>();
-    NodeList<Directive> directives = unit.directives;
-    int length = directives.length;
-    for (int i = 0; i < length; i++) {
-      Directive directive = directives[i];
-      if (directive is PartOfDirective) {
-        hasPartOfDirective = true;
-      } else {
-        hasNonPartOfDirective = true;
-        if (directive is UriBasedDirective) {
-          Source referencedSource = _resolveDirective(directive);
-          if (referencedSource != null) {
-            if (directive is ExportDirective) {
-              exportedSourceSet.add(referencedSource);
-            } else if (directive is ImportDirective) {
-              explicitlyImportedSourceSet.add(referencedSource);
-            } else if (directive is PartDirective) {
-              includedSourceSet.add(referencedSource);
-            } else {
-              throw new AnalysisException(
-                  '$runtimeType failed to handle a ${directive.runtimeType}');
-            }
-          }
-        }
-      }
-    }
-    //
-    // Always include "dart:core" source.
-    //
-    HashSet<Source> importedSourceSet =
-        new HashSet.from(explicitlyImportedSourceSet);
-    Source coreLibrarySource = context.sourceFactory.forUri(DartSdk.DART_CORE);
-    if (coreLibrarySource == null) {
-      String message;
-      DartSdk sdk = context.sourceFactory.dartSdk;
-      if (sdk == null) {
-        message = 'Could not resolve "dart:core": SDK not defined';
-      } else {
-        message = 'Could not resolve "dart:core": SDK incorrectly configured';
-      }
-      throw new AnalysisException(message);
-    }
-    importedSourceSet.add(coreLibrarySource);
-    //
-    // Compute kind.
-    //
-    SourceKind sourceKind = SourceKind.LIBRARY;
-    if (modificationTime == -1) {
-      sourceKind = SourceKind.UNKNOWN;
-    } else if (hasPartOfDirective && !hasNonPartOfDirective) {
-      sourceKind = SourceKind.PART;
-    }
-    //
-    // Compute source lists.
-    //
-    List<Source> explicitlyImportedSources =
-        explicitlyImportedSourceSet.toList();
-    List<Source> exportedSources = exportedSourceSet.toList();
-    List<Source> importedSources = importedSourceSet.toList();
-    List<Source> includedSources = includedSourceSet.toList();
-    List<Source> unitSources = <Source>[_source]..addAll(includedSourceSet);
-    List<LibrarySpecificUnit> librarySpecificUnits =
-        unitSources.map((s) => new LibrarySpecificUnit(_source, s)).toList();
-    //
-    // Compute referenced sources.
-    //
-    Set<Source> referencedSources = new Set<Source>();
-    referencedSources.add(coreLibrarySource);
-    referencedSources.addAll(unitSources);
-    for (Directive directive in unit.directives) {
-      if (directive is NamespaceDirective) {
-        referencedSources.add(directive.uriSource);
-        for (Configuration configuration in directive.configurations) {
-          referencedSources.add(configuration.uriSource);
-        }
-      }
-    }
-    referencedSources.removeWhere((source) => source == null);
-    //
-    // Record outputs.
-    //
-    List<AnalysisError> parseErrors = getUniqueErrors(errorListener.errors);
-    outputs[EXPLICITLY_IMPORTED_LIBRARIES] = explicitlyImportedSources;
-    outputs[EXPORTED_LIBRARIES] = exportedSources;
-    outputs[IMPORTED_LIBRARIES] = importedSources;
-    outputs[INCLUDED_PARTS] = includedSources;
-    outputs[LIBRARY_SPECIFIC_UNITS] = librarySpecificUnits;
-    outputs[PARSE_ERRORS] = parseErrors;
-    outputs[PARSED_UNIT] = unit;
-    outputs[REFERENCED_SOURCES] = referencedSources.toList();
-    outputs[SOURCE_KIND] = sourceKind;
-    outputs[UNITS] = unitSources;
-  }
-
-  /**
-   * Return the result of resolving the URI of the given URI-based [directive]
-   * against the URI of the given library, or `null` if the URI is not valid.
-   */
-  Source _resolveDirective(UriBasedDirective directive) {
-    bool isImport = directive is ImportDirective;
-
-    // Resolve the default URI.
-    Source defaultSource;
-    {
-      StringLiteral uriLiteral = directive.uri;
-      String uriContent = uriLiteral.stringValue;
-      if (uriContent != null) {
-        uriContent = uriContent.trim();
-        directive.uriContent = uriContent;
-      }
-      defaultSource = _resolveUri(isImport, uriLiteral, uriContent);
-      directive.uriSource = defaultSource;
-    }
-
-    // Resolve all configurations and try to choose one.
-    if (directive is NamespaceDirectiveImpl) {
-      String configuredUriContent;
-      Source configuredSource;
-      for (Configuration configuration in directive.configurations) {
-        String uriContent = configuration.uri.stringValue;
-        Source source = _resolveUri(isImport, configuration.uri, uriContent);
-        configuration.uriSource = source;
-        if (configuredSource == null) {
-          String variableName =
-              configuration.name.components.map((i) => i.name).join('.');
-          String variableValue = context.declaredVariables.get(variableName);
-          if (configuration.value != null &&
-                  variableValue == configuration.value.stringValue ||
-              variableValue == 'true') {
-            configuredUriContent = configuration.uri.stringValue;
-            configuredSource = source;
-          }
-        }
-      }
-      String selectedContentUri = configuredUriContent ?? directive.uriContent;
-      Source selectedSource = configuredSource ?? defaultSource;
-      directive.selectedUriContent = selectedContentUri;
-      directive.selectedSource = selectedSource;
-      return selectedSource;
-    }
-    return defaultSource;
-  }
-
-  /**
-   * Return the result of resolve the given [uriContent], reporting errors
-   * against the [uriLiteral].
-   */
-  Source _resolveUri(
-      bool isImport, StringLiteral uriLiteral, String uriContent) {
-    UriValidationCode code =
-        UriBasedDirectiveImpl.validateUri(isImport, uriLiteral, uriContent);
-    if (code == null) {
-      try {
-        Uri.parse(uriContent);
-      } on FormatException {
-        return null;
-      }
-      return context.sourceFactory.resolveUri(_source, uriContent);
-    } else if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) {
-      return null;
-    } else if (code == UriValidationCode.URI_WITH_INTERPOLATION) {
-      _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.URI_WITH_INTERPOLATION, uriLiteral);
-      return null;
-    } else if (code == UriValidationCode.INVALID_URI) {
-      _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.INVALID_URI, uriLiteral, [uriContent]);
-      return null;
-    }
-    throw new AnalysisException('Failed to handle validation code: $code');
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the given
-   * [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    return <String, TaskInput>{
-      LINE_INFO_INPUT_NAME: LINE_INFO.of(target),
-      MODIFICATION_TIME_INPUT_NAME: MODIFICATION_TIME.of(target),
-      TOKEN_STREAM_INPUT_NAME: TOKEN_STREAM.of(target, flushOnAccess: true)
-    };
-  }
-
-  /**
-   * Create a [ParseDartTask] based on the given [target] in the given
-   * [context].
-   */
-  static ParseDartTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ParseDartTask(context, target);
-  }
-}
-
-/**
- * A task that builds [RESOLVED_UNIT7] for a unit.
- */
-class PartiallyResolveUnitReferencesTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [LIBRARY_ELEMENT6] input.
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The name of the [RESOLVED_UNIT6] input.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  /**
-   * The name of the [TYPE_PROVIDER] input.
-   */
-  static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'PartiallyResolveUnitReferencesTask',
-      createTask,
-      buildInputs, <ResultDescriptor>[
-    INFERABLE_STATIC_VARIABLES_IN_UNIT,
-    CREATED_RESOLVED_UNIT7,
-    RESOLVED_UNIT7
-  ]);
-
-  PartiallyResolveUnitReferencesTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    CompilationUnitElement unitElement = unit.declaredElement;
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-    var inheritance = new InheritanceManager2(context.typeSystem);
-    //
-    // Resolve references and record outputs.
-    //
-    PartialResolverVisitor visitor = new PartialResolverVisitor(
-        inheritance,
-        libraryElement,
-        unitElement.source,
-        typeProvider,
-        AnalysisErrorListener.NULL_LISTENER);
-    unit.accept(visitor);
-    //
-    // Record outputs.
-    //
-    outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT] = visitor.staticVariables;
-    outputs[RESOLVED_UNIT7] = unit;
-    outputs[CREATED_RESOLVED_UNIT7] = true;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{
-      'fullyBuiltLibraryElements': READY_LIBRARY_ELEMENT6.of(unit.library),
-      LIBRARY_INPUT: LIBRARY_ELEMENT6.of(unit.library),
-      UNIT_INPUT: RESOLVED_UNIT6.of(unit),
-      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
-      // In strong mode, add additional dependencies to enforce inference
-      // ordering.
-
-      // Require that full inference be complete for all dependencies of the
-      // current library cycle.
-      'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES
-          .of(unit.library)
-          .toListOf(CREATED_RESOLVED_UNIT10)
-    };
-  }
-
-  /**
-   * Create a [PartiallyResolveUnitReferencesTask] based on the given [target]
-   * in the given [context].
-   */
-  static PartiallyResolveUnitReferencesTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new PartiallyResolveUnitReferencesTask(context, target);
-  }
-}
-
-/**
- * A task that ensures that [LIBRARY_ELEMENT2] is ready for the target library
- * source and its import/export closure.
- */
-class ReadyLibraryElement2Task extends SourceBasedAnalysisTask {
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ReadyLibraryElement2Task',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[READY_LIBRARY_ELEMENT2]);
-
-  ReadyLibraryElement2Task(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  bool get handlesDependencyCycles => true;
-
-  @override
-  void internalPerform() {
-    outputs[READY_LIBRARY_ELEMENT2] = true;
-  }
-
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
-      'thisLibraryElementReady': LIBRARY_ELEMENT2.of(source),
-      'directlyImportedLibrariesReady':
-          IMPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT2),
-      'directlyExportedLibrariesReady':
-          EXPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT2),
-    };
-  }
-
-  static ReadyLibraryElement2Task createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ReadyLibraryElement2Task(context, target);
-  }
-}
-
-/**
- * A task that ensures that [LIBRARY_ELEMENT6] is ready for the target library
- * source and its import/export closure.
- */
-class ReadyLibraryElement5Task extends SourceBasedAnalysisTask {
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ReadyLibraryElement5Task',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[READY_LIBRARY_ELEMENT6]);
-
-  ReadyLibraryElement5Task(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  bool get handlesDependencyCycles => true;
-
-  @override
-  void internalPerform() {
-    outputs[READY_LIBRARY_ELEMENT6] = true;
-  }
-
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
-      'thisLibraryElementReady': LIBRARY_ELEMENT6.of(source),
-      'directlyImportedLibrariesReady':
-          IMPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT6),
-      'directlyExportedLibrariesReady':
-          EXPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT6),
-    };
-  }
-
-  static ReadyLibraryElement5Task createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ReadyLibraryElement5Task(context, target);
-  }
-}
-
-/**
- * A task that ensures that [LIBRARY_ELEMENT7] is ready for the target library
- * source and its import/export closure.
- */
-class ReadyLibraryElement7Task extends SourceBasedAnalysisTask {
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ReadyLibraryElement7Task',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[READY_LIBRARY_ELEMENT7]);
-
-  ReadyLibraryElement7Task(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  bool get handlesDependencyCycles => true;
-
-  @override
-  void internalPerform() {
-    outputs[READY_LIBRARY_ELEMENT7] = true;
-  }
-
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
-      'thisLibraryElementReady': LIBRARY_ELEMENT7.of(source),
-      'directlyImportedLibrariesReady':
-          IMPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT7),
-      'directlyExportedLibrariesReady':
-          EXPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT7),
-    };
-  }
-
-  static ReadyLibraryElement7Task createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ReadyLibraryElement7Task(context, target);
-  }
-}
-
-/**
- * A task that ensures that [RESOLVED_UNIT] is ready for every unit of the
- * target library source and its import/export closure.
- */
-class ReadyResolvedUnitTask extends SourceBasedAnalysisTask {
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ReadyResolvedUnitTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[READY_RESOLVED_UNIT]);
-
-  ReadyResolvedUnitTask(InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  bool get handlesDependencyCycles => true;
-
-  @override
-  void internalPerform() {
-    outputs[READY_RESOLVED_UNIT] = true;
-  }
-
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
-      'thisLibraryUnitsReady':
-          LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT),
-    };
-  }
-
-  static ReadyResolvedUnitTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ReadyResolvedUnitTask(context, target);
-  }
-}
-
-/**
- * A task that ensures that the expression AST for a constant is resolved and
- * sets the [CONSTANT_EXPRESSION_RESOLVED] result.
- */
-class ResolveConstantExpressionTask extends ConstantEvaluationAnalysisTask {
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ResolveConstantExpressionTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[CONSTANT_EXPRESSION_RESOLVED]);
-
-  ResolveConstantExpressionTask(
-      InternalAnalysisContext context, ConstantEvaluationTarget constant)
-      : super(context, constant);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Record outputs.
-    //
-    outputs[CONSTANT_EXPRESSION_RESOLVED] = true;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source librarySource;
-    if (target is Element) {
-      CompilationUnitElementImpl unit = target
-          .getAncestor((Element element) => element is CompilationUnitElement);
-      librarySource = unit.librarySource;
-    } else if (target is ElementAnnotationImpl) {
-      librarySource = target.librarySource;
-    } else {
-      throw new AnalysisException(
-          'Cannot build inputs for a ${target.runtimeType}');
-    }
-    return <String, TaskInput>{
-      'createdResolvedUnit': CREATED_RESOLVED_UNIT11
-          .of(new LibrarySpecificUnit(librarySource, target.source))
-    };
-  }
-
-  /**
-   * Create a [ResolveConstantExpressionTask] based on the given [target] in
-   * the given [context].
-   */
-  static ResolveConstantExpressionTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ResolveConstantExpressionTask(context, target);
-  }
-}
-
-/**
- * A task that resolves imports and export directives to already built elements.
- */
-class ResolveDirectiveElementsTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the input whose value is the defining [LIBRARY_ELEMENT2].
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The name of the input for [RESOLVED_UNIT1] of a unit.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  static const String SOURCES_MODIFICATION_TIME_INPUT =
-      'SOURCES_MODIFICATION_TIME_INPUT';
-  static const String IMPORTS_SOURCE_KIND_INPUT = 'IMPORTS_SOURCE_KIND_INPUT';
-  static const String EXPORTS_SOURCE_KIND_INPUT = 'EXPORTS_SOURCE_KIND_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ResolveDirectiveElementsTask',
-      createTask,
-      buildInputs, <ResultDescriptor>[
-    CREATED_RESOLVED_UNIT2,
-    RESOLVED_UNIT2,
-    RESOLVE_DIRECTIVES_ERRORS
-  ]);
-
-  ResolveDirectiveElementsTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    LibrarySpecificUnit targetUnit = target;
-    //
-    // Prepare inputs.
-    //
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    Map<Source, int> sourceModificationTimeMap =
-        getRequiredInput(SOURCES_MODIFICATION_TIME_INPUT);
-    Map<Source, SourceKind> importSourceKindMap =
-        getRequiredInput(IMPORTS_SOURCE_KIND_INPUT);
-    Map<Source, SourceKind> exportSourceKindMap =
-        getRequiredInput(EXPORTS_SOURCE_KIND_INPUT);
-    //
-    // Resolve directive AST nodes to elements.
-    //
-    List<AnalysisError> errors = const <AnalysisError>[];
-    if (targetUnit.unit == targetUnit.library) {
-      DirectiveResolver resolver = new DirectiveResolver(
-          sourceModificationTimeMap, importSourceKindMap, exportSourceKindMap);
-      unit.accept(resolver);
-      errors = resolver.errors;
-    }
-    //
-    // Record outputs.
-    //
-    outputs[CREATED_RESOLVED_UNIT2] = true;
-    outputs[RESOLVED_UNIT2] = unit;
-    outputs[RESOLVE_DIRECTIVES_ERRORS] = errors;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT2.of(unit.library),
-      UNIT_INPUT: RESOLVED_UNIT1.of(unit),
-      SOURCES_MODIFICATION_TIME_INPUT:
-          REFERENCED_SOURCES.of(unit.library).toMapOf(MODIFICATION_TIME),
-      IMPORTS_SOURCE_KIND_INPUT:
-          IMPORTED_LIBRARIES.of(unit.library).toMapOf(SOURCE_KIND),
-      EXPORTS_SOURCE_KIND_INPUT:
-          EXPORTED_LIBRARIES.of(unit.library).toMapOf(SOURCE_KIND)
-    };
-  }
-
-  /**
-   * Create a [ResolveDirectiveElementsTask] based on the given [target] in
-   * the given [context].
-   */
-  static ResolveDirectiveElementsTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ResolveDirectiveElementsTask(context, target);
-  }
-}
-
-/**
- * An artificial task that does nothing except to force [LIBRARY_ELEMENT7] for
- * the target library and its import/export closure.
- */
-class ResolvedUnit7InLibraryClosureTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [LIBRARY_ELEMENT7] input.
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ResolvedUnit7InLibraryClosureTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[LIBRARY_ELEMENT8]);
-
-  ResolvedUnit7InLibraryClosureTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    LibraryElement library = getRequiredInput(LIBRARY_INPUT);
-    outputs[LIBRARY_ELEMENT8] = library;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
-      'readyForClosure': READY_LIBRARY_ELEMENT7.of(source),
-      LIBRARY_INPUT: LIBRARY_ELEMENT7.of(source),
-    };
-  }
-
-  /**
-   * Create a [ResolvedUnit7InLibraryClosureTask] based on the given
-   * [target] in the given [context].
-   */
-  static ResolvedUnit7InLibraryClosureTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ResolvedUnit7InLibraryClosureTask(context, target);
-  }
-}
-
-/**
- * An artificial task that does nothing except to force [LIBRARY_ELEMENT6] and
- * [RESOLVED_UNIT7] in the defining and part units of a library.
- */
-class ResolvedUnit7InLibraryTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [LIBRARY_ELEMENT6] input.
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ResolvedUnit7InLibraryTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[LIBRARY_ELEMENT7]);
-
-  ResolvedUnit7InLibraryTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    LibraryElement library = getRequiredInput(LIBRARY_INPUT);
-    outputs[LIBRARY_ELEMENT7] = library;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
-      'resolvedUnits':
-          LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT7),
-      LIBRARY_INPUT: LIBRARY_ELEMENT6.of(source),
-    };
-  }
-
-  /**
-   * Create a [ResolvedUnit7InLibraryTask] based on the given [target]
-   * in the given [context].
-   */
-  static ResolvedUnit7InLibraryTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ResolvedUnit7InLibraryTask(context, target);
-  }
-}
-
-/**
- * A task that ensures that all of the inferable instance members in a
- * compilation unit have had their right hand sides re-resolved
- */
-class ResolveInstanceFieldsInUnitTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [LIBRARY_ELEMENT6] input.
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The name of the [TYPE_PROVIDER] input.
-   */
-  static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
-  /**
-   * The name of the input whose value is the [RESOLVED_UNIT8] for the
-   * compilation unit.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ResolveInstanceFieldsInUnitTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[CREATED_RESOLVED_UNIT9, RESOLVED_UNIT9]);
-
-  /**
-   * Initialize a newly created task to build a library element for the given
-   * [unit] in the given [context].
-   */
-  ResolveInstanceFieldsInUnitTask(
-      InternalAnalysisContext context, LibrarySpecificUnit unit)
-      : super(context, unit);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-    var inheritance = new InheritanceManager2(context.typeSystem);
-
-    CompilationUnitElement unitElement = unit.declaredElement;
-    //
-    // Resolve references.
-    //
-    InstanceFieldResolverVisitor visitor = new InstanceFieldResolverVisitor(
-        inheritance,
-        libraryElement,
-        unitElement.source,
-        typeProvider,
-        AnalysisErrorListener.NULL_LISTENER);
-    visitor.resolveCompilationUnit(unit);
-    //
-    // Record outputs.
-    //
-    outputs[RESOLVED_UNIT9] = unit;
-    outputs[CREATED_RESOLVED_UNIT9] = true;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the given
-   * [libSource].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{
-      UNIT_INPUT: RESOLVED_UNIT8.of(unit),
-      LIBRARY_INPUT: LIBRARY_ELEMENT6.of(unit.library),
-      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
-      // In strong mode, add additional dependencies to enforce inference
-      // ordering.
-
-      // Require that static variable inference  be complete for all units in
-      // the current library cycle.
-      'orderLibraryCycleTasks':
-          LIBRARY_CYCLE_UNITS.of(unit.library).toListOf(CREATED_RESOLVED_UNIT8),
-      // Require that full inference be complete for all dependencies of the
-      // current library cycle.
-      'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES
-          .of(unit.library)
-          .toListOf(CREATED_RESOLVED_UNIT10)
-    };
-  }
-
-  /**
-   * Create a [ResolveInstanceFieldsInUnitTask] based on the given [target] in
-   * the given [context].
-   */
-  static ResolveInstanceFieldsInUnitTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ResolveInstanceFieldsInUnitTask(context, target);
-  }
-}
-
-/**
- * A task that finishes resolution by requesting [RESOLVED_UNIT11] for every
- * unit in the libraries closure and produces [LIBRARY_ELEMENT9].
- */
-class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [LIBRARY_ELEMENT8] input.
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ResolveLibraryReferencesTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[LIBRARY_ELEMENT9]);
-
-  ResolveLibraryReferencesTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    LibraryElement library = getRequiredInput(LIBRARY_INPUT);
-    outputs[LIBRARY_ELEMENT9] = library;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT8.of(source),
-      'resolvedUnits':
-          LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT11),
-    };
-  }
-
-  /**
-   * Create a [ResolveLibraryReferencesTask] based on the given [target] in
-   * the given [context].
-   */
-  static ResolveLibraryReferencesTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ResolveLibraryReferencesTask(context, target);
-  }
-}
-
-/**
- * A task that finishes resolution by requesting [RESOLVED_UNIT12] for every
- * unit in the libraries closure and produces [LIBRARY_ELEMENT].
- */
-class ResolveLibraryTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [LIBRARY_ELEMENT9] input.
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The name of the list of [RESOLVED_UNIT12] input.
-   */
-  static const String UNITS_INPUT = 'UNITS_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ResolveLibraryTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[LIBRARY_ELEMENT]);
-
-  ResolveLibraryTask(InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    LibraryElement library = getRequiredInput(LIBRARY_INPUT);
-    //
-    // Record outputs.
-    //
-    outputs[LIBRARY_ELEMENT] = library;
-  }
-
-/**
- * Return a map from the names of the inputs of this kind of task to the task
- * input descriptors describing those inputs for a task with the
- * given [target].
- */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT9.of(source),
-      'thisLibraryClosureIsReady': READY_RESOLVED_UNIT.of(source),
-    };
-  }
-
-/**
- * Create a [ResolveLibraryTask] based on the given [target] in the given
- * [context].
- */
-  static ResolveLibraryTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ResolveLibraryTask(context, target);
-  }
-}
-
-/**
- * An artificial task that does nothing except to force type names resolution
- * for the defining and part units of a library.
- */
-class ResolveLibraryTypeNamesTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [LIBRARY_ELEMENT5] input.
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The name of the [TYPE_PROVIDER] input.
-   */
-  static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ResolveLibraryTypeNamesTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[LIBRARY_ELEMENT6]);
-
-  ResolveLibraryTypeNamesTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    LibraryElement library = getRequiredInput(LIBRARY_INPUT);
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-    //
-    // Create the synthetic element for `loadLibrary`.
-    //
-    (library as LibraryElementImpl).createLoadLibraryFunction(typeProvider);
-    //
-    // Record outputs.
-    //
-    outputs[LIBRARY_ELEMENT6] = library;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
-      'resolvedUnit':
-          LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT5),
-      LIBRARY_INPUT: LIBRARY_ELEMENT5.of(source),
-      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
-    };
-  }
-
-  /**
-   * Create a [ResolveLibraryTypeNamesTask] based on the given [target] in
-   * the given [context].
-   */
-  static ResolveLibraryTypeNamesTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ResolveLibraryTypeNamesTask(context, target);
-  }
-}
-
-/**
- * An artificial task that does nothing except to force type parameter bounds
- * type names resolution for the defining and part units of a library.
- */
-class ResolveTopLevelLibraryTypeBoundsTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [LIBRARY_ELEMENT4] input.
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ResolveTopLevelLibraryTypeBoundsTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[LIBRARY_ELEMENT5]);
-
-  ResolveTopLevelLibraryTypeBoundsTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  bool get handlesDependencyCycles => true;
-
-  @override
-  void internalPerform() {
-    LibraryElement library = getRequiredInput(LIBRARY_INPUT);
-    outputs[LIBRARY_ELEMENT5] = library;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT4.of(source),
-      'thisLibraryUnitsReady':
-          LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT4),
-      'directlyImportedLibrariesReady':
-          IMPORTED_LIBRARIES.of(source).toListOf(LIBRARY_ELEMENT5),
-      'directlyExportedLibrariesReady':
-          EXPORTED_LIBRARIES.of(source).toListOf(LIBRARY_ELEMENT5),
-    };
-  }
-
-  /**
-   * Create a [ResolveTopLevelLibraryTypeBoundsTask] based on the given [target]
-   * in the given [context].
-   */
-  static ResolveTopLevelLibraryTypeBoundsTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ResolveTopLevelLibraryTypeBoundsTask(context, target);
-  }
-}
-
-/**
- * A task that builds [RESOLVED_UNIT4] for a unit.
- */
-class ResolveTopLevelUnitTypeBoundsTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the input whose value is the defining [LIBRARY_ELEMENT4].
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The name of the [RESOLVED_UNIT3] input.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ResolveTopLevelUnitTypeBoundsTask',
-      createTask,
-      buildInputs, <ResultDescriptor>[
-    RESOLVE_TYPE_BOUNDS_ERRORS,
-    CREATED_RESOLVED_UNIT4,
-    RESOLVED_UNIT4
-  ]);
-
-  ResolveTopLevelUnitTypeBoundsTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    LibraryElement library = getRequiredInput(LIBRARY_INPUT);
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    CompilationUnitElement unitElement = unit.declaredElement;
-    //
-    // Resolve TypeName nodes.
-    //
-    RecordingErrorListener errorListener = new RecordingErrorListener();
-    new TypeParameterBoundsResolver(
-            context.typeSystem, library, unitElement.source, errorListener)
-        .resolveTypeBounds(unit);
-    //
-    // Record outputs.
-    //
-    outputs[RESOLVE_TYPE_BOUNDS_ERRORS] =
-        getTargetSourceErrors(errorListener, target);
-    outputs[RESOLVED_UNIT4] = unit;
-    outputs[CREATED_RESOLVED_UNIT4] = true;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    // TODO(brianwilkerson) This task updates the element model to have type
-    // information and updates the class hierarchy. It should produce a new
-    // version of the element model in order to record those changes.
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{
-      'importsExportNamespace':
-          IMPORTED_LIBRARIES.of(unit.library).toMapOf(LIBRARY_ELEMENT4),
-      'dependOnAllExportedSources':
-          IMPORTED_LIBRARIES.of(unit.library).toMapOf(EXPORT_SOURCE_CLOSURE),
-      LIBRARY_INPUT: LIBRARY_ELEMENT4.of(unit.library),
-      UNIT_INPUT: RESOLVED_UNIT3.of(unit)
-    };
-  }
-
-  /**
-   * Create a [ResolveTopLevelUnitTypeBoundsTask] based on the given [target] in
-   * the given [context].
-   */
-  static ResolveTopLevelUnitTypeBoundsTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ResolveTopLevelUnitTypeBoundsTask(context, target);
-  }
-}
-
-/**
- * A task that resolves the bodies of top-level functions, constructors, and
- * methods within a single compilation unit.
- */
-class ResolveUnitTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the input whose value is the defining [LIBRARY_ELEMENT8].
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The name of the [TYPE_PROVIDER] input.
-   */
-  static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
-  /**
-   * The name of the [RESOLVED_UNIT10] input.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ResolveUnitTask', createTask, buildInputs, <ResultDescriptor>[
-    CONSTANT_EXPRESSIONS_DEPENDENCIES,
-    RESOLVE_UNIT_ERRORS,
-    CREATED_RESOLVED_UNIT11,
-    RESOLVED_UNIT11
-  ]);
-
-  ResolveUnitTask(
-      InternalAnalysisContext context, LibrarySpecificUnit compilationUnit)
-      : super(context, compilationUnit);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    LibrarySpecificUnit target = this.target;
-    LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-    var inheritance = new InheritanceManager2(context.typeSystem);
-    //
-    // Resolve everything.
-    //
-    CompilationUnitElement unitElement = unit.declaredElement;
-    RecordingErrorListener errorListener = new RecordingErrorListener();
-    ResolverVisitor visitor = new ResolverVisitor(inheritance, libraryElement,
-        unitElement.source, typeProvider, errorListener);
-    unit.accept(visitor);
-    //
-    // Compute constant expressions' dependencies.
-    //
-    List<ConstantEvaluationTarget> constExprDependencies;
-    {
-      ConstantExpressionsDependenciesFinder finder =
-          new ConstantExpressionsDependenciesFinder();
-      unit.accept(finder);
-      constExprDependencies = finder.dependencies.toList();
-    }
-    //
-    // Record outputs.
-    //
-    // TODO(brianwilkerson) This task modifies the element model (by copying the
-    // AST's for constructor initializers into it) but does not produce an
-    // updated version of the element model.
-    //
-    outputs[CONSTANT_EXPRESSIONS_DEPENDENCIES] = constExprDependencies;
-    outputs[RESOLVE_UNIT_ERRORS] = getTargetSourceErrors(errorListener, target);
-    outputs[RESOLVED_UNIT11] = unit;
-    outputs[CREATED_RESOLVED_UNIT11] = true;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the given
-   * [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT8.of(unit.library),
-      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
-      UNIT_INPUT: RESOLVED_UNIT10.of(unit),
-      // In strong mode, add additional dependencies to enforce inference
-      // ordering.
-
-      // Require that inference be complete for all units in the
-      // current library cycle.
-      'orderLibraryCycleTasks':
-          LIBRARY_CYCLE_UNITS.of(unit.library).toListOf(CREATED_RESOLVED_UNIT10)
-    };
-  }
-
-  /**
-   * Create a [ResolveUnitTask] based on the given [target] in
-   * the given [context].
-   */
-  static ResolveUnitTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ResolveUnitTask(context, target);
-  }
-}
-
-/**
- * A task that builds [RESOLVED_UNIT5] for a unit.
- */
-class ResolveUnitTypeNamesTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the input whose value is the defining [LIBRARY_ELEMENT5].
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The name of the [RESOLVED_UNIT4] input.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  /**
-   * The name of the [TYPE_PROVIDER] input.
-   */
-  static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ResolveUnitTypeNamesTask', createTask, buildInputs, <ResultDescriptor>[
-    RESOLVE_TYPE_NAMES_ERRORS,
-    CREATED_RESOLVED_UNIT5,
-    RESOLVED_UNIT5
-  ]);
-
-  ResolveUnitTypeNamesTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    LibraryElement library = getRequiredInput(LIBRARY_INPUT);
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    CompilationUnitElement unitElement = unit.declaredElement;
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-    //
-    // Resolve TypeName nodes.
-    //
-    RecordingErrorListener errorListener = new RecordingErrorListener();
-    TypeResolverVisitor visitor = new TypeResolverVisitor(
-        library, unitElement.source, typeProvider, errorListener,
-        shouldUseWithClauseInferredTypes: false,
-        shouldSetElementSupertypes: true);
-    unit.accept(visitor);
-    //
-    // Re-write the AST to handle the optional new and const feature.
-    //
-    unit.accept(new AstRewriteVisitor(context.typeSystem, library,
-        unit.declaredElement.source, typeProvider, errorListener));
-    //
-    // Record outputs.
-    //
-    outputs[RESOLVE_TYPE_NAMES_ERRORS] =
-        getTargetSourceErrors(errorListener, target);
-    outputs[RESOLVED_UNIT5] = unit;
-    outputs[CREATED_RESOLVED_UNIT5] = true;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    // TODO(brianwilkerson) This task updates the element model to have type
-    // information and updates the class hierarchy. It should produce a new
-    // version of the element model in order to record those changes.
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library),
-      UNIT_INPUT: RESOLVED_UNIT4.of(unit),
-      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
-    };
-  }
-
-  /**
-   * Create a [ResolveUnitTypeNamesTask] based on the given [target] in
-   * the given [context].
-   */
-  static ResolveUnitTypeNamesTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ResolveUnitTypeNamesTask(context, target);
-  }
-}
-
-/**
- * A task that builds [RESOLVED_UNIT6] for a unit.
- */
-class ResolveVariableReferencesTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [LIBRARY_ELEMENT1] input.
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The name of the [RESOLVED_UNIT5] input.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  /**
-   * The name of the [TYPE_PROVIDER] input.
-   */
-  static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ResolveVariableReferencesTask',
-      createTask,
-      buildInputs, <ResultDescriptor>[
-    CREATED_RESOLVED_UNIT6,
-    RESOLVED_UNIT6,
-    VARIABLE_REFERENCE_ERRORS
-  ]);
-
-  ResolveVariableReferencesTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    //
-    // Prepare inputs.
-    //
-    LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    CompilationUnitElement unitElement = unit.declaredElement;
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-    //
-    // Resolve local variables.
-    //
-    RecordingErrorListener errorListener = new RecordingErrorListener();
-    Scope nameScope = new LibraryScope(libraryElement);
-    VariableResolverVisitor visitor = new VariableResolverVisitor(
-        libraryElement, unitElement.source, typeProvider, errorListener,
-        nameScope: nameScope);
-    unit.accept(visitor);
-    //
-    // Record outputs.
-    //
-    outputs[RESOLVED_UNIT6] = unit;
-    outputs[CREATED_RESOLVED_UNIT6] = true;
-    outputs[VARIABLE_REFERENCE_ERRORS] =
-        getTargetSourceErrors(errorListener, target);
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT1.of(unit.library),
-      UNIT_INPUT: RESOLVED_UNIT5.of(unit),
-      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
-    };
-  }
-
-  /**
-   * Create a [ResolveVariableReferencesTask] based on the given [target] in
-   * the given [context].
-   */
-  static ResolveVariableReferencesTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ResolveVariableReferencesTask(context, target);
-  }
-}
-
-/**
- * A task that scans the content of a Dart file, producing a stream of Dart
- * tokens, line information, and any lexical errors encountered in the process.
- */
-class ScanDartTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the input whose value is the content of the file.
-   */
-  static const String CONTENT_INPUT_NAME = 'CONTENT_INPUT_NAME';
-
-  /**
-   * The name of the input whose value is the modification time of the file.
-   */
-  static const String MODIFICATION_TIME_INPUT = 'MODIFICATION_TIME_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ScanDartTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[IGNORE_INFO, LINE_INFO, SCAN_ERRORS, TOKEN_STREAM],
-      suitabilityFor: suitabilityFor);
-
-  /**
-   * Initialize a newly created task to access the content of the source
-   * associated with the given [target] in the given [context].
-   */
-  ScanDartTask(InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    Source source = getRequiredSource();
-    RecordingErrorListener errorListener = new RecordingErrorListener();
-
-    int modificationTime = getRequiredInput(MODIFICATION_TIME_INPUT);
-    if (modificationTime < 0) {
-      String message = 'Content could not be read';
-      if (context is InternalAnalysisContext) {
-        CacheEntry entry =
-            (context as InternalAnalysisContext).getCacheEntry(target);
-        CaughtException exception = entry.exception;
-        if (exception != null) {
-          message = exception.toString();
-        }
-      }
-      if (source.exists()) {
-        errorListener.onError(new AnalysisError(
-            source, 0, 0, ScannerErrorCode.UNABLE_GET_CONTENT, [message]));
-      }
-    }
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the given
-   * [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    if (target is Source) {
-      return <String, TaskInput>{
-        CONTENT_INPUT_NAME: CONTENT.of(target, flushOnAccess: true),
-        MODIFICATION_TIME_INPUT: MODIFICATION_TIME.of(target)
-      };
-    }
-    throw new AnalysisException(
-        'Cannot build inputs for a ${target.runtimeType}');
-  }
-
-  /**
-   * Create a [ScanDartTask] based on the given [target] in the given [context].
-   */
-  static ScanDartTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ScanDartTask(context, target);
-  }
-
-  /**
-   * Return an indication of how suitable this task is for the given [target].
-   */
-  static TaskSuitability suitabilityFor(AnalysisTarget target) {
-    if (target is Source) {
-      if (target.shortName.endsWith(AnalysisEngine.SUFFIX_DART)) {
-        return TaskSuitability.HIGHEST;
-      }
-      return TaskSuitability.LOWEST;
-    }
-    return TaskSuitability.NONE;
-  }
-}
-
-/**
- * A task that builds [STRONG_MODE_ERRORS] for a unit.  Also builds
- * [RESOLVED_UNIT] for a unit.
- */
-class StrongModeVerifyUnitTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [RESOLVED_UNIT12] input.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  /**
-   * The name of the [TYPE_PROVIDER] input.
-   */
-  static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'StrongModeVerifyUnitTask', createTask, buildInputs, <ResultDescriptor>[
-    STRONG_MODE_ERRORS,
-    CREATED_RESOLVED_UNIT,
-    RESOLVED_UNIT
-  ]);
-
-  StrongModeVerifyUnitTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    RecordingErrorListener errorListener = new RecordingErrorListener();
-    //
-    // Prepare inputs.
-    //
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    AnalysisOptionsImpl options = context.analysisOptions;
-    if (options.strongMode) {
-      CodeChecker checker = new CodeChecker(
-          typeProvider,
-          new Dart2TypeSystem(typeProvider,
-              implicitCasts: options.implicitCasts),
-          errorListener,
-          options);
-      checker.visitCompilationUnit(unit);
-    }
-    //
-    // Record outputs.
-    //
-    outputs[STRONG_MODE_ERRORS] = getUniqueErrors(errorListener.errors);
-    outputs[CREATED_RESOLVED_UNIT] = true;
-    outputs[RESOLVED_UNIT] = unit;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{
-      UNIT_INPUT: RESOLVED_UNIT12.of(unit),
-      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
-    };
-  }
-
-  /**
-   * Create a [StrongModeVerifyUnitTask] based on the given [target] in
-   * the given [context].
-   */
-  static StrongModeVerifyUnitTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new StrongModeVerifyUnitTask(context, target);
-  }
-}
-
-/**
- * A task that builds [VERIFY_ERRORS] for a unit.
- */
-class VerifyUnitTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [PENDING_ERRORS] input.
-   */
-  static const String PENDING_ERRORS_INPUT = 'PENDING_ERRORS_INPUT';
-
-  /**
-   * The name of the input of a mapping from [REFERENCED_SOURCES] to their
-   * [MODIFICATION_TIME]s.
-   */
-  static const String REFERENCED_SOURCE_MODIFICATION_TIME_MAP_INPUT =
-      'REFERENCED_SOURCE_MODIFICATION_TIME_MAP_INPUT';
-
-  /**
-   * The name of the [TYPE_PROVIDER] input.
-   */
-  static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
-  /**
-   * The name of the [RESOLVED_UNIT] input.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('VerifyUnitTask',
-      createTask, buildInputs, <ResultDescriptor>[VERIFY_ERRORS]);
-
-  /**
-   * The [ErrorReporter] to report errors to.
-   */
-  ErrorReporter errorReporter;
-
-  /**
-   * The mapping from the current library referenced sources to their
-   * modification times.
-   */
-  Map<Source, int> sourceTimeMap;
-
-  VerifyUnitTask(InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    RecordingErrorListener errorListener = new RecordingErrorListener();
-    Source source = getRequiredSource();
-    errorReporter = new ErrorReporter(errorListener, source);
-    //
-    // Prepare inputs.
-    //
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    CompilationUnitElement unitElement = unit.declaredElement;
-    LibraryElement libraryElement = unitElement.library;
-    if (libraryElement == null) {
-      throw new AnalysisException(
-          'VerifyUnitTask verifying a unit with no library: '
-          '${unitElement.source.fullName}');
-    }
-    List<PendingError> pendingErrors = getRequiredInput(PENDING_ERRORS_INPUT);
-    sourceTimeMap =
-        getRequiredInput(REFERENCED_SOURCE_MODIFICATION_TIME_MAP_INPUT);
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-    //
-    // Validate the directives.
-    //
-    validateDirectives(unit);
-    //
-    // Use the ConstantVerifier to compute errors.
-    //
-    ConstantVerifier constantVerifier = new ConstantVerifier(
-        errorReporter, libraryElement, typeProvider, context.declaredVariables);
-    unit.accept(constantVerifier);
-
-    //
-    // Compute inheritance and override errors.
-    //
-    var typeSystem = libraryElement.context.typeSystem;
-    var inheritanceManager = new InheritanceManager2(typeSystem);
-    var inheritanceOverrideVerifier = new InheritanceOverrideVerifier(
-        typeSystem, inheritanceManager, errorReporter);
-    inheritanceOverrideVerifier.verifyUnit(unit);
-
-    //
-    // Use the ErrorVerifier to compute errors.
-    //
-    ErrorVerifier errorVerifier = new ErrorVerifier(
-        errorReporter, libraryElement, typeProvider, inheritanceManager, false,
-        disableConflictingGenericsCheck: true);
-    unit.accept(errorVerifier);
-    //
-    // Convert the pending errors into actual errors.
-    //
-    for (PendingError pendingError in pendingErrors) {
-      errorListener.onError(pendingError.toAnalysisError());
-    }
-    //
-    // Record outputs.
-    //
-    outputs[VERIFY_ERRORS] = getUniqueErrors(errorListener.errors);
-  }
-
-  /**
-   * Check each directive in the given [unit] to see if the referenced source
-   * exists and report an error if it does not.
-   */
-  void validateDirectives(CompilationUnit unit) {
-    NodeList<Directive> directives = unit.directives;
-    int length = directives.length;
-    for (int i = 0; i < length; i++) {
-      Directive directive = directives[i];
-      if (directive is UriBasedDirective) {
-        validateReferencedSource(directive);
-      }
-    }
-  }
-
-  /**
-   * Check the given [directive] to see if the referenced source exists and
-   * report an error if it does not.
-   */
-  void validateReferencedSource(UriBasedDirectiveImpl directive) {
-    if (directive is NamespaceDirectiveImpl) {
-      for (Configuration configuration in directive.configurations) {
-        Source source = configuration.uriSource;
-        StringLiteral uriLiteral = configuration.uri;
-        String uriContent = uriLiteral?.stringValue?.trim();
-        if (source != null) {
-          int modificationTime = sourceTimeMap[source] ?? -1;
-          if (modificationTime >= 0) {
-            continue;
-          }
-        } else {
-          // Don't report errors already reported by ParseDartTask.resolveDirective
-          if (UriBasedDirectiveImpl.validateUri(
-                  directive is ImportDirective, uriLiteral, uriContent) !=
-              null) {
-            continue;
-          }
-        }
-        CompileTimeErrorCode errorCode =
-            CompileTimeErrorCode.URI_DOES_NOT_EXIST;
-        if (_isGenerated(source)) {
-          errorCode = CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED;
-        }
-        errorReporter.reportErrorForNode(errorCode, uriLiteral, [uriContent]);
-      }
-    }
-    Source source = directive.uriSource;
-    if (source != null) {
-      int modificationTime = sourceTimeMap[source] ?? -1;
-      if (modificationTime >= 0) {
-        return;
-      }
-    } else {
-      // Don't report errors already reported by ParseDartTask.resolveDirective
-      if (directive.validate() != null) {
-        return;
-      }
-    }
-    StringLiteral uriLiteral = directive.uri;
-    CompileTimeErrorCode errorCode = CompileTimeErrorCode.URI_DOES_NOT_EXIST;
-    if (_isGenerated(source)) {
-      errorCode = CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED;
-    }
-    errorReporter
-        .reportErrorForNode(errorCode, uriLiteral, [directive.uriContent]);
-  }
-
-  /**
-   * Return `true` if the given [source] refers to a file that is assumed to be
-   * generated.
-   */
-  bool _isGenerated(Source source) {
-    if (source == null) {
-      return false;
-    }
-    // TODO(brianwilkerson) Generalize this mechanism.
-    const List<String> suffixes = const <String>[
-      '.g.dart',
-      '.pb.dart',
-      '.pbenum.dart',
-      '.pbserver.dart',
-      '.pbjson.dart',
-      '.template.dart'
-    ];
-    String fullName = source.fullName;
-    for (String suffix in suffixes) {
-      if (fullName.endsWith(suffix)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{
-      'thisLibraryClosureIsReady': READY_RESOLVED_UNIT.of(unit.library),
-      UNIT_INPUT: RESOLVED_UNIT.of(unit),
-      REFERENCED_SOURCE_MODIFICATION_TIME_MAP_INPUT:
-          REFERENCED_SOURCES.of(unit.library).toMapOf(MODIFICATION_TIME),
-      PENDING_ERRORS_INPUT: PENDING_ERRORS.of(unit),
-      'requiredConstants': REQUIRED_CONSTANTS.of(unit).toListOf(CONSTANT_VALUE),
-      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
-    };
-  }
-
-  /**
-   * Create a [VerifyUnitTask] based on the given [target] in
-   * the given [context].
-   */
-  static VerifyUnitTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new VerifyUnitTask(context, target);
-  }
-}
-
-/**
- * A [TaskInput] whose value is a list of library sources exported directly
- * or indirectly by the target [Source].
- *
- * [resultDescriptor] is the type of result which should be produced for each
- * target [Source].
- */
-class _ExportSourceClosureTaskInput extends TaskInputImpl<List<Source>> {
-  final Source target;
-  final ResultDescriptor resultDescriptor;
-
-  _ExportSourceClosureTaskInput(this.target, this.resultDescriptor);
-
-  @override
-  TaskInputBuilder<List<Source>> createBuilder() =>
-      new _SourceClosureTaskInputBuilder(
-          target, _SourceClosureKind.EXPORT, resultDescriptor);
-}
-
-/**
- * An object holding either the name or the source associated with a part-of
- * directive.
- */
-class _NameOrSource {
-  final String name;
-
-  final Source source;
-
-  _NameOrSource(this.name, this.source);
-}
-
-/**
- * The kind of the source closure to build.
- */
-enum _SourceClosureKind { IMPORT, EXPORT, IMPORT_EXPORT }
-
-/**
- * A [TaskInputBuilder] used by [_ExportSourceClosureTaskInput].
- */
-class _SourceClosureTaskInputBuilder implements TaskInputBuilder<List<Source>> {
-  final _SourceClosureKind kind;
-  final Set<LibraryElement> _libraries = new HashSet<LibraryElement>();
-  final List<Source> _newSources = <Source>[];
-
-  @override
-  final ResultDescriptor currentResult;
-
-  Source currentTarget;
-
-  _SourceClosureTaskInputBuilder(
-      Source librarySource, this.kind, this.currentResult) {
-    _newSources.add(librarySource);
-  }
-
-  @override
-  void set currentValue(Object value) {
-    LibraryElement library = value;
-    if (_libraries.add(library)) {
-      if (kind == _SourceClosureKind.IMPORT ||
-          kind == _SourceClosureKind.IMPORT_EXPORT) {
-        List<ImportElement> imports = library.imports;
-        int length = imports.length;
-        for (int i = 0; i < length; i++) {
-          ImportElement importElement = imports[i];
-          Source importedSource = importElement.importedLibrary?.source;
-          if (importedSource != null) {
-            _newSources.add(importedSource);
-          }
-        }
-      }
-      if (kind == _SourceClosureKind.EXPORT ||
-          kind == _SourceClosureKind.IMPORT_EXPORT) {
-        List<ExportElement> exports = library.exports;
-        int length = exports.length;
-        for (int i = 0; i < length; i++) {
-          ExportElement exportElement = exports[i];
-          Source exportedSource = exportElement.exportedLibrary?.source;
-          if (exportedSource != null) {
-            _newSources.add(exportedSource);
-          }
-        }
-      }
-    }
-  }
-
-  @override
-  bool get flushOnAccess => false;
-
-  @override
-  List<Source> get inputValue {
-    return _libraries.map((LibraryElement library) => library.source).toList();
-  }
-
-  @override
-  void currentValueNotAvailable() {
-    // Nothing needs to be done.  moveNext() will simply go on to the next new
-    // source.
-  }
-
-  @override
-  bool moveNext() {
-    if (_newSources.isEmpty) {
-      return false;
-    }
-    currentTarget = _newSources.removeLast();
-    return true;
-  }
-}
diff --git a/pkg/analyzer/lib/src/task/dart_work_manager.dart b/pkg/analyzer/lib/src/task/dart_work_manager.dart
deleted file mode 100644
index 5aa9869..0000000
--- a/pkg/analyzer/lib/src/task/dart_work_manager.dart
+++ /dev/null
@@ -1,498 +0,0 @@
-// Copyright (c) 2015, 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';
-
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/generated/engine.dart'
-    show AnalysisEngine, AnalysisErrorInfo, CacheState, InternalAnalysisContext;
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/utilities_collection.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/dart.dart';
-
-/**
- * The manager for Dart specific analysis.
- */
-class DartWorkManager implements WorkManager {
-  /**
-   * The list of errors that are reported for raw Dart [Source]s.
-   */
-  static final List<ResultDescriptor<List<AnalysisError>>> _SOURCE_ERRORS =
-      <ResultDescriptor<List<AnalysisError>>>[
-    BUILD_DIRECTIVES_ERRORS,
-    BUILD_LIBRARY_ERRORS,
-    PARSE_ERRORS,
-    SCAN_ERRORS
-  ];
-
-  /**
-   * The list of errors that are reported for raw Dart [LibrarySpecificUnit]s.
-   */
-  static final List<ResultDescriptor<List<AnalysisError>>> _UNIT_ERRORS =
-      <ResultDescriptor<List<AnalysisError>>>[
-    HINTS,
-    LINTS,
-    LIBRARY_UNIT_ERRORS,
-    RESOLVE_DIRECTIVES_ERRORS,
-    RESOLVE_TYPE_NAMES_ERRORS,
-    RESOLVE_TYPE_BOUNDS_ERRORS,
-    RESOLVE_UNIT_ERRORS,
-    STRONG_MODE_ERRORS,
-    VARIABLE_REFERENCE_ERRORS,
-    VERIFY_ERRORS
-  ];
-
-  final InternalAnalysisContext context;
-
-  /**
-   * The [TargetedResult]s that should be computed with priority.
-   */
-  final LinkedHashSet<TargetedResult> priorityResultQueue =
-      new LinkedHashSet<TargetedResult>();
-
-  /**
-   * The sources whose kind we don't know yet.
-   */
-  final LinkedHashSet<Source> unknownSourceQueue = new LinkedHashSet<Source>();
-
-  /**
-   * The queue of library sources to process.
-   */
-  final LinkedHashSet<Source> librarySourceQueue = new LinkedHashSet<Source>();
-
-  /**
-   * A table mapping library sources to the part sources they include.
-   */
-  final HashMap<Source, List<Source>> libraryPartsMap =
-      new HashMap<Source, List<Source>>();
-
-  /**
-   * A table mapping part sources to the library sources that include them.
-   */
-  final HashMap<Source, List<Source>> partLibrariesMap =
-      new HashMap<Source, List<Source>>();
-
-  /**
-   * Initialize a newly created manager.
-   */
-  DartWorkManager(this.context) {
-    context.onResultInvalidated.listen((InvalidatedResult event) {
-      if (event.descriptor == LIBRARY_ERRORS_READY) {
-        CacheEntry entry = event.entry;
-        if (entry.explicitlyAdded &&
-            entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY) {
-          librarySourceQueue.add(entry.target);
-        }
-      }
-    });
-  }
-
-  /**
-   * Returns the correctly typed result of `context.analysisCache`.
-   */
-  AnalysisCache get analysisCache => context.analysisCache;
-
-  /**
-   * The partition that contains analysis results that are not shared with other
-   * contexts.
-   */
-  CachePartition get privateAnalysisCachePartition =>
-      context.privateAnalysisCachePartition;
-
-  /**
-   * Specifies that the client want the given [result] of the given [target]
-   * to be computed with priority.
-   */
-  void addPriorityResult(AnalysisTarget target, ResultDescriptor result) {
-    priorityResultQueue.add(new TargetedResult(target, result));
-  }
-
-  @override
-  void applyChange(List<Source> addedSources, List<Source> changedSources,
-      List<Source> removedSources) {
-    addedSources = addedSources.where(_isDartSource).toList();
-    changedSources = changedSources
-        .where(_isDartSource)
-        .where((source) => _needsComputing(source, SOURCE_KIND))
-        .toList();
-    removedSources = removedSources.where(_isDartSource).toList();
-    // unknown queue
-    unknownSourceQueue.addAll(addedSources);
-    unknownSourceQueue.addAll(changedSources);
-    unknownSourceQueue.removeAll(removedSources);
-    // library queue
-    librarySourceQueue.removeAll(changedSources);
-    librarySourceQueue.removeAll(removedSources);
-    // parts in libraries
-    for (Source changedSource in changedSources) {
-      _onLibrarySourceChangedOrRemoved(changedSource);
-    }
-    for (Source removedSource in removedSources) {
-      partLibrariesMap.remove(removedSource);
-      _onLibrarySourceChangedOrRemoved(removedSource);
-    }
-  }
-
-  @override
-  void applyPriorityTargets(List<AnalysisTarget> targets) {
-    // Unschedule the old targets.
-    List<TargetedResult> resultsToUnschedule = <TargetedResult>[];
-    for (TargetedResult result in priorityResultQueue) {
-      if (result.result == LIBRARY_ERRORS_READY) {
-        resultsToUnschedule.add(result);
-      }
-    }
-    priorityResultQueue.removeAll(resultsToUnschedule);
-    // Schedule new targets.
-    for (AnalysisTarget target in targets) {
-      if (_isDartSource(target)) {
-        SourceKind sourceKind = analysisCache.getValue(target, SOURCE_KIND);
-        if (sourceKind == SourceKind.UNKNOWN) {
-          addPriorityResult(target, SOURCE_KIND);
-        } else if (sourceKind == SourceKind.LIBRARY) {
-          _schedulePriorityLibrarySourceAnalysis(target);
-        } else if (sourceKind == SourceKind.PART) {
-          List<Source> libraries = context.getLibrariesContaining(target);
-          for (Source library in libraries) {
-            addPriorityResult(library, LIBRARY_ERRORS_READY);
-          }
-        }
-      }
-    }
-  }
-
-  @override
-  List<AnalysisError> getErrors(Source source) {
-    if (!_isDartSource(source)) {
-      return AnalysisError.NO_ERRORS;
-    }
-    // If analysis is finished, use all the errors.
-    if (analysisCache.getState(source, DART_ERRORS) == CacheState.VALID) {
-      return analysisCache.getValue(source, DART_ERRORS);
-    }
-    // If analysis is in progress, combine all known partial results.
-    List<AnalysisError> errors = <AnalysisError>[];
-    for (ResultDescriptor<List<AnalysisError>> descriptor in _SOURCE_ERRORS) {
-      errors.addAll(analysisCache.getValue(source, descriptor));
-    }
-    for (Source library in context.getLibrariesContaining(source)) {
-      LibrarySpecificUnit unit = new LibrarySpecificUnit(library, source);
-      for (ResultDescriptor<List<AnalysisError>> descriptor in _UNIT_ERRORS) {
-        errors.addAll(analysisCache.getValue(unit, descriptor));
-      }
-    }
-    return errors;
-  }
-
-  /**
-   * Returns libraries containing the given [part].
-   * Maybe empty, but not null.
-   */
-  List<Source> getLibrariesContainingPart(Source part) {
-    if (part.isInSystemLibrary) {
-      DartWorkManager sdkDartWorkManager = _getSdkDartWorkManager();
-      if (sdkDartWorkManager != this) {
-        return sdkDartWorkManager.getLibrariesContainingPart(part);
-      }
-    }
-    List<Source> libraries = partLibrariesMap[part];
-    libraries ??= _getLibrariesContainingPartFromResultProvider(part);
-    return libraries?.toList() ?? const <Source>[];
-  }
-
-  @override
-  TargetedResult getNextResult() {
-    // Try to find a priority result to compute.
-    while (priorityResultQueue.isNotEmpty) {
-      TargetedResult result = priorityResultQueue.first;
-      if (!_needsComputing(result.target, result.result)) {
-        priorityResultQueue.remove(result);
-        continue;
-      }
-      return result;
-    }
-    // Try to find a new library to analyze.
-    while (librarySourceQueue.isNotEmpty) {
-      Source librarySource = librarySourceQueue.first;
-      // Maybe done with this library.
-      if (!_needsComputing(librarySource, LIBRARY_ERRORS_READY)) {
-        librarySourceQueue.remove(librarySource);
-        continue;
-      }
-      // Analyze this library.
-      return new TargetedResult(librarySource, LIBRARY_ERRORS_READY);
-    }
-    // No libraries in the queue, check whether there are sources to organize.
-    while (unknownSourceQueue.isNotEmpty) {
-      Source source = unknownSourceQueue.first;
-      // Maybe done with this source.
-      if (!_needsComputing(source, SOURCE_KIND)) {
-        unknownSourceQueue.remove(source);
-        continue;
-      }
-      // Compute the kind of this source.
-      return new TargetedResult(source, SOURCE_KIND);
-    }
-    // TODO(scheglov) Report errors for parts that remained in the queue after
-    // all libraries had been processed.
-    // No results to compute.
-    return null;
-  }
-
-  @override
-  WorkOrderPriority getNextResultPriority() {
-    if (priorityResultQueue.isNotEmpty) {
-      return WorkOrderPriority.PRIORITY;
-    }
-    if (unknownSourceQueue.isNotEmpty || librarySourceQueue.isNotEmpty) {
-      return WorkOrderPriority.NORMAL;
-    }
-    return WorkOrderPriority.NONE;
-  }
-
-  /**
-   * Notifies the manager about analysis options changes.
-   */
-  void onAnalysisOptionsChanged() {
-    _invalidateAllLocalResolutionInformation(false);
-  }
-
-  /**
-   * Notifies the manager about [SourceFactory] changes.
-   */
-  void onSourceFactoryChanged() {
-    _invalidateAllLocalResolutionInformation(true);
-  }
-
-  @override
-  void resultsComputed(
-      AnalysisTarget target, Map<ResultDescriptor, dynamic> outputs) {
-    bool isDartSource = _isDartSource(target);
-    // Route SDK outputs to the SDK WorkManager.
-    if (isDartSource && target.source.isInSystemLibrary) {
-      DartWorkManager sdkWorkManager = _getSdkDartWorkManager();
-      if (sdkWorkManager != this) {
-        sdkWorkManager.resultsComputed(target, outputs);
-        return;
-      }
-    }
-    // Organize sources.
-    bool isDartLibrarySource = false;
-    if (isDartSource) {
-      Source source = target;
-      SourceKind kind = outputs[SOURCE_KIND];
-      if (kind != null) {
-        unknownSourceQueue.remove(source);
-        if (kind == SourceKind.LIBRARY) {
-          isDartLibrarySource = true;
-          if (context.prioritySources.contains(source)) {
-            _schedulePriorityLibrarySourceAnalysis(source);
-          } else {
-            bool needErrors = _shouldErrorsBeComputed(source);
-            if (needErrors) {
-              librarySourceQueue.add(target);
-            }
-          }
-        }
-      }
-    }
-    // Update parts in libraries.
-    if (isDartLibrarySource) {
-      Source library = target;
-      List<Source> includedParts = outputs[INCLUDED_PARTS] as List<Source>;
-      if (includedParts != null) {
-        libraryPartsMap[library] = includedParts;
-        for (Source part in includedParts) {
-          List<Source> libraries =
-              partLibrariesMap.putIfAbsent(part, () => <Source>[]);
-          if (!libraries.contains(library)) {
-            libraries.add(library);
-            _invalidateContainingLibraries(part);
-          }
-        }
-      }
-    }
-    // Update notice.
-    if (isDartSource) {
-      bool shouldSetErrors = false;
-      outputs.forEach((ResultDescriptor descriptor, value) {
-        if (descriptor == PARSED_UNIT && value != null) {
-          context.getNotice(target).parsedDartUnit = value;
-          shouldSetErrors = true;
-        }
-        if (descriptor == DART_ERRORS) {
-          shouldSetErrors = true;
-        }
-      });
-      if (shouldSetErrors) {
-        AnalysisErrorInfo info = context.getErrors(target);
-        context.getNotice(target).setErrors(info.errors, info.lineInfo);
-      }
-    }
-    if (target is LibrarySpecificUnit) {
-      Source source = target.source;
-      bool shouldSetErrors = false;
-      outputs.forEach((ResultDescriptor descriptor, value) {
-        if (descriptor == RESOLVED_UNIT && value != null) {
-          context.getNotice(source).resolvedDartUnit = value;
-          shouldSetErrors = true;
-        }
-      });
-      if (shouldSetErrors) {
-        AnalysisErrorInfo info = context.getErrors(source);
-        context.getNotice(source).setErrors(info.errors, info.lineInfo);
-      }
-    }
-  }
-
-  /**
-   * The given unit was incrementally resolved. Some of its error results might
-   * have been invalidated, so we schedule it for computing errors.
-   */
-  void unitIncrementallyResolved(Source librarySource, Source unitSource) {
-    librarySourceQueue.add(librarySource);
-  }
-
-  /**
-   * Ask the [context]'s result provider for [CONTAINING_LIBRARIES].
-   * Return the list of containing libraries, or `null` if unknown.
-   */
-  List<Source> _getLibrariesContainingPartFromResultProvider(Source part) {
-    CacheEntry cacheEntry = context.getCacheEntry(part);
-    bool knows = context.aboutToComputeResult(cacheEntry, CONTAINING_LIBRARIES);
-    if (knows) {
-      return cacheEntry.getValue(CONTAINING_LIBRARIES);
-    }
-    return null;
-  }
-
-  /**
-   * Return the SDK [DartWorkManager] or this one.
-   */
-  DartWorkManager _getSdkDartWorkManager() {
-    SourceFactory sourceFactory = context.sourceFactory;
-    InternalAnalysisContext sdkContext = sourceFactory.dartSdk.context;
-    if (sdkContext != context) {
-      for (WorkManager workManager in sdkContext.workManagers) {
-        if (workManager is DartWorkManager) {
-          return workManager;
-        }
-      }
-    }
-    return this;
-  }
-
-  /**
-   * Invalidate all of the resolution results computed by this context. The flag
-   * [invalidateUris] should be `true` if the cached results of converting URIs
-   * to source files should also be invalidated.
-   */
-  void _invalidateAllLocalResolutionInformation(bool invalidateUris) {
-    CachePartition partition = privateAnalysisCachePartition;
-    // Prepare targets and values to invalidate.
-    List<Source> dartSources = <Source>[];
-    List<LibrarySpecificUnit> unitTargets = <LibrarySpecificUnit>[];
-    MapIterator<AnalysisTarget, CacheEntry> iterator = partition.iterator();
-    while (iterator.moveNext()) {
-      AnalysisTarget target = iterator.key;
-      // Optionally gather Dart sources to invalidate URIs resolution.
-      if (invalidateUris && _isDartSource(target)) {
-        dartSources.add(target);
-      }
-      // LibrarySpecificUnit(s) are roots of Dart resolution.
-      // When one is invalidated, invalidation is propagated to all resolution.
-      if (target is LibrarySpecificUnit) {
-        unitTargets.add(target);
-        Source library = target.library;
-        if (context.exists(library)) {
-          CacheEntry entry = iterator.value;
-          if (entry.explicitlyAdded) {
-            librarySourceQueue.add(library);
-          }
-        }
-      }
-    }
-    // Invalidate targets and values.
-    unitTargets.forEach(partition.remove);
-    for (Source dartSource in dartSources) {
-      CacheEntry entry = partition.get(dartSource);
-      if (entry != null) {
-        // TODO(scheglov) we invalidate too much.
-        // Would be nice to invalidate just URLs resolution.
-        entry.setState(PARSED_UNIT, CacheState.INVALID);
-        entry.setState(IMPORTED_LIBRARIES, CacheState.INVALID);
-        entry.setState(EXPLICITLY_IMPORTED_LIBRARIES, CacheState.INVALID);
-        entry.setState(EXPORTED_LIBRARIES, CacheState.INVALID);
-        entry.setState(INCLUDED_PARTS, CacheState.INVALID);
-        entry.setState(LIBRARY_SPECIFIC_UNITS, CacheState.INVALID);
-        entry.setState(UNITS, CacheState.INVALID);
-      }
-    }
-  }
-
-  /**
-   * Invalidate  [CONTAINING_LIBRARIES] for the given [source].
-   * [CONTAINING_LIBRARIES] does not have dependencies, so we manage it here.
-   * The [source] may be a part, or a library whose contents is updated so
-   * will be a part.
-   */
-  void _invalidateContainingLibraries(Source source) {
-    CacheEntry entry = analysisCache.get(source);
-    if (entry != null) {
-      entry.setState(CONTAINING_LIBRARIES, CacheState.INVALID);
-    }
-  }
-
-  /**
-   * Returns `true` if the given [result] of the given [target] needs
-   * computing, i.e. it is not in the valid and not in the error state.
-   */
-  bool _needsComputing(AnalysisTarget target, ResultDescriptor result) {
-    CacheState state = analysisCache.getState(target, result);
-    return state != CacheState.VALID && state != CacheState.ERROR;
-  }
-
-  /**
-   * The given [library] source was changed or removed.
-   * Update [libraryPartsMap] and [partLibrariesMap].
-   */
-  void _onLibrarySourceChangedOrRemoved(Source library) {
-    List<Source> parts = libraryPartsMap.remove(library);
-    if (parts != null) {
-      for (Source part in parts) {
-        List<Source> libraries = partLibrariesMap[part];
-        if (libraries != null) {
-          libraries.remove(library);
-          _invalidateContainingLibraries(part);
-        }
-      }
-    }
-    _invalidateContainingLibraries(library);
-  }
-
-  /**
-   * Schedule computing [RESOLVED_UNIT] for the given [librarySource].
-   * If errors should be computed, then schedule [LIBRARY_ERRORS_READY] instead,
-   * it also computes [RESOLVED_UNIT] in process.
-   */
-  void _schedulePriorityLibrarySourceAnalysis(Source librarySource) {
-    bool needErrors = _shouldErrorsBeComputed(librarySource);
-    if (needErrors) {
-      addPriorityResult(librarySource, LIBRARY_ERRORS_READY);
-    } else {
-      var target = new LibrarySpecificUnit(librarySource, librarySource);
-      addPriorityResult(target, RESOLVED_UNIT);
-    }
-  }
-
-  bool _shouldErrorsBeComputed(Source source) =>
-      context.shouldErrorsBeAnalyzed(source);
-
-  static bool _isDartSource(AnalysisTarget target) {
-    return target is Source && AnalysisEngine.isDartFileName(target.fullName);
-  }
-}
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index feb81ad..8d9da75 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -198,10 +198,6 @@
     } else if (element is MapLiteralEntry) {
       checkAssignment(element.key, expectedKeyType);
       checkAssignment(element.value, expectedValueType);
-    } else if (element is SpreadElement) {
-      DartType mapType = typeProvider.mapType
-          .instantiate([expectedKeyType, expectedValueType]);
-      checkAssignment(element.expression, mapType);
     }
   }
 
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index 90dc42a..11b92be 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -252,6 +252,10 @@
     return _node(search, (n) => n is VariableDeclaration);
   }
 
+  VariableDeclarationList variableDeclarationList(String search) {
+    return _node(search, (n) => n is VariableDeclarationList);
+  }
+
   WhileStatement whileStatement(String search) {
     return _node(search, (n) => n is WhileStatement);
   }
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 1906862..81048a3 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.35.3
+version: 0.35.4
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
@@ -11,13 +11,12 @@
   collection: ^1.10.1
   convert: ^2.0.0
   crypto: '>=1.1.1 <3.0.0'
-  front_end: 0.1.13
+  front_end: 0.1.14
   glob: ^1.0.3
-  kernel: 0.3.13
+  kernel: 0.3.14
   meta: ^1.0.2
   package_config: '>=0.1.5 <2.0.0'
   path: '>=0.9.0 <2.0.0'
-  plugin: ^0.2.0
   pub_semver: ^1.4.2
   source_span: ^1.2.0
   watcher: '>=0.9.6 <0.10.0'
diff --git a/pkg/analyzer/test/generated/analysis_context_factory.dart b/pkg/analyzer/test/generated/analysis_context_factory.dart
index 2b99d3b..4ee79f0 100644
--- a/pkg/analyzer/test/generated/analysis_context_factory.dart
+++ b/pkg/analyzer/test/generated/analysis_context_factory.dart
@@ -24,6 +24,7 @@
 import 'package:analyzer/src/generated/testing/test_type_provider.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/string_source.dart';
+import 'package:analyzer/src/summary/summary_sdk.dart';
 import 'package:test/test.dart';
 
 /**
@@ -104,7 +105,6 @@
     TestTypeProvider provider = new TestTypeProvider();
     CompilationUnitElementImpl coreUnit = new CompilationUnitElementImpl();
     Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE);
-    coreContext.setContents(coreSource, "");
     coreUnit.librarySource = coreUnit.source = coreSource;
     ClassElementImpl overrideClassElement =
         ElementFactory.classElement2("_Override");
@@ -185,7 +185,6 @@
         AstTestFactory.libraryIdentifier2(["dart", "async"]));
     CompilationUnitElementImpl asyncUnit = new CompilationUnitElementImpl();
     Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
-    coreContext.setContents(asyncSource, "");
     asyncUnit.librarySource = asyncUnit.source = asyncSource;
     asyncLibrary.definingCompilationUnit = asyncUnit;
     // Future<T>
@@ -278,7 +277,6 @@
     //
     CompilationUnitElementImpl htmlUnit = new CompilationUnitElementImpl();
     Source htmlSource = sourceFactory.forUri(DartSdk.DART_HTML);
-    coreContext.setContents(htmlSource, "");
     htmlUnit.librarySource = htmlUnit.source = htmlSource;
     ClassElementImpl elementElement = ElementFactory.classElement2("Element");
     InterfaceType elementType = elementElement.type;
@@ -339,7 +337,6 @@
     //
     CompilationUnitElementImpl mathUnit = new CompilationUnitElementImpl();
     Source mathSource = sourceFactory.forUri(_DART_MATH);
-    coreContext.setContents(mathSource, "");
     mathUnit.librarySource = mathUnit.source = mathSource;
     FunctionElement cosElement = ElementFactory.functionElement3(
         "cos",
@@ -396,13 +393,6 @@
         coreContext, null, AstTestFactory.libraryIdentifier2(["dart", "math"]));
     mathLibrary.definingCompilationUnit = mathUnit;
     //
-    // Set empty sources for the rest of the libraries.
-    //
-    Source source = sourceFactory.forUri(_DART_INTERCEPTORS);
-    coreContext.setContents(source, "");
-    source = sourceFactory.forUri(_DART_JS_HELPER);
-    coreContext.setContents(source, "");
-    //
     // Record the elements.
     //
     Map<Source, LibraryElement> elementMap =
@@ -423,7 +413,11 @@
       library.exportNamespace = namespace;
       library.publicNamespace = namespace;
     }
-    context.recordLibraryElements(elementMap);
+
+    context.typeProvider = SummaryTypeProvider()
+      ..initializeCore(coreLibrary)
+      ..initializeAsync(asyncLibrary);
+
     // Create the synthetic element for `loadLibrary`.
     for (LibraryElementImpl library in elementMap.values) {
       library.createLoadLibraryFunction(context.typeProvider);
diff --git a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_driver_test.dart b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_driver_test.dart
deleted file mode 100644
index 12bc001..0000000
--- a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_driver_test.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-// 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.
-
-import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'checked_mode_compile_time_error_code.dart';
-import 'resolver_test_case.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(CheckedModeCompileTimeErrorCodeTest_Driver);
-    defineReflectiveTests(SetElementTypeNotAssignableTest);
-    defineReflectiveTests(SetElementTypeNotAssignableWithCodeAsUITest);
-  });
-}
-
-@reflectiveTest
-class CheckedModeCompileTimeErrorCodeTest_Driver
-    extends CheckedModeCompileTimeErrorCodeTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
-
-@reflectiveTest
-class SetElementTypeNotAssignableTest extends ResolverTestCase {
-  @override
-  bool get enableNewAnalysisDriver => true;
-
-  test_simple() async {
-    Source source = addSource("var v = const <String>{42};");
-    await computeAnalysisResult(source);
-    // TODO(brianwilkerson) Fix this so that only one error is produced.
-    assertErrors(source, [
-      CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE,
-      StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE
-    ]);
-    verify([source]);
-  }
-}
-
-@reflectiveTest
-class SetElementTypeNotAssignableWithCodeAsUITest extends ResolverTestCase {
-  @override
-  List<String> get enabledExperiments => ['spread-collections'];
-
-  @override
-  bool get enableNewAnalysisDriver => true;
-
-  test_simple_const() async {
-    // TODO(brianwilkerson) This test is not dependent on the experiments and
-    //  should be moved when these tests are cleaned up.
-    Source source = addSource("var v = const <String>{42};");
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
-  }
-
-  test_simple_nonConst() async {
-    // TODO(brianwilkerson) This test is not dependent on the experiments and
-    //  should be moved when these tests are cleaned up.
-    Source source = addSource("var v = <String>{42};");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
-  }
-
-  test_spread_valid_const() async {
-    await assertNoErrorsInCode('''
-var v = const <String>{...['a', 'b']};
-''');
-  }
-
-  test_spread_valid_nonConst() async {
-    await assertNoErrorsInCode('''
-var v = <String>{...['a', 'b']};
-''');
-  }
-}
diff --git a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code.dart b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
similarity index 95%
rename from pkg/analyzer/test/generated/checked_mode_compile_time_error_code.dart
rename to pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
index 66185d3..46643f5 100644
--- a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code.dart
+++ b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
@@ -5,13 +5,24 @@
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'resolver_test_case.dart';
 
-abstract class CheckedModeCompileTimeErrorCodeTest extends ResolverTestCase {
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(CheckedModeCompileTimeErrorCodeTest);
+  });
+}
+
+@reflectiveTest
+class CheckedModeCompileTimeErrorCodeTest extends ResolverTestCase {
   @override
   AnalysisOptions get defaultAnalysisOptions => new AnalysisOptionsImpl();
 
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   test_assertion_throws() async {
     Source source = addSource(r'''
 class A {
@@ -479,8 +490,7 @@
   test_listElementTypeNotAssignable() async {
     Source source = addSource("var v = const <String> [42];");
     await computeAnalysisResult(source);
-    assertErrors(source,
-        [CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+    assertErrors(source, [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
 
@@ -495,16 +505,6 @@
     verify([source]);
   }
 
-  test_mapKeyTypeNotAssignable() async {
-    Source source = addSource("var v = const <String, int > {1 : 2};");
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
-      StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE
-    ]);
-    verify([source]);
-  }
-
   test_mapLiteral_inferredKeyType() async {
     Source source = addSource('''
 const Object x = {1: 1};
@@ -527,16 +527,6 @@
     verify([source]);
   }
 
-  test_mapValueTypeNotAssignable() async {
-    Source source = addSource("var v = const <String, String> {'a' : 2};");
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
-      StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE
-    ]);
-    verify([source]);
-  }
-
   test_parameterAssignable_null() async {
     // Null is assignable to anything.
     Source source = addSource(r'''
diff --git a/pkg/analyzer/test/generated/compile_time_error_code.dart b/pkg/analyzer/test/generated/compile_time_error_code.dart
index b14a030..4a4f04d 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code.dart
@@ -1234,79 +1234,6 @@
     verify([source]);
   }
 
-  test_constMapKeyTypeImplementsEquals_direct() async {
-    Source source = addSource(r'''
-class A {
-  const A();
-  operator ==(other) => false;
-}
-main() {
-  const {const A() : 0};
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
-    verify([source]);
-  }
-
-  test_constMapKeyTypeImplementsEquals_dynamic() async {
-    // Note: static type of B.a is "dynamic", but actual type of the const
-    // object is A.  We need to make sure we examine the actual type when
-    // deciding whether there is a problem with operator==.
-    Source source = addSource(r'''
-class A {
-  const A();
-  operator ==(other) => false;
-}
-class B {
-  static const a = const A();
-}
-main() {
-  const {B.a : 0};
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
-    verify([source]);
-  }
-
-  test_constMapKeyTypeImplementsEquals_factory() async {
-    Source source = addSource(r'''
-class A { const factory A() = B; }
-
-class B implements A {
-  const B();
-
-  operator ==(o) => true;
-}
-
-main() {
-  var m = const { const A(): 42 };
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
-    verify([source]);
-  }
-
-  test_constMapKeyTypeImplementsEquals_super() async {
-    Source source = addSource(r'''
-class A {
-  const A();
-  operator ==(other) => false;
-}
-class B extends A {
-  const B();
-}
-main() {
-  const {const B() : 0};
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
-    verify([source]);
-  }
-
   test_constWithInvalidTypeParameters() async {
     Source source = addSource(r'''
 class A {
@@ -1491,7 +1418,6 @@
     await computeAnalysisResult(source);
     assertErrors(source, [
       ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
-      StrongModeCode.INVALID_CAST_LITERAL_MAP
     ]);
     verify([source]);
   }
@@ -1503,7 +1429,6 @@
     await computeAnalysisResult(source);
     assertErrors(source, [
       ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
-      StrongModeCode.INVALID_CAST_LITERAL_MAP
     ]);
     verify([source]);
   }
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
similarity index 90%
rename from pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart
rename to pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 1ea8ecc..2389261 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -13,7 +13,8 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(CompileTimeErrorCodeTest_Driver);
+    defineReflectiveTests(CompileTimeErrorCodeTest);
+    defineReflectiveTests(CompileTimeErrorCodeTest_WithUIAsCode);
     defineReflectiveTests(ConstSetElementTypeImplementsEqualsTest);
     defineReflectiveTests(ControlFlowCollectionsTest);
     defineReflectiveTests(InvalidTypeArgumentInConstSetTest);
@@ -23,7 +24,7 @@
 }
 
 @reflectiveTest
-class CompileTimeErrorCodeTest_Driver extends CompileTimeErrorCodeTestBase {
+class CompileTimeErrorCodeTest extends CompileTimeErrorCodeTestBase {
   @override
   bool get enableNewAnalysisDriver => true;
 
@@ -101,6 +102,42 @@
 }
 
 @reflectiveTest
+class CompileTimeErrorCodeTest_WithUIAsCode extends ResolverTestCase {
+  @override
+  List<String> get enabledExperiments =>
+      [EnableString.control_flow_collections, EnableString.spread_collections];
+
+  @override
+  bool get enableNewAnalysisDriver => true;
+
+  test_defaultValueInFunctionTypeAlias_new_named() async {
+    // This test used to fail with UI as code enabled. Test the fix here.
+    Source source = addSource('''
+typedef F = int Function({Map<String, String> m: const {}});
+''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [
+      ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
+    ]);
+    verify([source]);
+  }
+
+  test_defaultValueInFunctionTypeAlias_new_named_ambiguous() async {
+    // Test that the strong checker does not crash when given an ambiguous
+    // set or map literal.
+    Source source = addSource('''
+typedef F = int Function({Object m: const {1, 2: 3}});
+''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [
+      ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
+      CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH,
+    ]);
+    verify([source]);
+  }
+}
+
+@reflectiveTest
 class ConstSetElementTypeImplementsEqualsTest extends ResolverTestCase {
   @override
   bool get enableNewAnalysisDriver => true;
@@ -415,44 +452,13 @@
   test_listElementTypeNotAssignable_const() async {
     Source source = addSource("var v = const <String>[42];");
     await computeAnalysisResult(source);
-    assertErrors(source,
-        [CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
-  }
-
-  test_listElementTypeNotAssignable_nonConst() async {
-    Source source = addSource("var v = <String> [42];");
-    await computeAnalysisResult(source);
     assertErrors(source, [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
 
-  test_mapKeyTypeNotAssignable_const() async {
-    Source source = addSource("var v = const <String, int >{1 : 2};");
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
-  }
-
-  test_mapKeyTypeNotAssignable_nonConst() async {
-    Source source = addSource("var v = <String, int >{1 : 2};");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
-  }
-
   test_mapValueTypeNotAssignable_const() async {
     Source source = addSource("var v = const <String, String>{'a' : 2};");
     await computeAnalysisResult(source);
-    assertErrors(source,
-        [CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
-  }
-
-  test_mapValueTypeNotAssignable_nonConst() async {
-    Source source = addSource("var v = <String, String>{'a' : 2};");
-    await computeAnalysisResult(source);
     assertErrors(source, [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -533,14 +539,6 @@
   test_setElementTypeNotAssignable_const() async {
     Source source = addSource("var v = const <String>{42};");
     await computeAnalysisResult(source);
-    assertErrors(source,
-        [CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
-  }
-
-  test_setElementTypeNotAssignable_nonConst() async {
-    Source source = addSource("var v = <String>{42};");
-    await computeAnalysisResult(source);
     assertErrors(source, [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
diff --git a/pkg/analyzer/test/generated/error_suppression_driver_test.dart b/pkg/analyzer/test/generated/error_suppression_driver_test.dart
deleted file mode 100644
index 77e0f57..0000000
--- a/pkg/analyzer/test/generated/error_suppression_driver_test.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2017, 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 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'error_suppression.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(ErrorSuppressionTest_Driver);
-  });
-}
-
-@reflectiveTest
-class ErrorSuppressionTest_Driver extends ErrorSuppressionTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/generated/error_suppression.dart b/pkg/analyzer/test/generated/error_suppression_test.dart
similarity index 94%
rename from pkg/analyzer/test/generated/error_suppression.dart
rename to pkg/analyzer/test/generated/error_suppression_test.dart
index 80027a4..8eb21cf 100644
--- a/pkg/analyzer/test/generated/error_suppression.dart
+++ b/pkg/analyzer/test/generated/error_suppression_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
@@ -6,10 +6,21 @@
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'resolver_test_case.dart';
 
-abstract class ErrorSuppressionTest extends ResolverTestCase {
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ErrorSuppressionTest);
+  });
+}
+
+@reflectiveTest
+class ErrorSuppressionTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   String get ignoredCode => 'const_initialized_with_non_constant_value';
 
   List<ErrorCode> get reportedCodes => [
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 9182c50..eebd8bb 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -1356,78 +1356,6 @@
     verify([source]);
   }
 
-  test_missingReturn_async() async {
-    Source source = addSource('''
-import 'dart:async';
-Future<int> f() async {}
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.MISSING_RETURN]);
-    verify([source]);
-  }
-
-  test_missingReturn_factory() async {
-    Source source = addSource(r'''
-class A {
-  factory A() {}
-}
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.MISSING_RETURN]);
-    verify([source]);
-  }
-
-  test_missingReturn_function() async {
-    Source source = addSource("int f() {}");
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.MISSING_RETURN]);
-    verify([source]);
-  }
-
-  test_missingReturn_method() async {
-    Source source = addSource(r'''
-class A {
-  int m() {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.MISSING_RETURN]);
-    verify([source]);
-  }
-
-  test_missingReturn_method_inferred() async {
-    Source source = addSource(r'''
-abstract class A {
-  int m();
-}
-class B extends A {
-  m() {}
-}
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.MISSING_RETURN]);
-    verify([source]);
-  }
-
-  test_no_missingReturn_async_futureOrVoid() async {
-    Source source = addSource('''
-import 'dart:async';
-FutureOr<void> f(Future f) async {}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_no_missingReturn_async_futureVoid() async {
-    Source source = addSource('''
-import 'dart:async';
-Future<void> f() async {}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
   test_nullAwareBeforeOperator_minus() async {
     Source source = addSource(r'''
 m(x) {
diff --git a/pkg/analyzer/test/generated/invalid_code_driver_test.dart b/pkg/analyzer/test/generated/invalid_code_driver_test.dart
deleted file mode 100644
index b457f67..0000000
--- a/pkg/analyzer/test/generated/invalid_code_driver_test.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2017, 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 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'invalid_code.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(InvalidCodeTest_Driver);
-  });
-}
-
-@reflectiveTest
-class InvalidCodeTest_Driver extends InvalidCodeTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/generated/invalid_code.dart b/pkg/analyzer/test/generated/invalid_code_test.dart
similarity index 83%
rename from pkg/analyzer/test/generated/invalid_code.dart
rename to pkg/analyzer/test/generated/invalid_code_test.dart
index b7e6944..23bcf7d 100644
--- a/pkg/analyzer/test/generated/invalid_code.dart
+++ b/pkg/analyzer/test/generated/invalid_code_test.dart
@@ -7,19 +7,30 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'resolver_test_case.dart';
 
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InvalidCodeTest);
+  });
+}
+
 /**
  * Tests for various end-to-end cases when invalid code caused exceptions
  * in one or another Analyzer subsystem. We are not interested not in specific
  * errors generated, but we want to make sure that there is at least one,
  * and analysis finishes without exceptions.
  */
-abstract class InvalidCodeTest extends ResolverTestCase {
+@reflectiveTest
+class InvalidCodeTest extends ResolverTestCase {
   @override
   AnalysisOptions get defaultAnalysisOptions => new AnalysisOptionsImpl();
 
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   /**
    * This code results in a method with the empty name, and the default
    * constructor, which also has the empty name. The `Map` in `f` initializer
diff --git a/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
deleted file mode 100644
index af22a4a..0000000
--- a/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2017, 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 'package:analyzer/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'non_error_resolver.dart';
-import 'resolver_test_case.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(NonErrorResolverTest_Driver);
-    defineReflectiveTests(NonErrorResolverTest_WithUiAsCode);
-    defineReflectiveTests(NonConstantValueInInitializer);
-  });
-}
-
-@reflectiveTest
-class NonConstantValueInInitializer extends ResolverTestCase {
-  @override
-  List<String> get enabledExperiments => [EnableString.constant_update_2018];
-
-  @override
-  bool get enableNewAnalysisDriver => true;
-
-  test_intLiteralInDoubleContext_const_exact() async {
-    Source source = addSource(r'''
-const double x = 0;
-class C {
-  const C(double y) : assert(y is double), assert(x is double);
-}
-@C(0)
-@C(-0)
-@C(0x0)
-@C(-0x0)
-void main() {
-  const C(0);
-  const C(-0);
-  const C(0x0);
-  const C(-0x0);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_isCheckInConstAssert() async {
-    Source source = addSource(r'''
-class C {
-  const C() : assert(1 is int);
-}
-
-void main() {
-  const C();
-}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-}
-
-@reflectiveTest
-class NonErrorResolverTest_Driver extends NonErrorResolverTestBase {
-  @override
-  bool get enableNewAnalysisDriver => true;
-
-  @override
-  @failingTest
-  test_null_callOperator() {
-    return super.test_null_callOperator();
-  }
-}
-
-@reflectiveTest
-class NonErrorResolverTest_WithUiAsCode extends NonErrorResolverTest_Driver {
-  @override
-  List<String> get enabledExperiments =>
-      [EnableString.spread_collections, EnableString.control_flow_collections];
-}
diff --git a/pkg/analyzer/test/generated/non_error_resolver.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
similarity index 98%
rename from pkg/analyzer/test/generated/non_error_resolver.dart
rename to pkg/analyzer/test/generated/non_error_resolver_test.dart
index bba51ce..0c3d5cb 100644
--- a/pkg/analyzer/test/generated/non_error_resolver.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -8,29 +8,78 @@
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
+import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'resolver_test_case.dart';
 
-class NonErrorResolverTestBase extends ResolverTestCase {
-  @override
-  AnalysisOptions get defaultAnalysisOptions => new AnalysisOptionsImpl();
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(NonErrorResolverTest);
+    defineReflectiveTests(NonErrorResolverWithUiAsCodeTest);
+    defineReflectiveTests(NonConstantValueInInitializer);
+  });
+}
 
-  fail_undefinedEnumConstant() async {
+@reflectiveTest
+class NonConstantValueInInitializer extends ResolverTestCase {
+  @override
+  List<String> get enabledExperiments => [EnableString.constant_update_2018];
+
+  @override
+  bool get enableNewAnalysisDriver => true;
+
+  test_intLiteralInDoubleContext_const_exact() async {
     Source source = addSource(r'''
-enum E { ONE }
-E e() {
-  return E.TWO;
+const double x = 0;
+class C {
+  const C(double y) : assert(y is double), assert(x is double);
+}
+@C(0)
+@C(-0)
+@C(0x0)
+@C(-0x0)
+void main() {
+  const C(0);
+  const C(-0);
+  const C(0x0);
+  const C(-0x0);
 }''');
     await computeAnalysisResult(source);
     assertNoErrors(source);
     verify([source]);
   }
 
+  test_isCheckInConstAssert() async {
+    Source source = addSource(r'''
+class C {
+  const C() : assert(1 is int);
+}
+
+void main() {
+  const C();
+}
+''');
+    await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+}
+
+@reflectiveTest
+class NonErrorResolverTest extends ResolverTestCase {
+  @override
+  AnalysisOptions get defaultAnalysisOptions => new AnalysisOptionsImpl();
+
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   test_ambiguousExport() async {
     Source source = addSource(r'''
 library L;
@@ -1210,28 +1259,6 @@
     verify([source]);
   }
 
-  test_constMapKeyExpressionTypeImplementsEquals_abstract() async {
-    Source source = addSource(r'''
-abstract class B {
-  final id;
-  const B(this.id);
-  String toString() => 'C($id)';
-  /** Equality is identity equality, the id isn't used. */
-  bool operator==(Object other);
-  }
-
-class C extends B {
-  const C(id) : super(id);
-}
-
-Map getMap() {
-  return const { const C(0): 'Map: 0' };
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
   test_constNotInitialized_field() async {
     Source source = addSource(r'''
 class A {
@@ -1750,6 +1777,20 @@
     verify([source]);
   }
 
+  test_for_in_scope() async {
+    Source source = addSource('''
+main() {
+  List<List<int>> x = [[1]];
+  for (int x in x.first) {
+    print(x.isEven);
+  }
+}
+''');
+    await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   test_forEach_genericFunctionType() async {
     Source source = addSource(r'''
 main() {
@@ -4113,17 +4154,6 @@
     verify([source]);
   }
 
-  test_nonConstMapKey_constField() async {
-    Source source = addSource(r'''
-main() {
-  const {double.INFINITY: 0};
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source,
-        [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
-    verify([source]);
-  }
-
   test_nonConstMapValue_constField() async {
     Source source = addSource(r'''
 main() {
@@ -4395,6 +4425,7 @@
     verify([source]);
   }
 
+  @failingTest
   test_null_callOperator() async {
     Source source = addSource(r'''
 main() {
@@ -5510,6 +5541,18 @@
     verify([source]);
   }
 
+  @failingTest
+  test_undefinedEnumConstant() async {
+    Source source = addSource(r'''
+enum E { ONE }
+E e() {
+  return E.TWO;
+}''');
+    await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   test_undefinedGetter_static_conditionalAccess() async {
     // The conditional access operator '?.' can be used to access static
     // fields.
@@ -6039,3 +6082,10 @@
     await _check_wrongNumberOfParametersForOperator(name, "a");
   }
 }
+
+@reflectiveTest
+class NonErrorResolverWithUiAsCodeTest extends NonErrorResolverTest {
+  @override
+  List<String> get enabledExperiments =>
+      [EnableString.spread_collections, EnableString.control_flow_collections];
+}
diff --git a/pkg/analyzer/test/generated/non_hint_code_driver_test.dart b/pkg/analyzer/test/generated/non_hint_code_driver_test.dart
deleted file mode 100644
index c7c53cf..0000000
--- a/pkg/analyzer/test/generated/non_hint_code_driver_test.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2017, 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 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'non_hint_code.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(NonHintCodeTest_Driver);
-  });
-}
-
-@reflectiveTest
-class NonHintCodeTest_Driver extends NonHintCodeTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/generated/non_hint_code.dart b/pkg/analyzer/test/generated/non_hint_code_test.dart
similarity index 87%
rename from pkg/analyzer/test/generated/non_hint_code.dart
rename to pkg/analyzer/test/generated/non_hint_code_test.dart
index 75e1a3d..359dd7f 100644
--- a/pkg/analyzer/test/generated/non_hint_code.dart
+++ b/pkg/analyzer/test/generated/non_hint_code_test.dart
@@ -5,31 +5,20 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'resolver_test_case.dart';
 
-abstract class NonHintCodeTest extends ResolverTestCase {
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(NonHintCodeTest);
+  });
+}
+
+@reflectiveTest
+class NonHintCodeTest extends ResolverTestCase {
   @override
-  void reset() {
-    super.resetWith(packages: [
-      [
-        'meta',
-        r'''
-library meta;
-
-const _AlwaysThrows alwaysThrows = const _AlwaysThrows();
-const _Literal literal = const _Literal();
-
-class _AlwaysThrows {
-  const _AlwaysThrows();
-}
-class _Literal {
-  const _Literal();
-}
-'''
-      ]
-    ]);
-  }
+  bool get enableNewAnalysisDriver => true;
 
   test_async_future_object_without_return() async {
     Source source = addSource('''
@@ -147,64 +136,6 @@
     verify([source]);
   }
 
-  test_missingReturn_alwaysThrows() async {
-    Source source = addSource(r'''
-import 'package:meta/meta.dart';
-
-@alwaysThrows
-void a() {
-  throw 'msg';
-}
-
-int f() {
-  a();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_missingReturn_emptyFunctionBody() async {
-    Source source = addSource(r'''
-abstract class A {
-  int m();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_missingReturn_expressionFunctionBody() async {
-    Source source = addSource("int f() => 0;");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_missingReturn_futureVoidReturnType() async {
-    Source source = addSource('''
-import 'dart:async';
-Future<void> f() async {}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_missingReturn_noReturnType() async {
-    Source source = addSource("f() {}");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_missingReturn_voidReturnType() async {
-    Source source = addSource("void f() {}");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
   test_nullAwareInCondition_for_noCondition() async {
     Source source = addSource(r'''
 m(x) {
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index f90204a..f5becf3 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -1356,11 +1356,14 @@
 
   @override
   CompilationUnit parseCompilationUnit(String content,
-      {List<ErrorCode> codes, List<ExpectedError> errors}) {
+      {List<ErrorCode> codes,
+      List<ExpectedError> errors,
+      bool enableControlFlowCollections}) {
     GatheringErrorListener listener =
         new GatheringErrorListener(checkRanges: true);
 
-    CompilationUnit unit = parseCompilationUnit2(content, listener);
+    CompilationUnit unit = parseCompilationUnit2(content, listener,
+        enableControlFlowCollections: enableControlFlowCollections);
 
     // Assert and return result
     if (codes != null) {
@@ -1375,7 +1378,8 @@
   }
 
   CompilationUnit parseCompilationUnit2(
-      String content, GatheringErrorListener listener) {
+      String content, GatheringErrorListener listener,
+      {bool enableControlFlowCollections}) {
     var source = new StringSource(content, 'parser_test_StringSource.dart');
 
     void reportError(
@@ -1404,6 +1408,9 @@
     parser.listener = astBuilder;
     astBuilder.parser = parser;
     astBuilder.allowNativeClause = allowNativeClause;
+    if (enableControlFlowCollections != null) {
+      astBuilder.enableControlFlowCollections = enableControlFlowCollections;
+    }
     parser.parseUnit(_fastaTokens);
     CompilationUnitImpl unit = astBuilder.pop();
     unit.localDeclarations = astBuilder.localDeclarations;
diff --git a/pkg/analyzer/test/generated/resolver_driver_test.dart b/pkg/analyzer/test/generated/resolver_driver_test.dart
deleted file mode 100644
index 74af34f..0000000
--- a/pkg/analyzer/test/generated/resolver_driver_test.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2017, 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 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'resolver_test.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(StrictModeTest_Driver);
-    defineReflectiveTests(TypePropagationTest_Driver);
-  });
-}
-
-@reflectiveTest
-class StrictModeTest_Driver extends StrictModeTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
-
-@reflectiveTest
-class TypePropagationTest_Driver extends TypePropagationTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 5d5b657..772ed2b 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -45,6 +45,8 @@
     defineReflectiveTests(LibraryScopeTest);
     defineReflectiveTests(PrefixedNamespaceTest);
     defineReflectiveTests(ScopeTest);
+    defineReflectiveTests(StrictModeTest);
+    defineReflectiveTests(TypePropagationTest);
     defineReflectiveTests(TypeProviderImplTest);
     defineReflectiveTests(TypeResolverVisitorTest);
   });
@@ -571,18 +573,10 @@
  * The class `StrictModeTest` contains tests to ensure that the correct errors and warnings
  * are reported when the analysis engine is run in strict mode.
  */
-abstract class StrictModeTest extends ResolverTestCase {
-  fail_for() async {
-    Source source = addSource(r'''
-int f(List<int> list) {
-  num sum = 0;
-  for (num i = 0; i < list.length; i++) {
-    sum += list[i];
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
-  }
+@reflectiveTest
+class StrictModeTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
 
   @override
   void setUp() {
@@ -637,6 +631,19 @@
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
 
+  @failingTest
+  test_for() async {
+    Source source = addSource(r'''
+int f(List<int> list) {
+  num sum = 0;
+  for (num i = 0; i < list.length; i++) {
+    sum += list[i];
+  }
+}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+  }
+
   test_forEach() async {
     Source source = addSource(r'''
 int f(List<int> list) {
@@ -722,16 +729,10 @@
   }
 }
 
-abstract class TypePropagationTest extends ResolverTestCase {
-  fail_propagatedReturnType_functionExpression() async {
-    // TODO(scheglov) disabled because we don't resolve function expression
-    String code = r'''
-main() {
-  var v = (() {return 42;})();
-}''';
-    CompilationUnit unit = await resolveSource(code);
-    assertAssignedType(code, unit, typeProvider.dynamicType);
-  }
+@reflectiveTest
+class TypePropagationTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
 
   test_assignment_null() async {
     String code = r'''
@@ -1000,6 +1001,17 @@
     expect(methodInvoke.staticType, typeProvider.dynamicType);
   }
 
+  @failingTest
+  test_propagatedReturnType_functionExpression() async {
+    // TODO(scheglov) disabled because we don't resolve function expression
+    String code = r'''
+main() {
+  var v = (() {return 42;})();
+}''';
+    CompilationUnit unit = await resolveSource(code);
+    assertAssignedType(code, unit, typeProvider.dynamicType);
+  }
+
   /**
    * Return the resolved unit for the given [source].
    *
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart
index a682c9d..021bac0 100644
--- a/pkg/analyzer/test/generated/resolver_test_case.dart
+++ b/pkg/analyzer/test/generated/resolver_test_case.dart
@@ -574,13 +574,10 @@
       "test");
 
   /**
-   * Create a source object representing a file with the given [fileName] and
-   * give it an empty content. Return the source that was created.
+   * Return a source object representing a file with the given [fileName].
    */
   Source createNamedSource(String fileName) {
-    Source source = getFile(fileName).createSource();
-    analysisContext2.setContents(source, '');
-    return source;
+    return getFile(fileName).createSource();
   }
 
   /**
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_driver_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_driver_test.dart
deleted file mode 100644
index 9aa12df..0000000
--- a/pkg/analyzer/test/generated/static_type_analyzer_driver_test.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2017, 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 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'static_type_analyzer_test.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(StaticTypeAnalyzer2Test_Driver);
-  });
-}
-
-@reflectiveTest
-class StaticTypeAnalyzer2Test_Driver extends StaticTypeAnalyzer2Test {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index 020414b..dcdaa61 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -34,6 +34,7 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(SetLiteralsTest);
     defineReflectiveTests(StaticTypeAnalyzerTest);
+    defineReflectiveTests(StaticTypeAnalyzer2Test);
     defineReflectiveTests(StaticTypeAnalyzer3Test);
     defineReflectiveTests(StaticTypeAnalyzerWithSetLiteralsTest);
     defineReflectiveTests(StaticTypeAnalyzerWithStrictInferenceTest);
@@ -70,7 +71,11 @@
 /**
  * Like [StaticTypeAnalyzerTest], but as end-to-end tests.
  */
-abstract class StaticTypeAnalyzer2Test extends StaticTypeAnalyzer2TestShared {
+@reflectiveTest
+class StaticTypeAnalyzer2Test extends StaticTypeAnalyzer2TestShared {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   test_FunctionExpressionInvocation_block() async {
     String code = r'''
 main() {
@@ -1671,7 +1676,7 @@
 LinkedHashSet<int> test4() => {};
 ''';
     await resolveTestUnit(code, noErrors: false);
-    expectExpressionType('{}', 'Set<?>');
+    expectExpressionType('{}', 'Set<dynamic>');
     await assertErrorsInCode(code, [StrongModeCode.INVALID_CAST_LITERAL_SET]);
   }
 
@@ -1692,6 +1697,9 @@
 class StaticTypeAnalyzerWithStrictInferenceTest
     extends StaticTypeAnalyzer2TestShared {
   @override
+  bool get enableNewAnalysisDriver => true;
+
+  @override
   void setUp() {
     super.setUp();
     AnalysisOptionsImpl options = new AnalysisOptionsImpl();
@@ -1699,37 +1707,6 @@
     resetWith(options: options);
   }
 
-  @override
-  bool get enableNewAnalysisDriver => true;
-
-  test_topLevelVariable() async {
-    String code = r'''
-var a;
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertErrorsInCode(
-        code, [HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE]);
-  }
-
-  test_topLevelVariable_withType() async {
-    String code = r'''
-int a;
-dynamic b;
-Object c;
-Null d;
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
-  }
-
-  test_topLevelVariable_withInitializer() async {
-    String code = r'''
-var a = 7;
-''';
-    await resolveTestUnit(code, noErrors: false);
-    await assertNoErrorsInCode(code);
-  }
-
   test_localVariable() async {
     String code = r'''
 f() {
@@ -1741,6 +1718,16 @@
         code, [HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE]);
   }
 
+  test_localVariable_withInitializer() async {
+    String code = r'''
+f() {
+  var a = 7;
+}
+''';
+    await resolveTestUnit(code, noErrors: false);
+    await assertNoErrorsInCode(code);
+  }
+
   test_localVariable_withType() async {
     String code = r'''
 f() {
@@ -1754,11 +1741,29 @@
     await assertNoErrorsInCode(code);
   }
 
-  test_localVariable_withInitializer() async {
+  test_topLevelVariable() async {
     String code = r'''
-f() {
-  var a = 7;
-}
+var a;
+''';
+    await resolveTestUnit(code, noErrors: false);
+    await assertErrorsInCode(
+        code, [HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE]);
+  }
+
+  test_topLevelVariable_withInitializer() async {
+    String code = r'''
+var a = 7;
+''';
+    await resolveTestUnit(code, noErrors: false);
+    await assertNoErrorsInCode(code);
+  }
+
+  test_topLevelVariable_withType() async {
+    String code = r'''
+int a;
+dynamic b;
+Object c;
+Null d;
 ''';
     await resolveTestUnit(code, noErrors: false);
     await assertNoErrorsInCode(code);
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_driver_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_driver_test.dart
deleted file mode 100644
index 6286728..0000000
--- a/pkg/analyzer/test/generated/static_type_warning_code_driver_test.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2017, 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 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'static_type_warning_code.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(StaticTypeWarningCodeTest_Driver);
-    defineReflectiveTests(StrongModeStaticTypeWarningCodeTest_Driver);
-  });
-}
-
-@reflectiveTest
-class StaticTypeWarningCodeTest_Driver extends StaticTypeWarningCodeTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
-
-@reflectiveTest
-class StrongModeStaticTypeWarningCodeTest_Driver
-    extends StrongModeStaticTypeWarningCodeTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/generated/static_type_warning_code.dart b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
similarity index 98%
rename from pkg/analyzer/test/generated/static_type_warning_code.dart
rename to pkg/analyzer/test/generated/static_type_warning_code_test.dart
index 01f0538..36ad4c3 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -9,15 +9,17 @@
 
 import 'resolver_test_case.dart';
 
-abstract class StaticTypeWarningCodeTest extends ResolverTestCase {
-  fail_undefinedEnumConstant() async {
-    // We need a way to set the parseEnum flag in the parser to true.
-    await assertErrorsInCode(r'''
-enum E { ONE }
-E e() {
-  return E.TWO;
-}''', [StaticTypeWarningCode.UNDEFINED_ENUM_CONSTANT]);
-  }
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(StaticTypeWarningCodeTest);
+    defineReflectiveTests(StrongModeStaticTypeWarningCodeTest);
+  });
+}
+
+@reflectiveTest
+class StaticTypeWarningCodeTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
 
   test_assert_message_suppresses_type_promotion() async {
     // If a variable is assigned to inside the expression for an assert
@@ -1298,6 +1300,16 @@
 }''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
+  @failingTest
+  test_undefinedEnumConstant() async {
+    // We need a way to set the parseEnum flag in the parser to true.
+    await assertErrorsInCode(r'''
+enum E { ONE }
+E e() {
+  return E.TWO;
+}''', [StaticTypeWarningCode.UNDEFINED_ENUM_CONSTANT]);
+  }
+
   test_undefinedGetter() async {
     await assertErrorsInUnverifiedCode(r'''
 class T {}
@@ -1705,7 +1717,11 @@
   }
 }
 
-abstract class StrongModeStaticTypeWarningCodeTest extends ResolverTestCase {
+@reflectiveTest
+class StrongModeStaticTypeWarningCodeTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   void setUp() {
     super.setUp();
     AnalysisOptionsImpl options = new AnalysisOptionsImpl();
diff --git a/pkg/analyzer/test/generated/static_warning_code_driver_test.dart b/pkg/analyzer/test/generated/static_warning_code_driver_test.dart
deleted file mode 100644
index 2be665c..0000000
--- a/pkg/analyzer/test/generated/static_warning_code_driver_test.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2017, 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 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'resolver_test_case.dart';
-import 'static_warning_code_test.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(SetElementTypeNotAssignableTest);
-    defineReflectiveTests(StaticWarningCodeTest_Driver);
-  });
-}
-
-@reflectiveTest
-class SetElementTypeNotAssignableTest extends ResolverTestCase {
-  @override
-  bool get enableNewAnalysisDriver => true;
-
-  test_setElementTypeNotAssignable() async {
-    Source source = addSource("var v = <String>{42};");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
-  }
-}
-
-@reflectiveTest
-class StaticWarningCodeTest_Driver extends StaticWarningCodeTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/generated/static_warning_code_test.dart b/pkg/analyzer/test/generated/static_warning_code_test.dart
index 1aab715..096db7f 100644
--- a/pkg/analyzer/test/generated/static_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_warning_code_test.dart
@@ -14,6 +14,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(EqualValuesInConstSetTest);
+    defineReflectiveTests(StaticWarningCodeTest);
   });
 }
 
@@ -56,33 +57,10 @@
   }
 }
 
-abstract class StaticWarningCodeTest extends ResolverTestCase {
-  fail_argumentTypeNotAssignable_tearOff_required() async {
-    Source source = addSource(r'''
-class C {
-  Object/*=T*/ f/*<T>*/(Object/*=T*/ x) => x;
-}
-g(C c) {
-  var h = c.f/*<int>*/;
-  print(h('s'));
-}
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
-  }
-
-  fail_undefinedIdentifier_commentReference() async {
-    Source source = addSource(r'''
-/** [m] xxx [new B.c] */
-class A {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticWarningCode.UNDEFINED_IDENTIFIER,
-      StaticWarningCode.UNDEFINED_IDENTIFIER
-    ]);
-  }
+@reflectiveTest
+class StaticWarningCodeTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
 
   test_ambiguousImport_as() async {
     Source source = addSource(r'''
@@ -641,6 +619,22 @@
     verify([source]);
   }
 
+  @failingTest
+  test_argumentTypeNotAssignable_tearOff_required() async {
+    Source source = addSource(r'''
+class C {
+  Object/*=T*/ f/*<T>*/(Object/*=T*/ x) => x;
+}
+g(C c) {
+  var h = c.f/*<int>*/;
+  print(h('s'));
+}
+''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
+    verify([source]);
+  }
+
   test_assignmentToClass() async {
     Source source = addSource('''
 class C {}
@@ -2320,27 +2314,6 @@
     verify([source]);
   }
 
-  test_listElementTypeNotAssignable() async {
-    Source source = addSource("var v = <String> [42];");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
-  }
-
-  test_mapKeyTypeNotAssignable() async {
-    Source source = addSource("var v = <String, int > {1 : 2};");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
-  }
-
-  test_mapValueTypeNotAssignable() async {
-    Source source = addSource("var v = <String, String> {'a' : 2};");
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
-  }
-
   test_mismatchedAccessorTypes_topLevel() async {
     Source source = addSource(r'''
 int get g { return 0; }
@@ -3575,6 +3548,19 @@
     assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS_BOOLEAN]);
   }
 
+  @failingTest
+  test_undefinedIdentifier_commentReference() async {
+    Source source = addSource(r'''
+/** [m] xxx [new B.c] */
+class A {
+}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [
+      StaticWarningCode.UNDEFINED_IDENTIFIER,
+      StaticWarningCode.UNDEFINED_IDENTIFIER
+    ]);
+  }
+
   test_undefinedIdentifier_for() async {
     Source source = addSource(r'''
 f(var l) {
diff --git a/pkg/analyzer/test/generated/strong_mode_driver_test.dart b/pkg/analyzer/test/generated/strong_mode_driver_test.dart
deleted file mode 100644
index c6047e6..0000000
--- a/pkg/analyzer/test/generated/strong_mode_driver_test.dart
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (c) 2017, 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 'package:analyzer/src/generated/engine.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'resolver_test_case.dart';
-import 'strong_mode.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(StrongModeLocalInferenceTest_Driver);
-    defineReflectiveTests(StrongModeStaticTypeAnalyzer2Test_Driver);
-    defineReflectiveTests(StrongModeTypePropagationTest_Driver);
-  });
-}
-
-@reflectiveTest
-class StrongModeLocalInferenceTest_Driver extends StrongModeLocalInferenceTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
-
-@reflectiveTest
-class StrongModeStaticTypeAnalyzer2Test_Driver
-    extends StaticTypeAnalyzer2TestShared
-    with StrongModeStaticTypeAnalyzer2TestCases {
-  @override
-  bool get enableNewAnalysisDriver => true;
-
-  void setUp() {
-    super.setUp();
-    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
-    resetWith(options: options);
-  }
-
-  @failingTest
-  @override
-  test_genericFunction_parameter() {
-    return super.test_genericFunction_parameter();
-  }
-
-  @failingTest
-  @override
-  test_genericMethod_functionExpressionInvocation_functionTypedParameter_explicit() {
-    return super
-        .test_genericMethod_functionExpressionInvocation_functionTypedParameter_explicit();
-  }
-
-  @failingTest
-  @override
-  test_genericMethod_functionExpressionInvocation_functionTypedParameter_inferred() {
-    return super
-        .test_genericMethod_functionExpressionInvocation_functionTypedParameter_inferred();
-  }
-
-  @failingTest
-  @override
-  test_genericMethod_functionInvocation_functionTypedParameter_explicit() {
-    return super
-        .test_genericMethod_functionInvocation_functionTypedParameter_explicit();
-  }
-
-  @failingTest
-  @override
-  test_genericMethod_functionInvocation_functionTypedParameter_inferred() {
-    return super
-        .test_genericMethod_functionInvocation_functionTypedParameter_inferred();
-  }
-
-  @failingTest
-  @override
-  test_genericMethod_functionTypedParameter_tearoff() {
-    return super.test_genericMethod_functionTypedParameter_tearoff();
-  }
-
-  @override
-  @failingTest
-  test_genericMethod_nestedCaptureBounds() {
-    // https://github.com/dart-lang/sdk/issues/30236
-    return super.test_genericMethod_nestedCaptureBounds();
-  }
-
-  @override
-  @failingTest
-  test_genericMethod_tearoff_instantiated() {
-    return super.test_genericMethod_tearoff_instantiated();
-  }
-
-  @override
-  @failingTest
-  test_instantiateToBounds_class_error_extension_malbounded() {
-    return super.test_instantiateToBounds_class_error_extension_malbounded();
-  }
-
-  @override
-  @failingTest
-  test_instantiateToBounds_class_error_instantiation_malbounded() {
-    return super
-        .test_instantiateToBounds_class_error_instantiation_malbounded();
-  }
-
-  @override
-  @failingTest
-  test_instantiateToBounds_generic_function_error_malbounded() {
-    return super.test_instantiateToBounds_generic_function_error_malbounded();
-  }
-}
-
-@reflectiveTest
-class StrongModeTypePropagationTest_Driver
-    extends StrongModeTypePropagationTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/generated/strong_mode.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
similarity index 97%
rename from pkg/analyzer/test/generated/strong_mode.dart
rename to pkg/analyzer/test/generated/strong_mode_test.dart
index f327129..c0f832d 100644
--- a/pkg/analyzer/test/generated/strong_mode.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -16,12 +16,22 @@
 import 'package:analyzer/src/test_utilities/find_node.dart';
 import 'package:front_end/src/base/errors.dart';
 import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../utils.dart';
 import 'resolver_test_case.dart';
 
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(StrongModeLocalInferenceTest);
+    defineReflectiveTests(StrongModeStaticTypeAnalyzer2Test);
+    defineReflectiveTests(StrongModeTypePropagationTest);
+  });
+}
+
 /// Strong mode static analyzer local type inference tests
-abstract class StrongModeLocalInferenceTest extends ResolverTestCase {
+@reflectiveTest
+class StrongModeLocalInferenceTest extends ResolverTestCase {
   TypeAssertions _assertions;
 
   Asserter<DartType> _isDynamic;
@@ -51,6 +61,9 @@
   AsserterBuilder<DartType, DartType> _hasElementOf;
 
   @override
+  bool get enableNewAnalysisDriver => true;
+
+  @override
   Future<TestAnalysisResult> computeAnalysisResult(Source source) async {
     TestAnalysisResult result = await super.computeAnalysisResult(source);
     if (_assertions == null) {
@@ -2809,6 +2822,91 @@
   }
 }
 
+@reflectiveTest
+class StrongModeStaticTypeAnalyzer2Test extends StaticTypeAnalyzer2TestShared
+    with StrongModeStaticTypeAnalyzer2TestCases {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
+  void setUp() {
+    super.setUp();
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    resetWith(options: options);
+  }
+
+  @failingTest
+  @override
+  test_genericFunction_parameter() {
+    return super.test_genericFunction_parameter();
+  }
+
+  @failingTest
+  @override
+  test_genericMethod_functionExpressionInvocation_functionTypedParameter_explicit() {
+    return super
+        .test_genericMethod_functionExpressionInvocation_functionTypedParameter_explicit();
+  }
+
+  @failingTest
+  @override
+  test_genericMethod_functionExpressionInvocation_functionTypedParameter_inferred() {
+    return super
+        .test_genericMethod_functionExpressionInvocation_functionTypedParameter_inferred();
+  }
+
+  @failingTest
+  @override
+  test_genericMethod_functionInvocation_functionTypedParameter_explicit() {
+    return super
+        .test_genericMethod_functionInvocation_functionTypedParameter_explicit();
+  }
+
+  @failingTest
+  @override
+  test_genericMethod_functionInvocation_functionTypedParameter_inferred() {
+    return super
+        .test_genericMethod_functionInvocation_functionTypedParameter_inferred();
+  }
+
+  @failingTest
+  @override
+  test_genericMethod_functionTypedParameter_tearoff() {
+    return super.test_genericMethod_functionTypedParameter_tearoff();
+  }
+
+  @override
+  @failingTest
+  test_genericMethod_nestedCaptureBounds() {
+    // https://github.com/dart-lang/sdk/issues/30236
+    return super.test_genericMethod_nestedCaptureBounds();
+  }
+
+  @override
+  @failingTest
+  test_genericMethod_tearoff_instantiated() {
+    return super.test_genericMethod_tearoff_instantiated();
+  }
+
+  @override
+  @failingTest
+  test_instantiateToBounds_class_error_extension_malbounded() {
+    return super.test_instantiateToBounds_class_error_extension_malbounded();
+  }
+
+  @override
+  @failingTest
+  test_instantiateToBounds_class_error_instantiation_malbounded() {
+    return super
+        .test_instantiateToBounds_class_error_instantiation_malbounded();
+  }
+
+  @override
+  @failingTest
+  test_instantiateToBounds_generic_function_error_malbounded() {
+    return super.test_instantiateToBounds_generic_function_error_malbounded();
+  }
+}
+
 /// Test cases for [StrongModeStaticTypeAnalyzer2Test]
 mixin StrongModeStaticTypeAnalyzer2TestCases
     implements StaticTypeAnalyzer2TestShared {
@@ -4320,7 +4418,11 @@
   }
 }
 
-abstract class StrongModeTypePropagationTest extends ResolverTestCase {
+@reflectiveTest
+class StrongModeTypePropagationTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   @override
   void setUp() {
     super.setUp();
diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart
index 6f3ca73..4481253 100644
--- a/pkg/analyzer/test/generated/test_all.dart
+++ b/pkg/analyzer/test/generated/test_all.dart
@@ -1,45 +1,37 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2014, 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 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'all_the_rest_test.dart' as all_the_rest;
-import 'checked_mode_compile_time_error_code_driver_test.dart'
-    as checked_mode_compile_time_error_code_driver_test;
-import 'compile_time_error_code_driver_test.dart'
-    as compile_time_error_code_driver_test;
-
+import 'checked_mode_compile_time_error_code_test.dart'
+    as checked_mode_compile_time_error_code;
+import 'compile_time_error_code_test.dart' as compile_time_error_code;
 // ignore: deprecated_member_use_from_same_package
 import 'constant_test.dart' as constant_test;
 import 'declaration_resolver_test.dart' as declaration_resolver_test;
 import 'element_resolver_test.dart' as element_resolver_test;
 import 'engine_test.dart' as engine_test;
-import 'error_suppression_driver_test.dart' as error_suppression_driver_test;
+import 'error_suppression_test.dart' as error_suppression;
 import 'hint_code_test.dart' as hint_code_test;
 import 'inheritance_manager_test.dart' as inheritance_manager_test;
-import 'invalid_code_driver_test.dart' as invalid_code_driver_test;
+import 'invalid_code_test.dart' as invalid_code;
 import 'java_core_test.dart' as java_core_test;
 import 'java_io_test.dart' as java_io_test;
-import 'non_error_resolver_driver_test.dart' as non_error_resolver_driver_test;
-import 'non_hint_code_driver_test.dart' as non_hint_code_driver_test;
+import 'non_error_resolver_test.dart' as non_error_resolver;
+import 'non_hint_code_test.dart' as non_hint_code;
 import 'parser_fasta_test.dart' as parser_fasta_test;
 import 'parser_test.dart' as parser_test;
-import 'resolver_driver_test.dart' as resolver_driver_test;
 import 'resolver_test.dart' as resolver_test;
 import 'scanner_test.dart' as scanner_test;
 import 'sdk_test.dart' as sdk_test;
 import 'simple_resolver_test.dart' as simple_resolver_test;
 import 'source_factory_test.dart' as source_factory_test;
-import 'static_type_analyzer_driver_test.dart'
-    as static_type_analyzer_driver_test;
 import 'static_type_analyzer_test.dart' as static_type_analyzer_test;
-import 'static_type_warning_code_driver_test.dart'
-    as static_type_warning_code_driver_test;
-import 'static_warning_code_driver_test.dart'
-    as static_warning_code_driver_test;
-import 'static_warning_code_test.dart' as static_warning_code_test;
-import 'strong_mode_driver_test.dart' as strong_mode_driver_test;
+import 'static_type_warning_code_test.dart' as static_type_warning_code;
+import 'static_warning_code_test.dart' as static_warning_code;
+import 'strong_mode_test.dart' as strong_mode;
 import 'type_system_test.dart' as type_system_test;
 import 'utilities_dart_test.dart' as utilities_dart_test;
 import 'utilities_test.dart' as utilities_test;
@@ -47,34 +39,31 @@
 main() {
   defineReflectiveSuite(() {
     all_the_rest.main();
-    checked_mode_compile_time_error_code_driver_test.main();
-    compile_time_error_code_driver_test.main();
+    checked_mode_compile_time_error_code.main();
+    compile_time_error_code.main();
     constant_test.main();
     declaration_resolver_test.main();
     element_resolver_test.main();
     engine_test.main();
-    error_suppression_driver_test.main();
+    error_suppression.main();
     hint_code_test.main();
     inheritance_manager_test.main();
-    invalid_code_driver_test.main();
+    invalid_code.main();
     java_core_test.main();
     java_io_test.main();
-    non_error_resolver_driver_test.main();
-    non_hint_code_driver_test.main();
+    non_error_resolver.main();
+    non_hint_code.main();
     parser_fasta_test.main();
     parser_test.main();
-    resolver_driver_test.main();
     resolver_test.main();
     scanner_test.main();
     sdk_test.main();
     simple_resolver_test.main();
     source_factory_test.main();
-    static_type_analyzer_driver_test.main();
     static_type_analyzer_test.main();
-    static_type_warning_code_driver_test.main();
-    static_warning_code_driver_test.main();
-    static_warning_code_test.main();
-    strong_mode_driver_test.main();
+    static_type_warning_code.main();
+    static_warning_code.main();
+    strong_mode.main();
     type_system_test.main();
     utilities_dart_test.main();
     utilities_test.main();
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index 528bd33..b6ba562 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -14,8 +14,6 @@
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:plugin/manager.dart';
-import 'package:plugin/plugin.dart';
 import 'package:test/test.dart';
 
 import 'analysis_context_factory.dart';
@@ -98,11 +96,7 @@
     fail("Could not find method named $methodName in ${type.displayName}");
   }
 
-  void setUp() {
-    List<Plugin> plugins = <Plugin>[];
-    plugins.addAll(AnalysisEngine.instance.requiredPlugins);
-    new ExtensionManager().processPlugins(plugins);
-  }
+  void setUp() {}
 
   void tearDown() {}
 
diff --git a/pkg/analyzer/test/source/error_processor_test.dart b/pkg/analyzer/test/source/error_processor_test.dart
index d55cd52..966a8ed 100644
--- a/pkg/analyzer/test/source/error_processor_test.dart
+++ b/pkg/analyzer/test/source/error_processor_test.dart
@@ -7,10 +7,7 @@
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
 import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/task/options.dart';
-import 'package:plugin/manager.dart';
-import 'package:plugin/plugin.dart';
 import 'package:test/test.dart';
 import 'package:yaml/yaml.dart';
 
@@ -44,8 +41,6 @@
   AnalysisError annotate_overrides = new AnalysisError(
       new TestSource(), 0, 1, new LintCode('annotate_overrides', ''));
 
-  oneTimeSetup();
-
   setUp(() {
     context = new TestContext();
   });
@@ -162,11 +157,4 @@
 ErrorProcessor getProcessor(AnalysisError error) =>
     ErrorProcessor.getProcessor(context.analysisOptions, error);
 
-void oneTimeSetup() {
-  List<Plugin> plugins = <Plugin>[];
-  plugins.addAll(AnalysisEngine.instance.requiredPlugins);
-  ExtensionManager manager = new ExtensionManager();
-  manager.processPlugins(plugins);
-}
-
 class TestContext extends AnalysisContextImpl {}
diff --git a/pkg/analyzer/test/src/context/abstract_context.dart b/pkg/analyzer/test/src/context/abstract_context.dart
deleted file mode 100644
index 131646e..0000000
--- a/pkg/analyzer/test/src/context/abstract_context.dart
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright (c) 2015, 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 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/visitor.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/file_system/file_system.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/driver.dart';
-import 'package:analyzer/src/test_utilities/mock_sdk.dart';
-import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
-import 'package:plugin/manager.dart';
-import 'package:plugin/plugin.dart';
-import 'package:test/test.dart';
-
-/**
- * Finds an [Element] with the given [name].
- */
-Element findChildElement(Element root, String name, [ElementKind kind]) {
-  Element result = null;
-  root.accept(new _ElementVisitorFunctionWrapper((Element element) {
-    if (element.name != name) {
-      return;
-    }
-    if (kind != null && element.kind != kind) {
-      return;
-    }
-    result = element;
-  }));
-  return result;
-}
-
-/**
- * A function to be called for every [Element].
- */
-typedef void _ElementVisitorFunction(Element element);
-
-class AbstractContextTest with ResourceProviderMixin {
-  DartSdk sdk;
-  SourceFactory sourceFactory;
-  AnalysisContextImpl context;
-  AnalysisCache analysisCache;
-  AnalysisDriver analysisDriver;
-
-  UriResolver sdkResolver;
-  UriResolver resourceResolver;
-
-  AnalysisTask task;
-  Map<ResultDescriptor<dynamic>, dynamic> oldOutputs;
-  Map<ResultDescriptor<dynamic>, dynamic> outputs;
-
-  Source addSource(String path, String contents) {
-    Source source = newSource(path, contents);
-    ChangeSet changeSet = new ChangeSet();
-    changeSet.addedSource(source);
-    context.applyChanges(changeSet);
-    return source;
-  }
-
-  /**
-   * Assert that the given [elements] has the same number of items as the number
-   * of specified [names], and that for each specified name, a corresponding
-   * element can be found in the given collection with that name.
-   */
-  void assertNamedElements(List<Element> elements, List<String> names) {
-    for (String elemName in names) {
-      bool found = false;
-      for (Element elem in elements) {
-        if (elem.name == elemName) {
-          found = true;
-          break;
-        }
-      }
-      if (!found) {
-        StringBuffer buffer = new StringBuffer();
-        buffer.write("Expected element named: ");
-        buffer.write(elemName);
-        buffer.write("\n  but found: ");
-        for (Element elem in elements) {
-          buffer.write(elem.name);
-          buffer.write(", ");
-        }
-        fail(buffer.toString());
-      }
-    }
-    expect(elements, hasLength(names.length));
-  }
-
-  /**
-   * Compute the given [result] for the given [target].
-   */
-  void computeResult(AnalysisTarget target, ResultDescriptor result,
-      {Matcher matcher: null}) {
-    oldOutputs = outputs;
-    task = analysisDriver.computeResult(target, result);
-    if (matcher == null) {
-      expect(task, isNotNull);
-    } else {
-      expect(task, matcher);
-    }
-    expect(task.caughtException, isNull);
-    outputs = task.outputs;
-    for (ResultDescriptor descriptor in task.descriptor.results) {
-      expect(outputs, contains(descriptor));
-    }
-  }
-
-  AnalysisContextImpl createAnalysisContext() {
-    return new AnalysisContextImpl();
-  }
-
-  DartSdk createDartSdk() => new MockSdk(resourceProvider: resourceProvider);
-
-  Source newSource(String path, [String content = '']) {
-    File file = newFile(path, content: content);
-    return file.createSource();
-  }
-
-  List<Source> newSources(Map<String, String> sourceMap) {
-    List<Source> sources = <Source>[];
-    sourceMap.forEach((String path, String content) {
-      Source source = newSource(path, content);
-      sources.add(source);
-    });
-    return sources;
-  }
-
-  void prepareAnalysisContext([AnalysisOptions options]) {
-    sdk = createDartSdk();
-    sdkResolver = new DartUriResolver(sdk);
-    resourceResolver = new ResourceUriResolver(resourceProvider);
-    sourceFactory = new SourceFactory(
-        <UriResolver>[sdkResolver, resourceResolver], null, resourceProvider);
-    context = createAnalysisContext();
-    if (options != null) {
-      context.analysisOptions = options;
-    }
-    context.sourceFactory = sourceFactory;
-    analysisCache = context.analysisCache;
-    analysisDriver = context.driver;
-  }
-
-  CompilationUnit resolveLibraryUnit(Source source) {
-    return context.resolveCompilationUnit2(source, source);
-  }
-
-  void setUp() {
-    List<Plugin> plugins = <Plugin>[];
-    plugins.addAll(AnalysisEngine.instance.requiredPlugins);
-
-    ExtensionManager manager = new ExtensionManager();
-    manager.processPlugins(plugins);
-
-    prepareAnalysisContext();
-  }
-
-  void tearDown() {}
-}
-
-/**
- * Wraps the given [_ElementVisitorFunction] into an instance of
- * [GeneralizingElementVisitor].
- */
-class _ElementVisitorFunctionWrapper extends GeneralizingElementVisitor {
-  final _ElementVisitorFunction function;
-
-  _ElementVisitorFunctionWrapper(this.function);
-
-  visitElement(Element element) {
-    function(element);
-    super.visitElement(element);
-  }
-}
diff --git a/pkg/analyzer/test/src/context/source_test.dart b/pkg/analyzer/test/src/context/source_test.dart
index 45a5ffc..530d908 100644
--- a/pkg/analyzer/test/src/context/source_test.dart
+++ b/pkg/analyzer/test/src/context/source_test.dart
@@ -5,12 +5,11 @@
 import 'package:analyzer/src/context/source.dart';
 import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:package_config/packages.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'abstract_context.dart';
-
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(SourceFactoryImplTest);
@@ -18,7 +17,7 @@
 }
 
 @reflectiveTest
-class SourceFactoryImplTest extends AbstractContextTest {
+class SourceFactoryImplTest with ResourceProviderMixin {
   void test_restoreUri() {
     String libPath = convertPath('/pkgs/somepkg/lib');
     Uri libUri = getFolder(libPath).toUri();
@@ -27,7 +26,7 @@
       <UriResolver>[new ResourceUriResolver(resourceProvider)],
       new _MockPackages(packageUriMap),
     );
-    Source libSource = newSource('/pkgs/somepkg/lib');
+    Source libSource = newFile('/pkgs/somepkg/lib').createSource();
     Uri uri = sourceFactory.restoreUri(libSource);
     try {
       expect(uri, Uri.parse('package:foo/'));
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index b47fb50..f5bb3d3 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -2114,7 +2114,6 @@
     var fTypeParameter = fType.normalParameterTypes[0] as TypeParameterType;
     expect(fTypeParameter.element, same(fTypeTypeParameter));
     var tRef = findNode.simple('T>');
-    assertType(tRef, null);
     var functionTypeNode = tRef.parent.parent.parent as GenericFunctionType;
     var functionType = functionTypeNode.type as FunctionType;
     assertElement(tRef, functionType.typeFormals[0]);
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index f0e2140..7b9330f 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -802,6 +802,46 @@
       EnableString.spread_collections
     ];
 
+  test_listLiteral_ifElement_false_withElse() async {
+    await _resolveTestCode('''
+const c = [1, if (1 < 0) 2 else 3, 4];
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(
+        result.type, typeProvider.listType.instantiate([typeProvider.intType]));
+    expect(result.toListValue().map((e) => e.toIntValue()), [1, 3, 4]);
+  }
+
+  test_listLiteral_ifElement_false_withoutElse() async {
+    await _resolveTestCode('''
+const c = [1, if (1 < 0) 2, 3];
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(
+        result.type, typeProvider.listType.instantiate([typeProvider.intType]));
+    expect(result.toListValue().map((e) => e.toIntValue()), [1, 3]);
+  }
+
+  test_listLiteral_ifElement_true_withElse() async {
+    await _resolveTestCode('''
+const c = [1, if (1 > 0) 2 else 3, 4];
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(
+        result.type, typeProvider.listType.instantiate([typeProvider.intType]));
+    expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 4]);
+  }
+
+  test_listLiteral_ifElement_true_withoutElse() async {
+    await _resolveTestCode('''
+const c = [1, if (1 > 0) 2, 3];
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(
+        result.type, typeProvider.listType.instantiate([typeProvider.intType]));
+    expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 3]);
+  }
+
   test_listLiteral_nested() async {
     await _resolveTestCode('''
 const c = [1, if (1 > 0) if (2 > 1) 2, 3];
@@ -814,47 +854,7 @@
     expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 3]);
   }
 
-  test_listLiteral_withIf_false_withElse() async {
-    await _resolveTestCode('''
-const c = [1, if (1 < 0) 2 else 3, 4];
-''');
-    DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.listType.instantiate([typeProvider.intType]));
-    expect(result.toListValue().map((e) => e.toIntValue()), [1, 3, 4]);
-  }
-
-  test_listLiteral_withIf_false_withoutElse() async {
-    await _resolveTestCode('''
-const c = [1, if (1 < 0) 2, 3];
-''');
-    DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.listType.instantiate([typeProvider.intType]));
-    expect(result.toListValue().map((e) => e.toIntValue()), [1, 3]);
-  }
-
-  test_listLiteral_withIf_true_withElse() async {
-    await _resolveTestCode('''
-const c = [1, if (1 > 0) 2 else 3, 4];
-''');
-    DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.listType.instantiate([typeProvider.intType]));
-    expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 4]);
-  }
-
-  test_listLiteral_withIf_true_withoutElse() async {
-    await _resolveTestCode('''
-const c = [1, if (1 > 0) 2, 3];
-''');
-    DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.listType.instantiate([typeProvider.intType]));
-    expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 3]);
-  }
-
-  test_listLiteral_withSpread() async {
+  test_listLiteral_spreadElement() async {
     await _resolveTestCode('''
 const c = [1, ...[2, 3], 4];
 ''');
@@ -864,6 +864,66 @@
     expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 3, 4]);
   }
 
+  test_mapLiteral_ifElement_false_withElse() async {
+    await _resolveTestCode('''
+const c = {'a' : 1, if (1 < 0) 'b' : 2 else 'c' : 3, 'd' : 4};
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(
+        result.type,
+        typeProvider.mapType
+            .instantiate([typeProvider.stringType, typeProvider.intType]));
+    Map<DartObject, DartObject> value = result.toMapValue();
+    expect(value.keys.map((e) => e.toStringValue()),
+        unorderedEquals(['a', 'c', 'd']));
+    expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 3, 4]));
+  }
+
+  test_mapLiteral_ifElement_false_withoutElse() async {
+    await _resolveTestCode('''
+const c = {'a' : 1, if (1 < 0) 'b' : 2, 'c' : 3};
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(
+        result.type,
+        typeProvider.mapType
+            .instantiate([typeProvider.stringType, typeProvider.intType]));
+    Map<DartObject, DartObject> value = result.toMapValue();
+    expect(
+        value.keys.map((e) => e.toStringValue()), unorderedEquals(['a', 'c']));
+    expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 3]));
+  }
+
+  test_mapLiteral_ifElement_true_withElse() async {
+    await _resolveTestCode('''
+const c = {'a' : 1, if (1 > 0) 'b' : 2 else 'c' : 3, 'd' : 4};
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(
+        result.type,
+        typeProvider.mapType
+            .instantiate([typeProvider.stringType, typeProvider.intType]));
+    Map<DartObject, DartObject> value = result.toMapValue();
+    expect(value.keys.map((e) => e.toStringValue()),
+        unorderedEquals(['a', 'b', 'd']));
+    expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 2, 4]));
+  }
+
+  test_mapLiteral_ifElement_true_withoutElse() async {
+    await _resolveTestCode('''
+const c = {'a' : 1, if (1 > 0) 'b' : 2, 'c' : 3};
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(
+        result.type,
+        typeProvider.mapType
+            .instantiate([typeProvider.stringType, typeProvider.intType]));
+    Map<DartObject, DartObject> value = result.toMapValue();
+    expect(value.keys.map((e) => e.toStringValue()),
+        unorderedEquals(['a', 'b', 'c']));
+    expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 2, 3]));
+  }
+
   @failingTest
   test_mapLiteral_nested() async {
     // Fails because we're not yet parsing nested elements.
@@ -881,67 +941,7 @@
     expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 2, 3]));
   }
 
-  test_mapLiteral_withIf_false_withElse() async {
-    await _resolveTestCode('''
-const c = {'a' : 1, if (1 < 0) 'b' : 2 else 'c' : 3, 'd' : 4};
-''');
-    DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type,
-        typeProvider.mapType
-            .instantiate([typeProvider.stringType, typeProvider.intType]));
-    Map<DartObject, DartObject> value = result.toMapValue();
-    expect(value.keys.map((e) => e.toStringValue()),
-        unorderedEquals(['a', 'c', 'd']));
-    expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 3, 4]));
-  }
-
-  test_mapLiteral_withIf_false_withoutElse() async {
-    await _resolveTestCode('''
-const c = {'a' : 1, if (1 < 0) 'b' : 2, 'c' : 3};
-''');
-    DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type,
-        typeProvider.mapType
-            .instantiate([typeProvider.stringType, typeProvider.intType]));
-    Map<DartObject, DartObject> value = result.toMapValue();
-    expect(
-        value.keys.map((e) => e.toStringValue()), unorderedEquals(['a', 'c']));
-    expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 3]));
-  }
-
-  test_mapLiteral_withIf_true_withElse() async {
-    await _resolveTestCode('''
-const c = {'a' : 1, if (1 > 0) 'b' : 2 else 'c' : 3, 'd' : 4};
-''');
-    DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type,
-        typeProvider.mapType
-            .instantiate([typeProvider.stringType, typeProvider.intType]));
-    Map<DartObject, DartObject> value = result.toMapValue();
-    expect(value.keys.map((e) => e.toStringValue()),
-        unorderedEquals(['a', 'b', 'd']));
-    expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 2, 4]));
-  }
-
-  test_mapLiteral_withIf_true_withoutElse() async {
-    await _resolveTestCode('''
-const c = {'a' : 1, if (1 > 0) 'b' : 2, 'c' : 3};
-''');
-    DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type,
-        typeProvider.mapType
-            .instantiate([typeProvider.stringType, typeProvider.intType]));
-    Map<DartObject, DartObject> value = result.toMapValue();
-    expect(value.keys.map((e) => e.toStringValue()),
-        unorderedEquals(['a', 'b', 'c']));
-    expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 2, 3]));
-  }
-
-  test_mapLiteral_withSpread() async {
+  test_mapLiteral_spreadElement() async {
     await _resolveTestCode('''
 const c = {'a' : 1, ...{'b' : 2, 'c' : 3}, 'd' : 4};
 ''');
@@ -957,6 +957,46 @@
         value.values.map((e) => e.toIntValue()), unorderedEquals([1, 2, 3, 4]));
   }
 
+  test_setLiteral_ifElement_false_withElse() async {
+    await _resolveTestCode('''
+const c = {1, if (1 < 0) 2 else 3, 4};
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(
+        result.type, typeProvider.setType.instantiate([typeProvider.intType]));
+    expect(result.toSetValue().map((e) => e.toIntValue()), [1, 3, 4]);
+  }
+
+  test_setLiteral_ifElement_false_withoutElse() async {
+    await _resolveTestCode('''
+const c = {1, if (1 < 0) 2, 3};
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(
+        result.type, typeProvider.setType.instantiate([typeProvider.intType]));
+    expect(result.toSetValue().map((e) => e.toIntValue()), [1, 3]);
+  }
+
+  test_setLiteral_ifElement_true_withElse() async {
+    await _resolveTestCode('''
+const c = {1, if (1 > 0) 2 else 3, 4};
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(
+        result.type, typeProvider.setType.instantiate([typeProvider.intType]));
+    expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 4]);
+  }
+
+  test_setLiteral_ifElement_true_withoutElse() async {
+    await _resolveTestCode('''
+const c = {1, if (1 > 0) 2, 3};
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(
+        result.type, typeProvider.setType.instantiate([typeProvider.intType]));
+    expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 3]);
+  }
+
   test_setLiteral_nested() async {
     await _resolveTestCode('''
 const c = {1, if (1 > 0) if (2 > 1) 2, 3};
@@ -967,47 +1007,7 @@
     expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 3]);
   }
 
-  test_setLiteral_withIf_false_withElse() async {
-    await _resolveTestCode('''
-const c = {1, if (1 < 0) 2 else 3, 4};
-''');
-    DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.setType.instantiate([typeProvider.intType]));
-    expect(result.toSetValue().map((e) => e.toIntValue()), [1, 3, 4]);
-  }
-
-  test_setLiteral_withIf_false_withoutElse() async {
-    await _resolveTestCode('''
-const c = {1, if (1 < 0) 2, 3};
-''');
-    DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.setType.instantiate([typeProvider.intType]));
-    expect(result.toSetValue().map((e) => e.toIntValue()), [1, 3]);
-  }
-
-  test_setLiteral_withIf_true_withElse() async {
-    await _resolveTestCode('''
-const c = {1, if (1 > 0) 2 else 3, 4};
-''');
-    DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.setType.instantiate([typeProvider.intType]));
-    expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 4]);
-  }
-
-  test_setLiteral_withIf_true_withoutElse() async {
-    await _resolveTestCode('''
-const c = {1, if (1 > 0) 2, 3};
-''');
-    DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.setType.instantiate([typeProvider.intType]));
-    expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 3]);
-  }
-
-  test_setLiteral_withSpread() async {
+  test_setLiteral_spreadElement() async {
     await _resolveTestCode('''
 const c = {1, ...{2, 3}, 4};
 ''');
diff --git a/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart b/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart
new file mode 100644
index 0000000..b9ca532
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart
@@ -0,0 +1,804 @@
+// 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.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/constant/potentially_constant.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(IsConstantTypeExpressionTest);
+    defineReflectiveTests(PotentiallyConstantTest);
+    defineReflectiveTests(PotentiallyConstantWithUIAsCodeTest);
+  });
+}
+
+@reflectiveTest
+class IsConstantTypeExpressionTest extends DriverResolutionTest {
+  test_class() async {
+    await _assertConst(r'''
+int x;
+''');
+  }
+
+  test_class_prefix() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A {}
+''');
+    await _assertConst(r'''
+import 'a.dart' as p;
+p.A x;
+''');
+  }
+
+  test_class_prefix_deferred() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A {}
+''');
+    await _assertNotConst(r'''
+import 'a.dart' deferred as p;
+p.A x;
+''');
+  }
+
+  test_class_typeArguments() async {
+    await _assertConst(r'''
+List<int> x;
+''');
+  }
+
+  test_class_typeArguments_notConst() async {
+    await _assertNotConst(r'''
+class A<T> {
+  m() {
+    List<T> x;
+  }
+}
+''');
+  }
+
+  test_dynamic() async {
+    await _assertConst(r'''
+dynamic x;
+''');
+  }
+
+  test_genericFunctionType() async {
+    await _assertConst(r'''
+int Function<T extends num, U>(int, bool) x;
+''');
+  }
+
+  test_genericFunctionType_formalParameterType() async {
+    await _assertNotConst(r'''
+class A<T> {
+  m() {
+    Function(T) x;
+  }
+}
+''');
+  }
+
+  test_genericFunctionType_returnType() async {
+    await _assertNotConst(r'''
+class A<T> {
+  m() {
+    T Function() x;
+  }
+}
+''');
+  }
+
+  test_genericFunctionType_typeParameterBound() async {
+    await _assertNotConst(r'''
+class A<T> {
+  m() {
+    Function<U extends T>() x;
+  }
+}
+''');
+  }
+
+  test_typeParameter() async {
+    await _assertNotConst(r'''
+class A<T> {
+  m() {
+    T x;
+  }
+}
+''');
+  }
+
+  test_void() async {
+    await _assertConst(r'''
+void x;
+''');
+  }
+
+  Future<void> _assertConst(String code) async {
+    addTestFile(code);
+    await resolveTestFile();
+
+    var type = findNode.variableDeclarationList('x;').type;
+    expect(isConstantTypeExpression(type), isTrue);
+  }
+
+  Future<void> _assertNotConst(String code) async {
+    addTestFile(code);
+    await resolveTestFile();
+
+    var type = findNode.variableDeclarationList('x;').type;
+    expect(isConstantTypeExpression(type), isFalse);
+  }
+}
+
+@reflectiveTest
+class PotentiallyConstantTest extends DriverResolutionTest {
+  test_asExpression() async {
+    await _assertConst(r'''
+const a = 0;
+var x = a as int;
+''', () => _xInitializer());
+  }
+
+  test_asExpression_final() async {
+    await _assertNotConst(r'''
+final a = 0;
+var x = a as int;
+''', () => _xInitializer(), () => [findNode.simple('a as')]);
+  }
+
+  test_asExpression_notConstType() async {
+    await _assertNotConst(r'''
+const a = 0;
+class A<T> {
+  m() {
+    var x = a as T;
+  }
+}
+''', () => _xInitializer(), () => [findNode.typeName('T;')]);
+  }
+
+  test_conditional() async {
+    await _assertConst(r'''
+const a = 0;
+const b = 0;
+const c = 0;
+var x = a ? b : c;
+''', () => _xInitializer());
+  }
+
+  test_conditional_final() async {
+    await _assertNotConst(
+        r'''
+final a = 0;
+final b = 0;
+final c = 0;
+var x = a ? b : c;
+''',
+        () => _xInitializer(),
+        () => [
+              findNode.simple('a ?'),
+              findNode.simple('b :'),
+              findNode.simple('c;')
+            ]);
+  }
+
+  test_instanceCreation() async {
+    await _assertNotConst(r'''
+class A {
+  const A();
+}
+
+var x = new A(); // x
+''', () => _xInitializer(), () => [findNode.instanceCreation('A(); // x')]);
+  }
+
+  test_instanceCreation_const() async {
+    await _assertConst(r'''
+class A {
+  const A();
+}
+
+var x = const A();
+''', () => _xInitializer());
+  }
+
+  test_isExpression() async {
+    await _assertConst(r'''
+const a = 0;
+var x = a is int;
+''', () => _xInitializer());
+  }
+
+  test_isExpression_final() async {
+    await _assertNotConst(r'''
+final a = 0;
+var x = a is int;
+''', () => _xInitializer(), () => [findNode.simple('a is')]);
+  }
+
+  test_isExpression_notConstType() async {
+    await _assertNotConst(r'''
+const a = 0;
+class A<T> {
+  m() {
+    var x = a is T;
+  }
+}
+''', () => _xInitializer(), () => [findNode.typeName('T;')]);
+  }
+
+  test_listLiteral() async {
+    await _assertConst(r'''
+var x = const [0, 1, 2];
+''', () => _xInitializer());
+  }
+
+  test_listLiteral_notConst() async {
+    await _assertNotConst(r'''
+var x = [0, 1, 2];
+''', () => _xInitializer(), () => [findNode.listLiteral('0,')]);
+  }
+
+  test_listLiteral_notConst_element() async {
+    await _assertNotConst(r'''
+final a = 0;
+final b = 1;
+var x = const [a, b, 2];
+''', () => _xInitializer(),
+        () => [findNode.simple('a,'), findNode.simple('b,')]);
+  }
+
+  test_listLiteral_typeArgument() async {
+    await _assertConst(r'''
+var x = const <int>[0, 1, 2];
+''', () => _xInitializer());
+  }
+
+  test_listLiteral_typeArgument_notConstType() async {
+    await _assertNotConst(r'''
+class A<T> {
+  m() {
+    var x = const <T>[0, 1, 2];
+  }
+}
+''', () => _xInitializer(), () => [findNode.typeName('T>[0')]);
+  }
+
+  test_literal_bool() async {
+    await _assertConst(r'''
+var x = true;
+''', () => _xInitializer());
+  }
+
+  test_literal_double() async {
+    await _assertConst(r'''
+var x = 1.2;
+''', () => _xInitializer());
+  }
+
+  test_literal_int() async {
+    await _assertConst(r'''
+var x = 0;
+''', () => _xInitializer());
+  }
+
+  test_literal_null() async {
+    await _assertConst(r'''
+var x = null;
+''', () => _xInitializer());
+  }
+
+  test_literal_simpleString() async {
+    await _assertConst(r'''
+var x = '123';
+''', () => _xInitializer());
+  }
+
+  test_literal_symbol() async {
+    await _assertConst(r'''
+var x = #a.b.c;
+''', () => _xInitializer());
+  }
+
+  test_mapLiteral() async {
+    await _assertConst(r'''
+var x = const {0: 1};
+''', () => _xInitializer());
+  }
+
+  test_mapLiteral_notConst() async {
+    await _assertNotConst(r'''
+var x = {0: 1};
+''', () => _xInitializer(), () => [findNode.setOrMapLiteral('0: 1')]);
+  }
+
+  test_mapLiteral_notConst_key() async {
+    await _assertNotConst(r'''
+final a = 1;
+final b = 2;
+var x = const {0: 0, a: 1, b: 2};
+''', () => _xInitializer(),
+        () => [findNode.simple('a:'), findNode.simple('b:')]);
+  }
+
+  test_mapLiteral_notConst_value() async {
+    await _assertNotConst(r'''
+final a = 1;
+final b = 2;
+var x = const {0: 0, 1: a, 2: b};
+''', () => _xInitializer(),
+        () => [findNode.simple('a,'), findNode.simple('b}')]);
+  }
+
+  test_mapLiteral_typeArgument() async {
+    await _assertConst(r'''
+var x = const <int, int>{0: 0};
+''', () => _xInitializer());
+  }
+
+  test_mapLiteral_typeArgument_notConstType() async {
+    await _assertNotConst(r'''
+class A<T> {
+  m() {
+    var x = const <T, T>{};
+  }
+}
+''', () => _xInitializer(),
+        () => [findNode.typeName('T,'), findNode.typeName('T>{')]);
+  }
+
+  test_methodInvocation_identical() async {
+    await _assertConst(r'''
+const a = 0;
+const b = 0;
+var x = identical(a, b);
+''', () => _xInitializer());
+  }
+
+  test_methodInvocation_identical_final() async {
+    await _assertNotConst(r'''
+final a = 0;
+final b = 0;
+var x = identical(a, b);
+''', () => _xInitializer(),
+        () => [findNode.simple('a,'), findNode.simple('b)')]);
+  }
+
+  test_methodInvocation_name() async {
+    await _assertNotConst(r'''
+const a = 0;
+const b = 0;
+var x = foo(a, b);
+''', () => _xInitializer(), () => [findNode.methodInvocation('foo')]);
+  }
+
+  test_methodInvocation_target() async {
+    await _assertNotConst(r'''
+var x = a.foo();
+''', () => _xInitializer(), () => [findNode.methodInvocation('a.foo()')]);
+  }
+
+  test_parenthesizedExpression_const() async {
+    await _assertConst(r'''
+const a = 0;
+var x = (a);
+''', () => _xInitializer());
+  }
+
+  test_parenthesizedExpression_final() async {
+    await _assertNotConst(r'''
+final a = 0;
+var x = (a);
+''', () => _xInitializer(), () => [findNode.simple('a);')]);
+  }
+
+  test_postfixExpression() async {
+    await _assertNotConst(r'''
+const a = 0;
+var x = a++;
+''', () => _xInitializer(), () => [findNode.postfix('a++')]);
+  }
+
+  test_prefixedIdentifier_importPrefix() async {
+    newFile('/test/lib/a.dart', content: r'''
+const a = 0;
+''');
+    await _assertConst(r'''
+import 'a.dart' as p;
+var x = p.a + 1;
+''', () => _xInitializer());
+  }
+
+  test_prefixedIdentifier_importPrefix_deferred() async {
+    newFile('/test/lib/a.dart', content: r'''
+const a = 0;
+''');
+    await _assertNotConst(r'''
+import 'a.dart' deferred as p;
+var x = p.a + 1;
+''', () => _xInitializer(), () => [findNode.prefixed('p.a')]);
+  }
+
+  test_prefixedIdentifier_length_const() async {
+    await _assertConst(r'''
+const a = 'abc';
+var x = a.length;
+''', () => _xInitializer());
+  }
+
+  test_prefixedIdentifier_length_final() async {
+    await _assertNotConst(r'''
+final a = 'abc';
+var x = a.length;
+''', () => _xInitializer(), () => [findNode.simple('a.')]);
+  }
+
+  test_prefixedIdentifier_method_instance() async {
+    await _assertNotConst(r'''
+class A {
+  const A();
+  m() {};
+}
+
+const a = const A();
+
+var x = a.m;
+''', () => _xInitializer(), () => [findNode.prefixed('a.m')]);
+  }
+
+  test_prefixedIdentifier_method_static() async {
+    await _assertConst(r'''
+class A {
+  static m() {};
+}
+
+var x = A.m;
+''', () => _xInitializer());
+  }
+
+  test_prefixedIdentifier_method_static_viaInstance() async {
+    await _assertNotConst(r'''
+class A {
+  const A();
+  static m() {};
+}
+
+const a = const A();
+
+var x = a.m;
+''', () => _xInitializer(), () => [findNode.prefixed('a.m')]);
+  }
+
+  test_prefixedIdentifier_prefix_variable() async {
+    await _assertNotConst(r'''
+class A {
+  final a = 0;
+  const A();
+}
+
+const a = const A();
+
+var x = a.b + 1;
+''', () => _xInitializer(), () => [findNode.prefixed('a.b + 1')]);
+  }
+
+  test_prefixedIdentifier_staticField_const() async {
+    await _assertConst(r'''
+class A {
+  static const a = 0;
+}
+var x = A.a + 1;
+''', () => _xInitializer());
+  }
+
+  test_prefixedIdentifier_staticField_final() async {
+    await _assertNotConst(
+      r'''
+class A {
+  static final a = 0;
+}
+var x = A.a + 1;
+''',
+      () => _xInitializer(),
+      () => [findNode.prefixed('A.a')],
+    );
+  }
+
+  test_prefixExpression_bang() async {
+    await _assertConst(r'''
+const a = 0;
+var x = !a;
+''', () => _xInitializer());
+  }
+
+  test_prefixExpression_minus() async {
+    await _assertConst(r'''
+const a = 0;
+var x = -a;
+''', () => _xInitializer());
+  }
+
+  test_prefixExpression_minus_final() async {
+    await _assertNotConst(r'''
+final a = 0;
+var x = -a;
+''', () => _xInitializer(), () => [findNode.simple('a;')]);
+  }
+
+  test_prefixExpression_plusPlus() async {
+    await _assertNotConst(r'''
+const a = 0;
+var x = ++a;
+''', () => _xInitializer(), () => [findNode.prefix('++a')]);
+  }
+
+  test_prefixExpression_tilde() async {
+    await _assertConst(r'''
+const a = 0;
+var x = ~a;
+''', () => _xInitializer());
+  }
+
+  test_propertyAccess_length_final() async {
+    await _assertNotConst(r'''
+final a = 'abc';
+var x = (a).length;
+''', () => _xInitializer(), () => [findNode.simple('a).')]);
+  }
+
+  test_propertyAccess_length_stringLiteral() async {
+    await _assertConst(r'''
+var x = 'abc'.length;
+''', () => _xInitializer());
+  }
+
+  test_propertyAccess_staticField_withPrefix_const() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A {
+  static const a = 0;
+}
+''');
+    await _assertConst(r'''
+import 'a.dart' as p;
+var x = p.A.a + 1;
+''', () => _xInitializer());
+  }
+
+  test_propertyAccess_staticField_withPrefix_deferred() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A {
+  static const a = 0;
+}
+''');
+    await _assertNotConst(r'''
+import 'a.dart' deferred as p;
+var x = p.A.a + 1;
+''', () => _xInitializer(), () => [findNode.propertyAccess('p.A.a')]);
+  }
+
+  test_propertyAccess_staticField_withPrefix_final() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A {
+  static final a = 0;
+}
+''');
+    await _assertNotConst(r'''
+import 'a.dart' as p;
+var x = p.A.a + 1;
+''', () => _xInitializer(), () => [findNode.simple('a + 1')]);
+  }
+
+  test_propertyAccess_target_instanceCreation() async {
+    await _assertNotConst(r'''
+class A {
+  final a = 0;
+}
+
+var x = A().a + 1;
+''', () => _xInitializer(), () => [findNode.propertyAccess('A().a')]);
+  }
+
+  test_propertyAccess_target_variable() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A {
+  final a = 0;
+  const A();
+}
+
+const a = const A();
+''');
+    await _assertNotConst(r'''
+import 'a.dart' as p;
+
+var x = p.a.b + 1;
+''', () => _xInitializer(), () => [findNode.propertyAccess('p.a.b + 1')]);
+  }
+
+  test_setLiteral() async {
+    await _assertConst(r'''
+var x = const {0, 1, 2};
+''', () => _xInitializer());
+  }
+
+  test_setLiteral_notConst() async {
+    await _assertNotConst(r'''
+var x = {0, 1, 2};
+''', () => _xInitializer(), () => [findNode.setOrMapLiteral('0,')]);
+  }
+
+  test_setLiteral_notConst_element() async {
+    await _assertNotConst(r'''
+final a = 0;
+final b = 1;
+var x = const {a, b, 2};
+''', () => _xInitializer(),
+        () => [findNode.simple('a,'), findNode.simple('b,')]);
+  }
+
+  test_setLiteral_typeArgument() async {
+    await _assertConst(r'''
+var x = const <int>{0, 1, 2};
+''', () => _xInitializer());
+  }
+
+  test_setLiteral_typeArgument_notConstType() async {
+    await _assertNotConst(r'''
+class A<T> {
+  m() {
+    var x = const <T>{0, 1, 2};
+  }
+}
+''', () => _xInitializer(), () => [findNode.typeName('T>{0')]);
+  }
+
+  test_simpleIdentifier_function() async {
+    await _assertConst(r'''
+var x = f;
+
+void f() {}
+''', () => _xInitializer());
+  }
+
+  test_simpleIdentifier_localVar_const() async {
+    await _assertConst(r'''
+main() {
+  const a = 0;
+  var x = a + 1;
+}
+''', () => _xInitializer());
+  }
+
+  test_simpleIdentifier_localVar_final() async {
+    await _assertNotConst(
+      r'''
+main() {
+  final a = 0;
+  var x = a + 1;
+}
+''',
+      () => _xInitializer(),
+      () => [findNode.simple('a +')],
+    );
+  }
+
+  test_simpleIdentifier_topVar_const() async {
+    await _assertConst(r'''
+const a = 0;
+var x = a + 1;
+''', () => _xInitializer());
+  }
+
+  test_simpleIdentifier_topVar_final() async {
+    await _assertNotConst(
+      r'''
+final a = 0;
+var x = a + 1;
+''',
+      () => _xInitializer(),
+      () => [findNode.simple('a +')],
+    );
+  }
+
+  test_simpleIdentifier_type_class() async {
+    await _assertConst(r'''
+var x = int;
+''', () => _xInitializer());
+  }
+
+  test_stringInterpolation_topVar_const() async {
+    await _assertConst(r'''
+const a = 0;
+var x = 'a $a b';
+''', () => _xInitializer());
+  }
+
+  test_stringInterpolation_topVar_final() async {
+    await _assertNotConst(
+      r'''
+final a = 0;
+var x = 'a $a b';
+''',
+      () => _xInitializer(),
+      () => [findNode.simple('a b')],
+    );
+  }
+
+  _assertConst(String code, AstNode Function() getNode) async {
+    addTestFile(code);
+    await resolveTestFile();
+
+    var node = getNode();
+    var notConstList = getNotPotentiallyConstants(node);
+    expect(notConstList, isEmpty);
+  }
+
+  _assertNotConst(String code, AstNode Function() getNode,
+      List<AstNode> Function() getNotConstList) async {
+    addTestFile(code);
+    await resolveTestFile();
+
+    var node = getNode();
+    var notConstList = getNotPotentiallyConstants(node);
+
+    var expectedNotConst = getNotConstList();
+    expect(notConstList, unorderedEquals(expectedNotConst));
+  }
+
+  Expression _xInitializer() {
+    return findNode.variableDeclaration('x = ').initializer;
+  }
+}
+
+@reflectiveTest
+class PotentiallyConstantWithUIAsCodeTest extends PotentiallyConstantTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+  test_ifElement_then() async {
+    await _assertConst(r'''
+const a = 0;
+const b = 0;
+var x = const [if (a) b];
+''', () => _xInitializer());
+  }
+
+  test_ifElement_then_final() async {
+    await _assertNotConst(r'''
+final a = 0;
+final b = 0;
+var x = const [if (a) b];
+''', () => _xInitializer(),
+        () => [findNode.simple('a)'), findNode.simple('b]')]);
+  }
+
+  test_ifElement_thenElse() async {
+    await _assertConst(r'''
+const a = 0;
+const b = 0;
+const c = 0;
+var x = const [if (a) b else c];
+''', () => _xInitializer());
+  }
+
+  test_spreadElement() async {
+    await _assertConst(r'''
+const a = [0, 1, 2];
+var x = const [...a];
+''', () => _xInitializer());
+  }
+
+  test_spreadElement_final() async {
+    await _assertNotConst(r'''
+final a = [0, 1, 2];
+var x = const [...a];
+''', () => _xInitializer(), () => [findNode.simple('a];')]);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/constant/test_all.dart b/pkg/analyzer/test/src/dart/constant/test_all.dart
index 022da95..95c1b2e 100644
--- a/pkg/analyzer/test/src/dart/constant/test_all.dart
+++ b/pkg/analyzer/test/src/dart/constant/test_all.dart
@@ -5,13 +5,14 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'evaluation_test.dart' as evaluation;
+import 'potentially_constant_test.dart' as potentially_constant;
 import 'utilities_test.dart' as utilities;
 import 'value_test.dart' as value;
 
-/// Utility for manually running all tests.
 main() {
   defineReflectiveSuite(() {
     evaluation.main();
+    potentially_constant.main();
     utilities.main();
     value.main();
   }, name: 'constant');
diff --git a/pkg/analyzer/test/src/dart/constant/utilities_test.dart b/pkg/analyzer/test/src/dart/constant/utilities_test.dart
index 0fa3898..f501f97 100644
--- a/pkg/analyzer/test/src/dart/constant/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/utilities_test.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -17,7 +18,6 @@
 import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
 import 'package:analyzer/src/generated/testing/element_factory.dart';
 import 'package:analyzer/src/generated/testing/test_type_provider.dart';
-import 'package:analyzer/src/task/dart.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analyzer/test/src/dart/resolution/for_element_test.dart b/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
new file mode 100644
index 0000000..3069acf
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
@@ -0,0 +1,69 @@
+// 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 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ForEachElementTest);
+    defineReflectiveTests(ForLoopElementTest);
+  });
+}
+
+@reflectiveTest
+class ForEachElementTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+  test_declaredIdentifierScope() async {
+    addTestFile(r'''
+main() {
+  <int>[for (var i in [1, 2, 3]) i]; // 1
+  <double>[for (var i in [1.1, 2.2, 3.3]) i]; // 2
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertElement(
+      findNode.simple('i]; // 1'),
+      findNode.simple('i in [1, 2').staticElement,
+    );
+    assertElement(
+      findNode.simple('i]; // 2'),
+      findNode.simple('i in [1.1').staticElement,
+    );
+  }
+}
+
+@reflectiveTest
+class ForLoopElementTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+  test_declaredVariableScope() async {
+    addTestFile(r'''
+main() {
+  <int>[for (var i = 1; i < 10; i += 3) i]; // 1
+  <double>[for (var i = 1.1; i < 10; i += 5) i]; // 2
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertElement(
+      findNode.simple('i]; // 1'),
+      findNode.simple('i = 1;').staticElement,
+    );
+    assertElement(
+      findNode.simple('i]; // 2'),
+      findNode.simple('i = 1.1;').staticElement,
+    );
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index 71d5075..ccbc919 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -1,51 +1,57 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// 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 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'assignment_test.dart' as assignment_test;
-import 'class_test.dart' as class_test;
-import 'comment_test.dart' as comment_test;
-import 'constant_test.dart' as constant_test;
-import 'enum_test.dart' as enum_test;
-import 'flow_analysis_test.dart' as flow_analysis_test;
-import 'for_in_test.dart' as for_in_test;
-import 'generic_type_alias_test.dart' as generic_type_alias_test;
-import 'import_prefix_test.dart' as import_prefix_test;
-import 'instance_creation_test.dart' as instance_creation_test;
+import 'assignment_test.dart' as assignment;
+import 'class_alias_test.dart' as class_alias;
+import 'class_test.dart' as class_resolution;
+import 'comment_test.dart' as comment;
+import 'constant_test.dart' as constant;
+import 'definite_assignment_test.dart' as definite_assignment;
+import 'enum_test.dart' as enum_resolution;
+import 'flow_analysis_test.dart' as flow_analysis;
+import 'for_element_test.dart' as for_element;
+import 'for_in_test.dart' as for_in;
+import 'generic_type_alias_test.dart' as generic_type_alias;
+import 'import_prefix_test.dart' as import_prefix;
+import 'instance_creation_test.dart' as instance_creation;
 import 'instance_member_inference_class_test.dart'
-    as instance_member_inference_class_test;
+    as instance_member_inference_class;
 import 'instance_member_inference_mixin_test.dart'
-    as instance_member_inference_mixin_test;
-import 'method_invocation_test.dart' as method_invocation_test;
-import 'mixin_test.dart' as mixin_test;
-import 'non_nullable_test.dart' as non_nullable_test;
-import 'optional_const_test.dart' as optional_const_test;
-import 'property_access_test.dart' as property_access_test;
-import 'top_type_inference_test.dart' as top_type_inference_test;
+    as instance_member_inference_mixin;
+import 'method_invocation_test.dart' as method_invocation;
+import 'mixin_test.dart' as mixin_resolution;
+import 'non_nullable_test.dart' as non_nullable;
+import 'optional_const_test.dart' as optional_const;
+import 'property_access_test.dart' as property_access;
+import 'top_type_inference_test.dart' as top_type_inference;
 import 'type_inference/test_all.dart' as type_inference;
 
 main() {
   defineReflectiveSuite(() {
-    assignment_test.main();
-    class_test.main();
-    comment_test.main();
-    constant_test.main();
-    enum_test.main();
-    flow_analysis_test.main();
-    for_in_test.main();
-    generic_type_alias_test.main();
-    import_prefix_test.main();
-    instance_creation_test.main();
-    instance_member_inference_class_test.main();
-    instance_member_inference_mixin_test.main();
-    method_invocation_test.main();
-    mixin_test.main();
-    non_nullable_test.main();
-    optional_const_test.main();
-    property_access_test.main();
-    top_type_inference_test.main();
+    assignment.main();
+    class_alias.main();
+    class_resolution.main();
+    comment.main();
+    constant.main();
+    definite_assignment.main();
+    enum_resolution.main();
+    flow_analysis.main();
+    for_element.main();
+    for_in.main();
+    generic_type_alias.main();
+    import_prefix.main();
+    instance_creation.main();
+    instance_member_inference_class.main();
+    instance_member_inference_mixin.main();
+    method_invocation.main();
+    mixin_resolution.main();
+    non_nullable.main();
+    optional_const.main();
+    property_access.main();
+    top_type_inference.main();
     type_inference.main();
   }, name: 'resolution');
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
index 2f0f5a8..1f90c94 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
@@ -41,7 +41,35 @@
     assertType(findNode.listLiteral('['), 'List<String>');
   }
 
-  test_context_typeArgs_expression_conflict() async {
+  test_context_noTypeArgs_noElements_typeParameter() async {
+    addTestFile('''
+class A<E extends List<int>> {
+  E a = [];
+}
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('['), 'List<dynamic>');
+  }
+
+  test_context_noTypeArgs_noElements_typeParameter_dynamic() async {
+    addTestFile('''
+class A<E extends List<dynamic>> {
+  E a = [];
+}
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('['), 'List<dynamic>');
+  }
+
+  test_context_typeArgs_expression_conflictingContext() async {
+    addTestFile('''
+List<String> a = <int>[0];
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('['), 'List<int>');
+  }
+
+  test_context_typeArgs_expression_conflictingExpression() async {
     addTestFile('''
 List<String> a = <String>[0];
 ''');
@@ -49,6 +77,17 @@
     assertType(findNode.listLiteral('['), 'List<String>');
   }
 
+  @failingTest
+  test_context_typeArgs_expression_conflictingTypeArgs() async {
+    // Context type and element types both suggest `String`, so this should
+    // override the explicit type argument.
+    addTestFile('''
+List<String> a = <int>['a'];
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('['), 'List<String>');
+  }
+
   test_context_typeArgs_expression_noConflict() async {
     addTestFile('''
 List<String> a = <String>['a'];
@@ -73,15 +112,7 @@
     assertType(findNode.listLiteral('['), 'List<String>');
   }
 
-  test_noContext_noTypeArgs_expressions_conflict() async {
-    addTestFile('''
-var a = [1, '2', 3];
-''');
-    await resolveTestFile();
-    assertType(findNode.listLiteral('['), 'List<Object>');
-  }
-
-  test_noContext_noTypeArgs_expressions_noConflict() async {
+  test_noContext_noTypeArgs_expressions_lubOfInt() async {
     addTestFile('''
 var a = [1, 2, 3];
 ''');
@@ -89,6 +120,22 @@
     assertType(findNode.listLiteral('['), 'List<int>');
   }
 
+  test_noContext_noTypeArgs_expressions_lubOfNum() async {
+    addTestFile('''
+var a = [1, 2.3, 4];
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('['), 'List<num>');
+  }
+
+  test_noContext_noTypeArgs_expressions_lubOfObject() async {
+    addTestFile('''
+var a = [1, '2', 3];
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('['), 'List<Object>');
+  }
+
   test_noContext_noTypeArgs_noElements() async {
     addTestFile('''
 var a = [];
@@ -113,6 +160,15 @@
     assertType(findNode.listLiteral('['), 'List<int>');
   }
 
+  @failingTest
+  test_noContext_typeArgs_expressions_conflict() async {
+    addTestFile('''
+var a = <int, String>[1, 2];
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('['), 'List<int>');
+  }
+
   test_noContext_typeArgs_noElements() async {
     addTestFile('''
 var a = <num>[];
@@ -134,7 +190,7 @@
 
   test_noContext_noTypeArgs_forEachWithDeclaration() async {
     addTestFile('''
-var c = [1, 2, 3];
+List<int> c;
 var a = [for (int e in c) e * 2];
 ''');
     await resolveTestFile();
@@ -143,7 +199,7 @@
 
   test_noContext_noTypeArgs_forEachWithIdentifier() async {
     addTestFile('''
-var c = [1, 2, 3];
+List<int> c;
 int b;
 var a = [for (b in c) b * 2];
 ''');
@@ -170,72 +226,90 @@
 
   test_noContext_noTypeArgs_if() async {
     addTestFile('''
-var c = true;
+bool c = true;
 var a = [if (c) 1];
 ''');
     await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<int>');
   }
 
-  test_noContext_noTypeArgs_ifElse_conflict() async {
+  test_noContext_noTypeArgs_ifElse_lubOfInt() async {
     addTestFile('''
-var c = true;
-var a = [if (c) 1 else '2'];
-''');
-    await resolveTestFile();
-    assertType(findNode.listLiteral('['), 'List<Object>');
-  }
-
-  test_noContext_noTypeArgs_ifElse_noConflict() async {
-    addTestFile('''
-var c = true;
+bool c = true;
 var a = [if (c) 1 else 2];
 ''');
     await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<int>');
   }
 
+  test_noContext_noTypeArgs_ifElse_lubOfNum() async {
+    addTestFile('''
+bool c = true;
+var a = [if (c) 1 else 2.3];
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('['), 'List<num>');
+  }
+
+  test_noContext_noTypeArgs_ifElse_lubOfObject() async {
+    addTestFile('''
+bool c = true;
+var a = [if (c) 1 else '2'];
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('['), 'List<Object>');
+  }
+
   test_noContext_noTypeArgs_spread() async {
     addTestFile('''
-var c = [1, 2, 3];
+List<int> c;
 var a = [...c];
 ''');
     await resolveTestFile();
     assertType(findNode.listLiteral('[...'), 'List<int>');
   }
 
-  test_noContext_noTypeArgs_spread_conflict() async {
+  test_noContext_noTypeArgs_spread_lubOfInt() async {
     addTestFile('''
-var c = [1];
-var b = ['a'];
-var a = [...b, ...c];
-''');
-    await resolveTestFile();
-    assertType(findNode.listLiteral('[...'), 'List<Object>');
-  }
-
-  test_noContext_noTypeArgs_spread_noConflict() async {
-    addTestFile('''
-var c = [1];
-var b = [2];
+List<int> c;
+List<int> b;
 var a = [...b, ...c];
 ''');
     await resolveTestFile();
     assertType(findNode.listLiteral('[...'), 'List<int>');
   }
 
-  test_noContext_noTypeArgs_spread_onlyNull() async {
+  test_noContext_noTypeArgs_spread_lubOfNum() async {
     addTestFile('''
-f() {
-  var futureNull = Future.value(null);
-  var a = [...?await futureNull];
-}
+List<int> c;
+List<double> b;
+var a = [...b, ...c];
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('[...'), 'List<num>');
+  }
+
+  test_noContext_noTypeArgs_spread_lubOfObject() async {
+    addTestFile('''
+List<int> c;
+List<String> b;
+var a = [...b, ...c];
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('[...'), 'List<Object>');
+  }
+
+  test_noContext_noTypeArgs_spread_nestedInIf_oneAmbiguous() async {
+    addTestFile('''
+List<int> c;
+dynamic d;
+var a = [if (0 < 1) ...c else ...d];
 ''');
     await resolveTestFile();
     assertType(findNode.listLiteral('['), 'List<dynamic>');
   }
 
-  test_noContext_noTypeArgs_spread_nullAndNotNull() async {
+  test_noContext_noTypeArgs_spread_nullAware_nullAndNotNull() async {
     addTestFile('''
 f() {
   var futureNull = Future.value(null);
@@ -243,6 +317,17 @@
 }
 ''');
     await resolveTestFile();
-    assertType(findNode.listLiteral('['), 'List<int>');
+    assertType(findNode.listLiteral('['), 'List<dynamic>');
+  }
+
+  test_noContext_noTypeArgs_spread_nullAware_onlyNull() async {
+    addTestFile('''
+f() {
+  var futureNull = Future.value(null);
+  var a = [...?await futureNull];
+}
+''');
+    await resolveTestFile();
+    assertType(findNode.listLiteral('['), 'List<Null>');
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
index e796c8e..7c7d5cd 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
@@ -20,7 +20,7 @@
 class MapLiteralTest extends DriverResolutionTest {
   AstNode setOrMapLiteral(String search) => findNode.setOrMapLiteral(search);
 
-  test_context_noTypeArgs_entry_conflict() async {
+  test_context_noTypeArgs_entry_conflictingKey() async {
     addTestFile('''
 Map<int, int> a = {'a' : 1};
 ''');
@@ -28,6 +28,14 @@
     assertType(setOrMapLiteral('{'), 'Map<int, int>');
   }
 
+  test_context_noTypeArgs_entry_conflictingValue() async {
+    addTestFile('''
+Map<int, int> a = {1 : 'a'};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{'), 'Map<int, int>');
+  }
+
   test_context_noTypeArgs_entry_noConflict() async {
     addTestFile('''
 Map<int, int> a = {1 : 2};
@@ -44,7 +52,27 @@
     assertType(setOrMapLiteral('{'), 'Map<String, String>');
   }
 
-  test_context_typeArgs_entry_conflict() async {
+  test_context_noTypeArgs_noEntries_typeParameters() async {
+    addTestFile('''
+class A<E extends Map<int, String>> {
+  E a = {};
+}
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{}'), 'Map<dynamic, dynamic>');
+  }
+
+  test_context_noTypeArgs_noEntries_typeParameters_dynamic() async {
+    addTestFile('''
+class A<E extends Map<dynamic, dynamic>> {
+  E a = {};
+}
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{}'), 'Map<dynamic, dynamic>');
+  }
+
+  test_context_typeArgs_entry_conflictingKey() async {
     addTestFile('''
 Map<String, String> a = <String, String>{0 : 'a'};
 ''');
@@ -52,6 +80,14 @@
     assertType(setOrMapLiteral('{'), 'Map<String, String>');
   }
 
+  test_context_typeArgs_entry_conflictingValue() async {
+    addTestFile('''
+Map<String, String> a = <String, String>{'a' : 1};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{'), 'Map<String, String>');
+  }
+
   test_context_typeArgs_entry_noConflict() async {
     addTestFile('''
 Map<String, String> a = <String, String>{'a' : 'b'};
@@ -76,15 +112,25 @@
     assertType(setOrMapLiteral('{'), 'Map<String, String>');
   }
 
-  test_noContext_noTypeArgs_expressions_conflict() async {
+  test_default_constructor_param_typed() async {
     addTestFile('''
-var a = {1 : '1', '2' : 2, 3 : '3'};
+class C {
+  const C({x = const <String, int>{}});
+}
 ''');
     await resolveTestFile();
-    assertType(setOrMapLiteral('{'), 'Map<Object, Object>');
   }
 
-  test_noContext_noTypeArgs_expressions_noConflict() async {
+  test_default_constructor_param_untyped() async {
+    addTestFile('''
+class C {
+  const C({x = const {}});
+}
+''');
+    await resolveTestFile();
+  }
+
+  test_noContext_noTypeArgs_expressions_lubOfIntAndString() async {
     addTestFile('''
 var a = {1 : 'a', 2 : 'b', 3 : 'c'};
 ''');
@@ -92,6 +138,22 @@
     assertType(setOrMapLiteral('{'), 'Map<int, String>');
   }
 
+  test_noContext_noTypeArgs_expressions_lubOfNumAndNum() async {
+    addTestFile('''
+var a = {1 : 2, 3.0 : 4, 5 : 6.0};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{'), 'Map<num, num>');
+  }
+
+  test_noContext_noTypeArgs_expressions_lubOfObjectAndObject() async {
+    addTestFile('''
+var a = {1 : '1', '2' : 2, 3 : '3'};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{'), 'Map<Object, Object>');
+  }
+
   test_noContext_noTypeArgs_noEntries() async {
     addTestFile('''
 var a = {};
@@ -100,9 +162,17 @@
     assertType(setOrMapLiteral('{'), 'Map<dynamic, dynamic>');
   }
 
-  test_noContext_typeArgs_entry_conflict() async {
+  test_noContext_typeArgs_entry_conflictingKey() async {
     addTestFile('''
-var a = <String, int>{'a' : 1};
+var a = <String, int>{1 : 2};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{'), 'Map<String, int>');
+  }
+
+  test_noContext_typeArgs_entry_conflictingValue() async {
+    addTestFile('''
+var a = <String, int>{'a' : 'b'};
 ''');
     await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<String, int>');
@@ -116,7 +186,7 @@
     assertType(setOrMapLiteral('{'), 'Map<int, int>');
   }
 
-  test_noContext_typeArgs_expression_conflict() async {
+  test_noContext_typeArgs_expression_conflictingElement() async {
     addTestFile('''
 var a = <int, String>{1};
 ''');
@@ -124,6 +194,15 @@
     assertType(setOrMapLiteral('{'), 'Map<int, String>');
   }
 
+  @failingTest
+  test_noContext_typeArgs_expressions_conflictingTypeArgs() async {
+    addTestFile('''
+var a = <int>{1 : 2, 3 : 4};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{'), 'Map<int, int>');
+  }
+
   test_noContext_typeArgs_noEntries() async {
     addTestFile('''
 var a = <num, String>{};
@@ -147,7 +226,7 @@
 
   test_noContext_noTypeArgs_forEachWithDeclaration() async {
     addTestFile('''
-var c = [1, 2, 3];
+List<int> c;
 var a = {for (int e in c) e : e * 2};
 ''');
     await resolveTestFile();
@@ -156,7 +235,7 @@
 
   test_noContext_noTypeArgs_forEachWithIdentifier() async {
     addTestFile('''
-var c = [1, 2, 3];
+List<int> c;
 int b;
 var a = {for (b in c) b * 2 : b};
 ''');
@@ -183,66 +262,118 @@
 
   test_noContext_noTypeArgs_if() async {
     addTestFile('''
-var c = true;
+bool c = true;
 var a = {if (c) 1 : 2};
 ''');
     await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<int, int>');
   }
 
-  test_noContext_noTypeArgs_ifElse_conflict() async {
+  test_noContext_noTypeArgs_ifElse_lubOfIntAndInt() async {
     addTestFile('''
-var c = true;
-var a = {if (c) 1 : '1' else '2': 2 };
-''');
-    await resolveTestFile();
-    assertType(setOrMapLiteral('{'), 'Map<Object, Object>');
-  }
-
-  test_noContext_noTypeArgs_ifElse_noConflict() async {
-    addTestFile('''
-var c = true;
+bool c = true;
 var a = {if (c) 1 : 3 else 2 : 4};
 ''');
     await resolveTestFile();
     assertType(setOrMapLiteral('{'), 'Map<int, int>');
   }
 
+  test_noContext_noTypeArgs_ifElse_lubOfNumAndNum() async {
+    addTestFile('''
+bool c = true;
+var a = {if (c) 1.0 : 3 else 2 : 4.0};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{'), 'Map<num, num>');
+  }
+
+  test_noContext_noTypeArgs_ifElse_lubOfObjectAndObject() async {
+    addTestFile('''
+bool c = true;
+var a = {if (c) 1 : '1' else '2': 2 };
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{'), 'Map<Object, Object>');
+  }
+
   test_noContext_noTypeArgs_spread() async {
     addTestFile('''
-Map<int, int> c = {1 : 1, 2 : 2, 3 : 3};
+Map<int, int> c;
 var a = {...c};
 ''');
     await resolveTestFile();
     assertType(setOrMapLiteral('{...'), 'Map<int, int>');
   }
 
-  test_noContext_noTypeArgs_spread_conflict() async {
+  test_noContext_noTypeArgs_spread_dynamic() async {
     addTestFile('''
-Map<int, int> c = {1 : 2};
-Map<String, String> b = {'a' : 'b'};
+var c = {};
+var a = {...c};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{...'), 'Map<dynamic, dynamic>');
+  }
+
+  test_noContext_noTypeArgs_spread_lubOfIntAndInt() async {
+    addTestFile('''
+Map<int, int> c;
+Map<int, int> b;
+var a = {...b, ...c};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{...'), 'Map<int, int>');
+  }
+
+  test_noContext_noTypeArgs_spread_lubOfNumAndNum() async {
+    addTestFile('''
+Map<int, double> c;
+Map<double, int> b;
+var a = {...b, ...c};
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{...'), 'Map<num, num>');
+  }
+
+  test_noContext_noTypeArgs_spread_lubOfObjectObject() async {
+    addTestFile('''
+Map<int, int> c;
+Map<String, String> b;
 var a = {...b, ...c};
 ''');
     await resolveTestFile();
     assertType(setOrMapLiteral('{...'), 'Map<Object, Object>');
   }
 
-  test_noContext_noTypeArgs_spread_dynamic() async {
+  test_noContext_noTypeArgs_spread_nestedInIf_oneAmbiguous() async {
     addTestFile('''
-var c = {1 : 1, 2 : 2, 3 : 3};
-var a = {...c};
+Map<String, int> c;
+dynamic d;
+var a = {if (0 < 1) ...c else ...d};
 ''');
     await resolveTestFile();
-    assertType(setOrMapLiteral('{...'), 'Map<int, int>');
+    assertType(setOrMapLiteral('{'), 'Map<dynamic, dynamic>');
   }
 
-  test_noContext_noTypeArgs_spread_noConflict() async {
+  @failingTest
+  test_noContext_noTypeArgs_spread_nullAware_nullAndNotNull() async {
     addTestFile('''
-Map<int, int> c = {1 : 3};
-Map<int, int> b = {2 : 4};
-var a = {...b, ...c};
+f() {
+  var futureNull = Future.value(null);
+  var a = {1 : 'a', ...?await futureNull, 2 : 'b'};
+}
 ''');
     await resolveTestFile();
-    assertType(setOrMapLiteral('{...'), 'Map<int, int>');
+    assertType(setOrMapLiteral('{1'), 'Map<int, String>');
+  }
+
+  test_noContext_noTypeArgs_spread_nullAware_onlyNull() async {
+    addTestFile('''
+f() {
+  var futureNull = Future.value(null);
+  var a = {...?await futureNull};
+}
+''');
+    await resolveTestFile();
+    assertType(setOrMapLiteral('{...'), 'dynamic');
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
index b4bd6a9..b2da4b7 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
@@ -54,7 +54,17 @@
     assertType(setLiteral('{}'), 'Set<dynamic>');
   }
 
-  test_context_typeArgs_expression_conflict() async {
+  test_context_noTypeArgs_noElements_typeParameter_dynamic() async {
+    addTestFile('''
+class A<E extends Set<dynamic>> {
+  E a = {};
+}
+''');
+    await resolveTestFile();
+    assertType(setLiteral('{}'), 'Set<dynamic>');
+  }
+
+  test_context_typeArgs_expression_conflictingExpression() async {
     addTestFile('''
 Set<String> a = <String>{0};
 ''');
@@ -62,6 +72,15 @@
     assertType(setLiteral('{'), 'Set<String>');
   }
 
+  @failingTest
+  test_context_typeArgs_expression_conflictingTypeArgs() async {
+    addTestFile('''
+Set<String> a = <int>{'a'};
+''');
+    await resolveTestFile();
+    assertType(setLiteral('{'), 'Set<String>');
+  }
+
   test_context_typeArgs_expression_noConflict() async {
     addTestFile('''
 Set<String> a = <String>{'a'};
@@ -86,15 +105,7 @@
     assertType(setLiteral('{'), 'Set<String>');
   }
 
-  test_noContext_noTypeArgs_expressions_conflict() async {
-    addTestFile('''
-var a = {1, '2', 3};
-''');
-    await resolveTestFile();
-    assertType(setLiteral('{'), 'Set<Object>');
-  }
-
-  test_noContext_noTypeArgs_expressions_noConflict() async {
+  test_noContext_noTypeArgs_expressions_lubOfInt() async {
     addTestFile('''
 var a = {1, 2, 3};
 ''');
@@ -102,6 +113,22 @@
     assertType(setLiteral('{'), 'Set<int>');
   }
 
+  test_noContext_noTypeArgs_expressions_lubOfNum() async {
+    addTestFile('''
+var a = {1, 2.3, 4};
+''');
+    await resolveTestFile();
+    assertType(setLiteral('{'), 'Set<num>');
+  }
+
+  test_noContext_noTypeArgs_expressions_lubOfObject() async {
+    addTestFile('''
+var a = {1, '2', 3};
+''');
+    await resolveTestFile();
+    assertType(setLiteral('{'), 'Set<Object>');
+  }
+
   test_noContext_typeArgs_expression_conflict() async {
     addTestFile('''
 var a = <String>{1};
@@ -118,6 +145,15 @@
     assertType(setLiteral('{'), 'Set<int>');
   }
 
+  @failingTest
+  test_noContext_typeArgs_expressions_conflict() async {
+    addTestFile('''
+var a = <int, String>{1, 2};
+''');
+    await resolveTestFile();
+    assertType(setLiteral('{'), 'Set<int>');
+  }
+
   test_noContext_typeArgs_noElements() async {
     addTestFile('''
 var a = <num>{};
@@ -139,16 +175,9 @@
   @override
   AstNode setLiteral(String search) => findNode.setOrMapLiteral(search);
 
-  @failingTest
-  @override
-  test_context_noTypeArgs_noElements_typeParameter() async {
-    // Failing because Map<dynamic, dynamic> is being inferred.
-    await super.test_context_noTypeArgs_noElements_typeParameter();
-  }
-
   test_noContext_noTypeArgs_forEachWithDeclaration() async {
     addTestFile('''
-var c = [1, 2, 3];
+List<int> c;
 var a = {for (int e in c) e * 2};
 ''');
     await resolveTestFile();
@@ -157,7 +186,7 @@
 
   test_noContext_noTypeArgs_forEachWithIdentifier() async {
     addTestFile('''
-var c = [1, 2, 3];
+List<int> c;
 int b;
 var a = {for (b in c) b * 2};
 ''');
@@ -184,57 +213,98 @@
 
   test_noContext_noTypeArgs_if() async {
     addTestFile('''
-var c = true;
+bool c = true;
 var a = {if (c) 1};
 ''');
     await resolveTestFile();
     assertType(setLiteral('{'), 'Set<int>');
   }
 
-  test_noContext_noTypeArgs_ifElse_conflict() async {
+  test_noContext_noTypeArgs_ifElse_lubOfInt() async {
     addTestFile('''
-var c = true;
-var a = {if (c) 1 else '2'};
-''');
-    await resolveTestFile();
-    assertType(setLiteral('{'), 'Set<Object>');
-  }
-
-  test_noContext_noTypeArgs_ifElse_noConflict() async {
-    addTestFile('''
-var c = true;
+bool c = true;
 var a = {if (c) 1 else 2};
 ''');
     await resolveTestFile();
     assertType(setLiteral('{'), 'Set<int>');
   }
 
+  test_noContext_noTypeArgs_ifElse_lubOfNum() async {
+    addTestFile('''
+bool c = true;
+var a = {if (c) 1 else 2.3};
+''');
+    await resolveTestFile();
+    assertType(setLiteral('{'), 'Set<num>');
+  }
+
+  test_noContext_noTypeArgs_ifElse_lubOfObject() async {
+    addTestFile('''
+bool c = true;
+var a = {if (c) 1 else '2'};
+''');
+    await resolveTestFile();
+    assertType(setLiteral('{'), 'Set<Object>');
+  }
+
   test_noContext_noTypeArgs_spread() async {
     addTestFile('''
-var c = [1, 2, 3];
+List<int> c;
 var a = {...c};
 ''');
     await resolveTestFile();
     assertType(setLiteral('{...'), 'Set<int>');
   }
 
-  test_noContext_noTypeArgs_spread_conflict() async {
+  test_noContext_noTypeArgs_spread_lubOfInt() async {
     addTestFile('''
-var c = [1];
-var b = ['a'];
+List<int> c;
+List<int> b;
+var a = {...b, ...c};
+''');
+    await resolveTestFile();
+    assertType(setLiteral('{...'), 'Set<int>');
+  }
+
+  test_noContext_noTypeArgs_spread_lubOfNum() async {
+    addTestFile('''
+List<int> c;
+List<double> b;
+var a = {...b, ...c};
+''');
+    await resolveTestFile();
+    assertType(setLiteral('{...'), 'Set<num>');
+  }
+
+  test_noContext_noTypeArgs_spread_lubOfObject() async {
+    addTestFile('''
+List<int> c;
+List<String> b;
 var a = {...b, ...c};
 ''');
     await resolveTestFile();
     assertType(setLiteral('{...'), 'Set<Object>');
   }
 
-  test_noContext_noTypeArgs_spread_noConflict() async {
+  test_noContext_noTypeArgs_spread_nestedInIf_oneAmbiguous() async {
     addTestFile('''
-var c = [1];
-var b = [2];
-var a = {...b, ...c};
+List<int> c;
+dynamic d;
+var a = {if (0 < 1) ...c else ...d};
 ''');
     await resolveTestFile();
-    assertType(setLiteral('{...'), 'Set<int>');
+    assertType(setLiteral('{'), 'Set<dynamic>');
+  }
+
+  @failingTest
+  test_noContext_noTypeArgs_spread_nullAware_nullAndNotNull() async {
+    addTestFile('''
+f() {
+  var futureNull = Future.value(null);
+  var a = {1, ...?await futureNull, 2};
+}
+''');
+    await resolveTestFile();
+    assertType(setLiteral('{1'), 'Set<int>');
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/ambiguous_set_or_map_literal_test.dart b/pkg/analyzer/test/src/diagnostics/ambiguous_set_or_map_literal_test.dart
new file mode 100644
index 0000000..8e95614
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/ambiguous_set_or_map_literal_test.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(AmbiguousSetOrMapLiteralBothTest);
+    defineReflectiveTests(AmbiguousSetOrMapLiteralEitherTest);
+  });
+}
+
+@reflectiveTest
+class AmbiguousSetOrMapLiteralBothTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [
+      EnableString.control_flow_collections,
+      EnableString.spread_collections
+    ];
+
+  test_setAndMap() async {
+    assertErrorsInCode('''
+Map<int, int> map;
+Set<int> set;
+var c = {...set, ...map};
+''', [CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH]);
+  }
+}
+
+@reflectiveTest
+class AmbiguousSetOrMapLiteralEitherTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [
+      EnableString.control_flow_collections,
+      EnableString.spread_collections
+    ];
+
+  test_setAndMap() async {
+    assertErrorsInCode('''
+var map;
+var set;
+var c = {...set, ...map};
+''', [CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart b/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart
index f51e17b..5f92e7f 100644
--- a/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart
@@ -2,6 +2,9 @@
 // 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 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -10,6 +13,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ConstEvalThrowsExceptionTest);
+    defineReflectiveTests(ConstEvalThrowsExceptionWithUIAsCodeTest);
   });
 }
 
@@ -80,4 +84,94 @@
     await resolveTestFile();
     assertNoTestErrors();
   }
+
+  test_default_constructor_arg_empty_map_importAnalyzedAfter() async {
+    addTestFile('''
+import 'other.dart';
+
+main() {
+  var c = const C();
+}
+''');
+    newFile('/test/lib/other.dart', content: '''
+class C {
+  final Map<String, int> m;
+  const C({this.m = const <String, int>{}})
+    : assert(m != null);
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    var otherFileResult =
+        await resolveFile(convertPath('/test/lib/other.dart'));
+    expect(otherFileResult.errors, isEmpty);
+  }
+
+  test_default_constructor_arg_empty_map_importAnalyzedBefore() async {
+    addTestFile('''
+import 'other.dart';
+
+main() {
+  var c = const C();
+}
+''');
+    newFile('/test/lib/other.dart', content: '''
+class C {
+  final Map<String, int> m;
+  const C({this.m = const <String, int>{}})
+    : assert(m != null);
+}
+''');
+    var otherFileResult =
+        await resolveFile(convertPath('/test/lib/other.dart'));
+    expect(otherFileResult.errors, isEmpty);
+    await resolveTestFile();
+    assertNoTestErrors();
+  }
+}
+
+@reflectiveTest
+class ConstEvalThrowsExceptionWithUIAsCodeTest
+    extends ConstEvalThrowsExceptionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [
+      EnableString.control_flow_collections,
+      EnableString.spread_collections,
+    ];
+
+  test_ifElement_false_thenNotEvaluated() async {
+    assertNoErrorsInCode('''
+const dynamic nil = null;
+const c = [if (1 < 0) nil + 1];
+''');
+  }
+
+  test_ifElement_nonBoolCondition_list() async {
+    assertErrorsInCode('''
+const dynamic nonBool = 3;
+const c = const [if (nonBool) 'a'];
+''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+  }
+
+  test_ifElement_nonBoolCondition_map() async {
+    assertErrorsInCode('''
+const dynamic nonBool = null;
+const c = const {if (nonBool) 'a' : 1};
+''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+  }
+
+  test_ifElement_nonBoolCondition_set() async {
+    assertErrorsInCode('''
+const dynamic nonBool = 'a';
+const c = const {if (nonBool) 3};
+''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+  }
+
+  test_ifElement_true_elseNotEvaluated() async {
+    assertNoErrorsInCode('''
+const dynamic nil = null;
+const c = [if (0 < 1) 3 else nil + 1];
+''');
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/const_map_key_expression_type_implements_equals_test.dart b/pkg/analyzer/test/src/diagnostics/const_map_key_expression_type_implements_equals_test.dart
new file mode 100644
index 0000000..9822a85
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/const_map_key_expression_type_implements_equals_test.dart
@@ -0,0 +1,118 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConstMapKeyExpressionTypeImplementsEqualsTest);
+    defineReflectiveTests(
+      ConstMapKeyExpressionTypeImplementsEqualsWithUIAsCodeTest,
+    );
+  });
+}
+
+@reflectiveTest
+class ConstMapKeyExpressionTypeImplementsEqualsTest
+    extends DriverResolutionTest {
+  test_abstract() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  const A();
+  bool operator==(Object other);
+}
+
+main() {
+  const {const A(): 0};
+}
+''');
+  }
+
+  test_constField() async {
+    await assertErrorsInCode(r'''
+main() {
+  const {double.INFINITY: 0};
+}
+''', [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+  }
+
+  test_direct() async {
+    await assertErrorsInCode(r'''
+class A {
+  const A();
+  operator ==(other) => false;
+}
+
+main() {
+  const {const A() : 0};
+}
+''', [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+  }
+
+  test_dynamic() async {
+    // Note: static type of B.a is "dynamic", but actual type of the const
+    // object is A.  We need to make sure we examine the actual type when
+    // deciding whether there is a problem with operator==.
+    await assertErrorsInCode(r'''
+class A {
+  const A();
+  operator ==(other) => false;
+}
+
+class B {
+  static const a = const A();
+}
+
+main() {
+  const {B.a : 0};
+}
+''', [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+  }
+
+  test_factory() async {
+    await assertErrorsInCode(r'''
+class A {
+  const factory A() = B;
+}
+
+class B implements A {
+  const B();
+  operator ==(o) => true;
+}
+
+main() {
+  const {const A(): 42};
+}
+''', [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+  }
+
+  test_super() async {
+    await assertErrorsInCode(r'''
+class A {
+  const A();
+  operator ==(other) => false;
+}
+
+class B extends A {
+  const B();
+}
+
+main() {
+  const {const B() : 0};
+}
+''', [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+  }
+}
+
+@reflectiveTest
+class ConstMapKeyExpressionTypeImplementsEqualsWithUIAsCodeTest
+    extends ConstMapKeyExpressionTypeImplementsEqualsTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+}
diff --git a/pkg/analyzer/test/src/diagnostics/const_set_element_type_implements_equals_test.dart b/pkg/analyzer/test/src/diagnostics/const_set_element_type_implements_equals_test.dart
new file mode 100644
index 0000000..95fa251
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/const_set_element_type_implements_equals_test.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConstSetElementTypeImplementsEqualsTest);
+    defineReflectiveTests(
+      ConstSetElementTypeImplementsEqualsWithUIAsCodeTest,
+    );
+  });
+}
+
+@reflectiveTest
+class ConstSetElementTypeImplementsEqualsTest extends DriverResolutionTest {
+  test_constField() async {
+    await assertErrorsInCode(r'''
+class A {
+  static const a = const A();
+  const A();
+  operator ==(other) => false;
+}
+main() {
+  const {A.a};
+}
+''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+  }
+
+  test_direct() async {
+    await assertErrorsInCode(r'''
+class A {
+  const A();
+  operator ==(other) => false;
+}
+main() {
+  const {const A()};
+}
+''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+  }
+
+  test_dynamic() async {
+    // Note: static type of B.a is "dynamic", but actual type of the const
+    // object is A.  We need to make sure we examine the actual type when
+    // deciding whether there is a problem with operator==.
+    await assertErrorsInCode(r'''
+class A {
+  const A();
+  operator ==(other) => false;
+}
+class B {
+  static const a = const A();
+}
+main() {
+  const {B.a};
+}
+''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+  }
+
+  test_factory() async {
+    await assertErrorsInCode(r'''
+class A { const factory A() = B; }
+
+class B implements A {
+  const B();
+
+  operator ==(o) => true;
+}
+
+main() {
+  var m = const {const A()};
+}
+''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+  }
+
+  test_super() async {
+    await assertErrorsInCode(r'''
+class A {
+  const A();
+  operator ==(other) => false;
+}
+class B extends A {
+  const B();
+}
+main() {
+  const {const B()};
+}
+''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+  }
+}
+
+@reflectiveTest
+class ConstSetElementTypeImplementsEqualsWithUIAsCodeTest
+    extends ConstSetElementTypeImplementsEqualsTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+  test_spread_list() async {
+    await assertErrorsInCode(r'''
+class A {
+  const A();
+  operator ==(other) => false;
+}
+
+main() {
+  const {...[A()]};
+}
+''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+  }
+
+  test_spread_set() async {
+    await assertErrorsInCode(r'''
+class A {
+  const A();
+  operator ==(other) => false;
+}
+
+main() {
+  const {...{A()}};
+}
+''', [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/const_spread_expected_list_or_set_test.dart b/pkg/analyzer/test/src/diagnostics/const_spread_expected_list_or_set_test.dart
new file mode 100644
index 0000000..9c8d9f4
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/const_spread_expected_list_or_set_test.dart
@@ -0,0 +1,120 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConstSpreadExpectedListOrSetTest);
+  });
+}
+
+@reflectiveTest
+class ConstSpreadExpectedListOrSetTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+  test_const_listInt() async {
+    await assertErrorsInCode('''
+const dynamic a = 5;
+var b = const <int>[...a];
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]);
+  }
+
+  test_const_listList() async {
+    await assertNoErrorsInCode('''
+const dynamic a = [5];
+var b = const <int>[...a];
+''');
+  }
+
+  test_const_listMap() async {
+    await assertErrorsInCode('''
+const dynamic a = <int, int>{0: 1};
+var b = const <int>[...a];
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]);
+  }
+
+  test_const_listNull() async {
+    await assertErrorsInCode('''
+const dynamic a = null;
+var b = const <int>[...a];
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]);
+  }
+
+  test_const_listNull_nullable() async {
+    await assertNoErrorsInCode('''
+const dynamic a = null;
+var b = const <int>[...?a];
+''');
+  }
+
+  test_const_listSet() async {
+    await assertNoErrorsInCode('''
+const dynamic a = <int>{5};
+var b = const <int>[...a];
+''');
+  }
+
+  test_const_setInt() async {
+    await assertErrorsInCode('''
+const dynamic a = 5;
+var b = const <int>{...a};
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]);
+  }
+
+  test_const_setList() async {
+    await assertNoErrorsInCode('''
+const dynamic a = <int>[5];
+var b = const <int>{...a};
+''');
+  }
+
+  test_const_setMap() async {
+    await assertErrorsInCode('''
+const dynamic a = <int, int>{1: 2};
+var b = const <int>{...a};
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]);
+  }
+
+  test_const_setNull() async {
+    await assertErrorsInCode('''
+const dynamic a = null;
+var b = const <int>{...a};
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET]);
+  }
+
+  test_const_setNull_nullable() async {
+    await assertNoErrorsInCode('''
+const dynamic a = null;
+var b = const <int>{...?a};
+''');
+  }
+
+  test_const_setSet() async {
+    await assertNoErrorsInCode('''
+const dynamic a = <int>{5};
+var b = const <int>{...a};
+''');
+  }
+
+  test_nonConst_listInt() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 5;
+var b = <int>[...a];
+''');
+  }
+
+  test_nonConst_setInt() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 5;
+var b = <int>{...a};
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/const_spread_expected_map_test.dart b/pkg/analyzer/test/src/diagnostics/const_spread_expected_map_test.dart
new file mode 100644
index 0000000..405a700
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/const_spread_expected_map_test.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConstSpreadExpectedMapTest);
+  });
+}
+
+@reflectiveTest
+class ConstSpreadExpectedMapTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+  test_const_mapInt() async {
+    await assertErrorsInCode('''
+const dynamic a = 5;
+var b = const <int, int>{...a};
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP]);
+  }
+
+  test_const_mapList() async {
+    await assertErrorsInCode('''
+const dynamic a = <int>[5];
+var b = const <int, int>{...a};
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP]);
+  }
+
+  test_const_mapMap() async {
+    await assertNoErrorsInCode('''
+const dynamic a = <int, int>{1: 2};
+var b = <int, int>{...a};
+''');
+  }
+
+  test_const_mapNull() async {
+    await assertErrorsInCode('''
+const dynamic a = null;
+var b = const <int, int>{...a};
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP]);
+  }
+
+  test_const_mapNull_nullable() async {
+    await assertNoErrorsInCode('''
+const dynamic a = null;
+var b = <int, int>{...?a};
+''');
+  }
+
+  test_const_mapSet() async {
+    await assertErrorsInCode('''
+const dynamic a = <int>{5};
+var b = const <int, int>{...a};
+''', [CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP]);
+  }
+
+  test_nonConst_mapInt() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 5;
+var b = <int, int>{...a};
+''');
+  }
+
+  test_nonConst_mapMap() async {
+    await assertNoErrorsInCode('''
+const dynamic a = {1: 2};
+var b = <int, int>{...a};
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/equal_keys_in_map_test.dart b/pkg/analyzer/test/src/diagnostics/equal_keys_in_map_test.dart
index 2469819..661e118 100644
--- a/pkg/analyzer/test/src/diagnostics/equal_keys_in_map_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/equal_keys_in_map_test.dart
@@ -24,44 +24,43 @@
       EnableString.spread_collections,
     ];
 
-  test_ifElement_elseBranch_evaluated_addsDuplicate() async {
+  test_ifElement_false_elseEvaluated() async {
     await assertErrorsInCode('''
-void main() {
-  const notTrue = false;
-  const {1: null, if (notTrue) 2: null else 1: null};
-}
+const c = {1: null, if (1 < 0) 2: null else 1: null};
 ''', [StaticWarningCode.EQUAL_KEYS_IN_MAP]);
   }
 
-  test_ifElement_evaluated_addsDuplicate() async {
+  test_ifElement_false_onlyElseEvaluated() async {
+    assertNoErrorsInCode('''
+const c = {if (0 < 1) 1 : 1 else 1 : 2};
+''');
+  }
+
+  test_ifElement_false_thenNotEvaluated() async {
+    assertNoErrorsInCode('''
+const c = {2 : 1, if (1 < 0) 2 : 2};
+''');
+  }
+
+  test_ifElement_true_elseNotEvaluated() async {
+    assertNoErrorsInCode('''
+const c = {1 : 1, if (0 < 1) 2 : 2 else 1 : 2};
+''');
+  }
+
+  test_ifElement_true_onlyThenEvaluated() async {
+    assertNoErrorsInCode('''
+const c = {if (0 < 1) 1 : 1 else 1 : 2};
+''');
+  }
+
+  test_ifElement_true_thenEvaluated() async {
     await assertErrorsInCode('''
-void main() {
-  const {1: null, if (true) 1: null};
-}
+const c = {1: null, if (0 < 1) 1: null};
 ''', [StaticWarningCode.EQUAL_KEYS_IN_MAP]);
   }
 
   @failingTest
-  test_ifElement_notEvaluated_doesntAddDuplicate() async {
-    await assertNoErrorsInCode('''
-void main() {
-  const notTrue = false;
-  const {1: null, if (notTrue) 1: null};
-}
-''');
-  }
-
-  @failingTest
-  test_ifElement_withElse_evaluated_doesntAddDuplicate() async {
-    await assertNoErrorsInCode('''
-void main() {
-  const isTrue = true;
-  const {if (isTrue) 1: null : 1 :null};
-}
-''');
-  }
-
-  @failingTest
   test_nonConst_noDuplicateReported() async {
     await assertNoErrorsInCode('''
 void main() {
@@ -70,7 +69,6 @@
 ''');
   }
 
-  @failingTest
   test_spreadElement_addsDuplicate() async {
     await assertErrorsInCode('''
 void main() {
diff --git a/pkg/analyzer/test/src/diagnostics/expression_in_map_test.dart b/pkg/analyzer/test/src/diagnostics/expression_in_map_test.dart
new file mode 100644
index 0000000..7f81b3c
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/expression_in_map_test.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ExpressionInMapTest);
+    defineReflectiveTests(ExpressionInMapWithUiAsCodeTest);
+  });
+}
+
+@reflectiveTest
+class ExpressionInMapTest extends DriverResolutionTest {
+  test_map() async {
+    await assertErrorsInCode('''
+var m = <String, int>{'a', 'b' : 2};
+''', [ParserErrorCode.EXPECTED_TOKEN, ParserErrorCode.MISSING_IDENTIFIER]);
+  }
+
+  test_map_const() async {
+    await assertErrorsInCode('''
+var m = <String, int>{'a', 'b' : 2};
+''', [ParserErrorCode.EXPECTED_TOKEN, ParserErrorCode.MISSING_IDENTIFIER]);
+  }
+}
+
+@reflectiveTest
+class ExpressionInMapWithUiAsCodeTest extends ExpressionInMapTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [
+      EnableString.control_flow_collections,
+      EnableString.spread_collections,
+    ];
+
+  test_map() async {
+    await assertErrorsInCode('''
+var m = <String, int>{'a', 'b' : 2};
+''', [CompileTimeErrorCode.EXPRESSION_IN_MAP]);
+  }
+
+  test_map_const() async {
+    await assertErrorsInCode('''
+var m = <String, int>{'a', 'b' : 2};
+''', [CompileTimeErrorCode.EXPRESSION_IN_MAP]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_cast_new_expr_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_cast_new_expr_test.dart
index f1c94b4..7ea31a2 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_cast_new_expr_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_cast_new_expr_test.dart
@@ -29,7 +29,10 @@
 class B extends A {
   const B();
 }
-''', [StrongModeCode.INVALID_CAST_NEW_EXPR]);
+''', [
+      StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE,
+      StrongModeCode.INVALID_CAST_NEW_EXPR,
+    ]);
   }
 
   test_listLiteral_nonConst() async {
@@ -53,7 +56,10 @@
 class B extends A {
   const B();
 }
-''', [StrongModeCode.INVALID_CAST_NEW_EXPR]);
+''', [
+      StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE,
+      StrongModeCode.INVALID_CAST_NEW_EXPR,
+    ]);
   }
 
   test_setLiteral_nonConst() async {
diff --git a/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
new file mode 100644
index 0000000..c92a8a0
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
@@ -0,0 +1,144 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ListElementTypeNotAssignableTest);
+    defineReflectiveTests(ListElementTypeNotAssignableWithUIAsCodeTest);
+  });
+}
+
+@reflectiveTest
+class ListElementTypeNotAssignableTest extends DriverResolutionTest {
+  test_explicitTypeArgs_const() async {
+    await assertErrorsInCode('''
+var v = const <String>[42];
+''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_explicitTypeArgs_const_actualTypeMatch() async {
+    await assertNoErrorsInCode('''
+const dynamic x = null;
+var v = const <String>[x];
+''');
+  }
+
+  test_explicitTypeArgs_const_actualTypeMismatch() async {
+    await assertErrorsInCode('''
+const dynamic x = 42;
+var v = const <String>[x];
+''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_explicitTypeArgs_notConst() async {
+    await assertErrorsInCode('''
+var v = <String> [42];
+''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+}
+
+@reflectiveTest
+class ListElementTypeNotAssignableWithUIAsCodeTest
+    extends ListElementTypeNotAssignableTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+  test_const_ifElement_thenElseFalse_intInt() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = const <int>[if (1 < 0) a else b];
+''');
+  }
+
+  test_const_ifElement_thenElseFalse_intString() async {
+    await assertErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 'b';
+var v = const <int>[if (1 < 0) a else b];
+''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_const_ifElement_thenFalse_intString() async {
+    await assertErrorsInCode('''
+var v = const <int>[if (1 < 0) 'a'];
+''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_const_ifElement_thenFalse_intString_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = const <int>[if (1 < 0) a];
+''');
+  }
+
+  test_const_ifElement_thenTrue_intInt() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int>[if (true) a];
+''');
+  }
+
+  test_const_ifElement_thenTrue_intString() async {
+    await assertErrorsInCode('''
+const dynamic a = 'a';
+var v = const <int>[if (true) a];
+''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_const_spread_intInt() async {
+    await assertNoErrorsInCode('''
+var v = const <int>[...[0, 1]];
+''');
+  }
+
+  test_nonConst_ifElement_thenElseFalse_intDynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 'a';
+const dynamic b = 'b';
+var v = <int>[if (1 < 0) a else b];
+''');
+  }
+
+  test_nonConst_ifElement_thenElseFalse_intInt() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = <int>[if (1 < 0) a else b];
+''');
+  }
+
+  test_nonConst_ifElement_thenFalse_intString() async {
+    await assertErrorsInCode('''
+var v = <int>[if (1 < 0) 'a'];
+''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_nonConst_ifElement_thenTrue_intDynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = <int>[if (true) a];
+''');
+  }
+
+  test_nonConst_ifElement_thenTrue_intInt() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = <int>[if (true) a];
+''');
+  }
+
+  test_nonConst_spread_intInt() async {
+    await assertNoErrorsInCode('''
+var v = <int>[...[0, 1]];
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart b/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart
new file mode 100644
index 0000000..140e53e
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MapEntryNotInMapTest);
+    defineReflectiveTests(MapEntryNotInMapWithUiAsCodeTest);
+  });
+}
+
+@reflectiveTest
+class MapEntryNotInMapTest extends DriverResolutionTest {
+  test_set() async {
+    await assertErrorsInCode('''
+var c = <int>{1:2};
+''', [ParserErrorCode.UNEXPECTED_TOKEN]);
+  }
+
+  test_set_const() async {
+    await assertErrorsInCode('''
+var c = const <int>{1:2};
+''', [ParserErrorCode.UNEXPECTED_TOKEN]);
+  }
+}
+
+@reflectiveTest
+class MapEntryNotInMapWithUiAsCodeTest extends MapEntryNotInMapTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [
+      EnableString.control_flow_collections,
+      EnableString.spread_collections,
+    ];
+
+  test_set() async {
+    await assertErrorsInCode('''
+var c = <int>{1:2};
+''', [CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP]);
+  }
+
+  test_set_const() async {
+    await assertErrorsInCode('''
+var c = const <int>{1:2};
+''', [CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
new file mode 100644
index 0000000..2ea6a69
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
@@ -0,0 +1,191 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MapKeyTypeNotAssignableTest);
+    defineReflectiveTests(MapKeyTypeNotAssignableWithUIAsCodeTest);
+  });
+}
+
+@reflectiveTest
+class MapKeyTypeNotAssignableTest extends DriverResolutionTest {
+  test_const_intInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int, bool>{a : true};
+''');
+  }
+
+  test_const_intString_dynamic() async {
+    await assertErrorsInCode('''
+const dynamic a = 'a';
+var v = const <int, bool>{a : true};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_const_intString_value() async {
+    await assertErrorsInCode('''
+var v = const <int, bool>{'a' : true};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_nonConst_intInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = <int, bool>{a : true};
+''');
+  }
+
+  test_nonConst_intString_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = <int, bool>{a : true};
+''');
+  }
+
+  test_nonConst_intString_value() async {
+    await assertErrorsInCode('''
+var v = <int, bool>{'a' : true};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+  }
+}
+
+@reflectiveTest
+class MapKeyTypeNotAssignableWithUIAsCodeTest
+    extends MapKeyTypeNotAssignableTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+  test_const_ifElement_thenElseFalse_intInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = const <int, bool>{if (1 < 0) a: true else b: false};
+''');
+  }
+
+  test_const_ifElement_thenElseFalse_intString_dynamic() async {
+    await assertErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 'b';
+var v = const <int, bool>{if (1 < 0) a: true else b: false};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_const_ifElement_thenFalse_intString_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = const <int, bool>{if (1 < 0) a: true};
+''');
+  }
+
+  test_const_ifElement_thenFalse_intString_value() async {
+    await assertErrorsInCode('''
+var v = const <int, bool>{if (1 < 0) 'a': true};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_const_ifElement_thenTrue_intInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int, bool>{if (true) a: true};
+''');
+  }
+
+  test_const_ifElement_thenTrue_intString_dynamic() async {
+    await assertErrorsInCode('''
+const dynamic a = 'a';
+var v = const <int, bool>{if (true) a: true};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_const_ifElement_thenTrue_notConst() async {
+    await assertErrorsInCode('''
+final a = 0;
+var v = const <int, bool>{if (1 < 2) a: true};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+  }
+
+  test_const_spread_intInt() async {
+    await assertNoErrorsInCode('''
+var v = const <int, String>{...{1: 'a'}};
+''');
+  }
+
+  test_const_spread_intString_dynamic() async {
+    await assertErrorsInCode('''
+const dynamic a = 'a';
+var v = const <int, String>{...{a: 'a'}};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_nonConst_ifElement_thenElseFalse_intInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = <int, bool>{if (1 < 0) a: true else b: false};
+''');
+  }
+
+  test_nonConst_ifElement_thenElseFalse_intString_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 'b';
+var v = <int, bool>{if (1 < 0) a: true else b: false};
+''');
+  }
+
+  test_nonConst_ifElement_thenFalse_intString_value() async {
+    await assertErrorsInCode('''
+var v = <int, bool>{if (1 < 0) 'a': true};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_nonConst_ifElement_thenTrue_intInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = <int, bool>{if (true) a: true};
+''');
+  }
+
+  test_nonConst_ifElement_thenTrue_intString_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = <int, bool>{if (true) a: true};
+''');
+  }
+
+  test_nonConst_spread_intInt() async {
+    await assertNoErrorsInCode('''
+var v = <int, String>{...{1: 'a'}};
+''');
+  }
+
+  test_nonConst_spread_intNum() async {
+    await assertNoErrorsInCode('''
+var v = <int, int>{...<num, num>{1: 1}};
+''');
+  }
+
+  test_nonConst_spread_intString() async {
+    await assertErrorsInCode('''
+var v = <int, String>{...{'a': 'a'}};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_nonConst_spread_intString_dynamic() async {
+    await assertNoErrorsInCode('''
+dynamic a = 'a';
+var v = <int, String>{...{a: 'a'}};
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
new file mode 100644
index 0000000..3a9bc4a
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
@@ -0,0 +1,191 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MapValueTypeNotAssignableTest);
+    defineReflectiveTests(MapValueTypeNotAssignableWithUIAsCodeTest);
+  });
+}
+
+@reflectiveTest
+class MapValueTypeNotAssignableTest extends DriverResolutionTest {
+  test_const_intInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <bool, int>{true: a};
+''');
+  }
+
+  test_const_intString_dynamic() async {
+    await assertErrorsInCode('''
+const dynamic a = 'a';
+var v = const <bool, int>{true: a};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_const_intString_value() async {
+    await assertErrorsInCode('''
+var v = const <bool, int>{true: 'a'};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_nonConst_intInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = <bool, int>{true: a};
+''');
+  }
+
+  test_nonConst_intString_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = <bool, int>{true: a};
+''');
+  }
+
+  test_nonConst_intString_value() async {
+    await assertErrorsInCode('''
+var v = <bool, int>{true: 'a'};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+  }
+}
+
+@reflectiveTest
+class MapValueTypeNotAssignableWithUIAsCodeTest
+    extends MapValueTypeNotAssignableTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+  test_const_ifElement_thenElseFalse_intInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = const <bool, int>{if (1 < 0) true: a else false: b};
+''');
+  }
+
+  test_const_ifElement_thenElseFalse_intString_dynamic() async {
+    await assertErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 'b';
+var v = const <bool, int>{if (1 < 0) true: a else false: b};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_const_ifElement_thenFalse_intString_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = const <bool, int>{if (1 < 0) true: a};
+''');
+  }
+
+  test_const_ifElement_thenFalse_intString_value() async {
+    await assertErrorsInCode('''
+var v = const <bool, int>{if (1 < 0) true: 'a'};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_const_ifElement_thenTrue_intInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <bool, int>{if (true) true: a};
+''');
+  }
+
+  test_const_ifElement_thenTrue_intString_dynamic() async {
+    await assertErrorsInCode('''
+const dynamic a = 'a';
+var v = const <bool, int>{if (true) true: a};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_const_ifElement_thenTrue_notConst() async {
+    await assertErrorsInCode('''
+final a = 0;
+var v = const <bool, int>{if (1 < 2) true: a};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+  }
+
+  test_const_spread_intInt() async {
+    await assertNoErrorsInCode('''
+var v = const <bool, int>{...{true: 1}};
+''');
+  }
+
+  test_const_spread_intString_dynamic() async {
+    await assertErrorsInCode('''
+const dynamic a = 'a';
+var v = const <bool, int>{...{true: a}};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_nonConst_ifElement_thenElseFalse_intInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = <bool, int>{if (1 < 0) true: a else false: b};
+''');
+  }
+
+  test_nonConst_ifElement_thenElseFalse_intString_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 'b';
+var v = <bool, int>{if (1 < 0) true: a else false: b};
+''');
+  }
+
+  test_nonConst_ifElement_thenFalse_intString_value() async {
+    await assertErrorsInCode('''
+var v = <bool, int>{if (1 < 0) true: 'a'};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_nonConst_ifElement_thenTrue_intInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = <bool, int>{if (true) true: a};
+''');
+  }
+
+  test_nonConst_ifElement_thenTrue_intString_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = <bool, int>{if (true) true: a};
+''');
+  }
+
+  test_nonConst_spread_intInt() async {
+    await assertNoErrorsInCode('''
+var v = <bool, int>{...{true: 1}};
+''');
+  }
+
+  test_nonConst_spread_intNum() async {
+    await assertNoErrorsInCode('''
+var v = <int, int>{...<num, num>{1: 1}};
+''');
+  }
+
+  test_nonConst_spread_intString() async {
+    await assertErrorsInCode('''
+var v = <bool, int>{...{true: 'a'}};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_nonConst_spread_intString_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = <bool, int>{...{true: a}};
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/missing_return_test.dart b/pkg/analyzer/test/src/diagnostics/missing_return_test.dart
new file mode 100644
index 0000000..5b03a7c
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/missing_return_test.dart
@@ -0,0 +1,111 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/test_utilities/package_mixin.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MissingReturnTest);
+  });
+}
+
+@reflectiveTest
+class MissingReturnTest extends DriverResolutionTest with PackageMixin {
+  test_async() async {
+    await assertErrorsInCode(r'''
+import 'dart:async';
+Future<int> f() async {}
+''', [HintCode.MISSING_RETURN]);
+  }
+
+  test_factory() async {
+    await assertErrorsInCode(r'''
+class A {
+  factory A() {}
+}
+''', [HintCode.MISSING_RETURN]);
+  }
+
+  test_function() async {
+    await assertErrorsInCode(r'''
+int f() {}
+''', [HintCode.MISSING_RETURN]);
+  }
+
+  test_method() async {
+    await assertErrorsInCode(r'''
+class A {
+  int m() {}
+}''', [HintCode.MISSING_RETURN]);
+  }
+
+  test_method_inferred() async {
+    await assertErrorsInCode(r'''
+abstract class A {
+  int m();
+}
+class B extends A {
+  m() {}
+}
+''', [HintCode.MISSING_RETURN]);
+  }
+
+  test_emptyFunctionBody() async {
+    await assertNoErrorsInCode(r'''
+abstract class A {
+  int m();
+}''');
+  }
+
+  test_expressionFunctionBody() async {
+    await assertNoErrorsInCode(r'''
+int f() => 0;
+''');
+  }
+
+  test_async_futureVoid() async {
+    await assertNoErrorsInCode(r'''
+import 'dart:async';
+Future<void> f() async {}
+''');
+  }
+
+  test_async_futureOrVoid() async {
+    await assertNoErrorsInCode(r'''
+import 'dart:async';
+FutureOr<void> f(Future f) async {}
+''');
+  }
+
+  test_noReturnType() async {
+    await assertNoErrorsInCode(r'''
+f() {}
+''');
+  }
+
+  test_voidReturnType() async {
+    await assertNoErrorsInCode(r'''
+void f() {}
+''');
+  }
+
+  test_alwaysThrows() async {
+    addMetaPackage();
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+@alwaysThrows
+void a() {
+  throw 'msg';
+}
+
+int f() {
+  a();
+}''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart b/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
new file mode 100644
index 0000000..4865ced
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+//    defineReflectiveTests(NonBoolConditionTest);
+    defineReflectiveTests(NonBoolConditionWithUIAsCodeTest);
+  });
+}
+
+//@reflectiveTest
+class NonBoolConditionTest extends DriverResolutionTest {}
+
+@reflectiveTest
+class NonBoolConditionWithUIAsCodeTest extends NonBoolConditionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [
+      EnableString.control_flow_collections,
+      EnableString.spread_collections,
+    ];
+
+  test_ifElement() async {
+    assertErrorsInCode('''
+const c = [if (3) 1];
+''', [StaticTypeWarningCode.NON_BOOL_CONDITION]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_list_element_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_list_element_test.dart
new file mode 100644
index 0000000..f90a4c4
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_list_element_test.dart
@@ -0,0 +1,101 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(NonConstantListElementTest);
+    defineReflectiveTests(NonConstantListElementWithUiAsCodeTest);
+  });
+}
+
+@reflectiveTest
+class NonConstantListElementTest extends DriverResolutionTest {
+  test_const_topVar() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const [a];
+''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+  }
+
+  test_nonConst_topVar() async {
+    await assertNoErrorsInCode('''
+final dynamic a = 0;
+var v = [a];
+''');
+  }
+}
+
+@reflectiveTest
+class NonConstantListElementWithUiAsCodeTest
+    extends NonConstantListElementTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [
+      EnableString.control_flow_collections,
+      EnableString.spread_collections,
+    ];
+
+  test_const_ifElement_thenElseFalse_finalElse() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const [if (1 < 0) 0 else a];
+''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+  }
+
+  test_const_ifElement_thenElseFalse_finalThen() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const [if (1 < 0) a else 0];
+''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+  }
+
+  test_const_ifElement_thenElseTrue_finalElse() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const [if (1 > 0) 0 else a];
+''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+  }
+
+  test_const_ifElement_thenElseTrue_finalThen() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const [if (1 > 0) a else 0];
+''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+  }
+
+  test_const_ifElement_thenFalse_constThen() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const [if (1 < 0) a];
+''');
+  }
+
+  test_const_ifElement_thenFalse_finalThen() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const [if (1 < 0) a];
+''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+  }
+
+  test_const_ifElement_thenTrue_constThen() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const [if (1 > 0) a];
+''');
+  }
+
+  test_const_ifElement_thenTrue_finalThen() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const [if (1 > 0) a];
+''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_map_element_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_map_element_test.dart
index 459422f..ddff55a 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_map_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_map_element_test.dart
@@ -12,6 +12,10 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantMapElementWithUiAsCodeTest);
+    defineReflectiveTests(NonConstantMapKeyTest);
+    defineReflectiveTests(NonConstantMapKeyWithUiAsCodeTest);
+    defineReflectiveTests(NonConstantMapValueTest);
+    defineReflectiveTests(NonConstantMapValueWithUiAsCodeTest);
   });
 }
 
@@ -74,7 +78,6 @@
 ''', [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
   }
 
-  @failingTest
   test_ifElementWithElse_mayBeConst() async {
     await assertNoErrorsInCode('''
 void main() {
@@ -101,3 +104,169 @@
 ''', [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
   }
 }
+
+@reflectiveTest
+class NonConstantMapKeyTest extends DriverResolutionTest {
+  test_const_topVar() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{a: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+  }
+
+  test_nonConst_topVar() async {
+    await assertNoErrorsInCode('''
+final dynamic a = 0;
+var v = <int, int>{a: 0};
+''');
+  }
+}
+
+@reflectiveTest
+class NonConstantMapKeyWithUiAsCodeTest extends NonConstantMapKeyTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [
+      EnableString.control_flow_collections,
+      EnableString.spread_collections,
+    ];
+
+  test_const_ifElement_thenElseFalse_finalElse() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 < 0) 0: 0 else a: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+  }
+
+  test_const_ifElement_thenElseFalse_finalThen() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 < 0) a: 0 else 0: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+  }
+
+  test_const_ifElement_thenElseTrue_finalElse() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 > 0) 0: 0 else a: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+  }
+
+  test_const_ifElement_thenElseTrue_finalThen() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 > 0) a: 0 else 0: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+  }
+
+  test_const_ifElement_thenFalse_constThen() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int, int>{if (1 < 0) a: 0};
+''');
+  }
+
+  test_const_ifElement_thenFalse_finalThen() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 < 0) a: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+  }
+
+  test_const_ifElement_thenTrue_constThen() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int, int>{if (1 > 0) a: 0};
+''');
+  }
+
+  test_const_ifElement_thenTrue_finalThen() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 > 0) a: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+  }
+}
+
+@reflectiveTest
+class NonConstantMapValueTest extends DriverResolutionTest {
+  test_const_topVar() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{0: a};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+  }
+
+  test_nonConst_topVar() async {
+    await assertNoErrorsInCode('''
+final dynamic a = 0;
+var v = <int, int>{0: a};
+''');
+  }
+}
+
+@reflectiveTest
+class NonConstantMapValueWithUiAsCodeTest extends NonConstantMapValueTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [
+      EnableString.control_flow_collections,
+      EnableString.spread_collections,
+    ];
+
+  test_const_ifElement_thenElseFalse_finalElse() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 < 0) 0: 0 else 0: a};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+  }
+
+  test_const_ifElement_thenElseFalse_finalThen() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 < 0) 0: a else 0: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+  }
+
+  test_const_ifElement_thenElseTrue_finalElse() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 > 0) 0: 0 else 0: a};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+  }
+
+  test_const_ifElement_thenElseTrue_finalThen() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 > 0) 0: a else 0: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+  }
+
+  test_const_ifElement_thenFalse_constThen() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int, int>{if (1 < 0) 0: a};
+''');
+  }
+
+  test_const_ifElement_thenFalse_finalThen() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 < 0) 0: a};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+  }
+
+  test_const_ifElement_thenTrue_constThen() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int, int>{if (1 > 0) 0: a};
+''');
+  }
+
+  test_const_ifElement_thenTrue_finalThen() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int, int>{if (1 > 0) 0: a};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart
new file mode 100644
index 0000000..1d8c475
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart
@@ -0,0 +1,100 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(NonConstantSetElementTest);
+    defineReflectiveTests(NonConstantSetElementWithUiAsCodeTest);
+  });
+}
+
+@reflectiveTest
+class NonConstantSetElementTest extends DriverResolutionTest {
+  test_const_topVar() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int>{a};
+''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+  }
+
+  test_nonConst_topVar() async {
+    await assertNoErrorsInCode('''
+final dynamic a = 0;
+var v = <int>{a};
+''');
+  }
+}
+
+@reflectiveTest
+class NonConstantSetElementWithUiAsCodeTest extends NonConstantSetElementTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [
+      EnableString.control_flow_collections,
+      EnableString.spread_collections,
+    ];
+
+  test_const_ifElement_thenElseFalse_finalElse() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int>{if (1 < 0) 0 else a};
+''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+  }
+
+  test_const_ifElement_thenElseFalse_finalThen() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int>{if (1 < 0) a else 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+  }
+
+  test_const_ifElement_thenElseTrue_finalElse() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int>{if (1 > 0) 0 else a};
+''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+  }
+
+  test_const_ifElement_thenElseTrue_finalThen() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int>{if (1 > 0) a else 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+  }
+
+  test_const_ifElement_thenFalse_constThen() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int>{if (1 < 0) a};
+''');
+  }
+
+  test_const_ifElement_thenFalse_finalThen() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int>{if (1 < 0) a};
+''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+  }
+
+  test_const_ifElement_thenTrue_constThen() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int>{if (1 > 0) a};
+''');
+  }
+
+  test_const_ifElement_thenTrue_finalThen() async {
+    await assertErrorsInCode('''
+final dynamic a = 0;
+var v = const <int>{if (1 > 0) a};
+''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart b/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart
new file mode 100644
index 0000000..f326006
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(NotIterableSpreadTest);
+  });
+}
+
+@reflectiveTest
+class NotIterableSpreadTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [
+      EnableString.control_flow_collections,
+      EnableString.spread_collections,
+    ];
+
+  test_iterable_list() async {
+    await assertNoErrorsInCode('''
+var a = [0];
+var v = [...a];
+''');
+  }
+
+  test_iterable_null() async {
+    await assertNoErrorsInCode('''
+var v = [...?null];
+''');
+  }
+
+  test_notIterable_direct() async {
+    await assertErrorsInCode('''
+var a = 0;
+var v = [...a];
+''', [CompileTimeErrorCode.NOT_ITERABLE_SPREAD]);
+  }
+
+  test_notIterable_forElement() async {
+    await assertErrorsInCode('''
+var a = 0;
+var v = [for (var i in []) ...a];
+''', [CompileTimeErrorCode.NOT_ITERABLE_SPREAD]);
+  }
+
+  test_notIterable_ifElement_else() async {
+    await assertErrorsInCode('''
+var a = 0;
+var v = [if (1 > 0) ...[] else ...a];
+''', [CompileTimeErrorCode.NOT_ITERABLE_SPREAD]);
+  }
+
+  test_notIterable_ifElement_then() async {
+    await assertErrorsInCode('''
+var a = 0;
+var v = [if (1 > 0) ...a];
+''', [CompileTimeErrorCode.NOT_ITERABLE_SPREAD]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart b/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart
new file mode 100644
index 0000000..a9bf651
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(NotMapSpreadTest);
+  });
+}
+
+@reflectiveTest
+class NotMapSpreadTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [
+      EnableString.control_flow_collections,
+      EnableString.spread_collections,
+    ];
+
+  test_map() async {
+    await assertNoErrorsInCode('''
+var a = {0: 0};
+var v = <int, int>{...a};
+''');
+  }
+
+  test_map_null() async {
+    await assertNoErrorsInCode('''
+var v = <int, int>{...?null};
+''');
+  }
+
+  test_notMap_direct() async {
+    await assertErrorsInCode('''
+var a = 0;
+var v = <int, int>{...a};
+''', [CompileTimeErrorCode.NOT_MAP_SPREAD]);
+  }
+
+  test_notMap_forElement() async {
+    await assertErrorsInCode('''
+var a = 0;
+var v = <int, int>{for (var i in []) ...a};
+''', [CompileTimeErrorCode.NOT_MAP_SPREAD]);
+  }
+
+  test_notMap_ifElement_else() async {
+    await assertErrorsInCode('''
+var a = 0;
+var v = <int, int>{if (1 > 0) ...<int, int>{} else ...a};
+''', [CompileTimeErrorCode.NOT_MAP_SPREAD]);
+  }
+
+  test_notMap_ifElement_then() async {
+    await assertErrorsInCode('''
+var a = 0;
+var v = <int, int>{if (1 > 0) ...a};
+''', [CompileTimeErrorCode.NOT_MAP_SPREAD]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart
new file mode 100644
index 0000000..10364de
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart
@@ -0,0 +1,145 @@
+// Copyright (c) 2019, 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 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(SetElementTypeNotAssignableTest);
+    defineReflectiveTests(SetElementTypeNotAssignableWithUIAsCodeTest);
+  });
+}
+
+@reflectiveTest
+class SetElementTypeNotAssignableTest extends DriverResolutionTest {
+  test_explicitTypeArgs_const() async {
+    await assertErrorsInCode('''
+var v = const <String>{42};
+''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_explicitTypeArgs_const_actualTypeMatch() async {
+    await assertNoErrorsInCode('''
+const dynamic x = null;
+var v = const <String>{x};
+''');
+  }
+
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/21119')
+  test_explicitTypeArgs_const_actualTypeMismatch() async {
+    await assertErrorsInCode('''
+const dynamic x = 42;
+var v = const <String>{x};
+''', [CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_explicitTypeArgs_notConst() async {
+    await assertErrorsInCode('''
+var v = <String>{42};
+''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+}
+
+@reflectiveTest
+class SetElementTypeNotAssignableWithUIAsCodeTest
+    extends SetElementTypeNotAssignableTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+  test_const_ifElement_thenElseFalse_intInt() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = const <int>{if (1 < 0) a else b};
+''');
+  }
+
+  test_const_ifElement_thenElseFalse_intString() async {
+    await assertErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 'b';
+var v = const <int>{if (1 < 0) a else b};
+''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_const_ifElement_thenFalse_intString() async {
+    await assertErrorsInCode('''
+var v = const <int>{if (1 < 0) 'a'};
+''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_const_ifElement_thenFalse_intString_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = const <int>{if (1 < 0) a};
+''');
+  }
+
+  test_const_ifElement_thenTrue_intInt() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int>{if (true) a};
+''');
+  }
+
+  test_const_ifElement_thenTrue_intString() async {
+    await assertErrorsInCode('''
+const dynamic a = 'a';
+var v = const <int>{if (true) a};
+''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_const_spread_intInt() async {
+    await assertNoErrorsInCode('''
+var v = const <int>{...[0, 1]};
+''');
+  }
+
+  test_nonConst_ifElement_thenElseFalse_intDynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 'a';
+const dynamic b = 'b';
+var v = <int>{if (1 < 0) a else b};
+''');
+  }
+
+  test_nonConst_ifElement_thenElseFalse_intInt() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+const dynamic b = 0;
+var v = <int>{if (1 < 0) a else b};
+''');
+  }
+
+  test_nonConst_ifElement_thenFalse_intString() async {
+    await assertErrorsInCode('''
+var v = <int>[if (1 < 0) 'a'];
+''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_nonConst_ifElement_thenTrue_intDynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 'a';
+var v = <int>{if (true) a};
+''');
+  }
+
+  test_nonConst_ifElement_thenTrue_intInt() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = <int>{if (true) a};
+''');
+  }
+
+  test_nonConst_spread_intInt() async {
+    await assertNoErrorsInCode('''
+var v = <int>{...[0, 1]};
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index fed2324..f1f3b5f 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -4,14 +4,26 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'ambiguous_set_or_map_literal_test.dart' as ambiguous_set_or_map_literal;
 import 'argument_type_not_assignable_test.dart' as argument_type_not_assignable;
 import 'can_be_null_after_null_aware_test.dart' as can_be_null_after_null_aware;
 import 'const_constructor_param_type_mismatch_test.dart'
     as const_constructor_param_type_mismatch;
+import 'const_constructor_with_mixin_with_field_test.dart'
+    as const_constructor_with_mixin_with_field;
+import 'const_eval_throws_exception_test.dart' as const_eval_throws_exception;
+import 'const_map_key_expression_type_implements_equals_test.dart'
+    as const_map_key_expression_type_implements_equals;
+import 'const_set_element_type_implements_equals_test.dart'
+    as const_set_element_type_implements_equals;
+import 'const_spread_expected_list_or_set_test.dart'
+    as const_spread_expected_list_or_set;
+import 'const_spread_expected_map_test.dart' as const_spread_expected_map;
 import 'dead_code_test.dart' as dead_code;
 import 'deprecated_member_use_test.dart' as deprecated_member_use;
 import 'division_optimization_test.dart' as division_optimization;
 import 'equal_keys_in_map_test.dart' as equal_keys_in_map;
+import 'expression_in_map_test.dart' as expression_in_map;
 import 'invalid_assignment_test.dart' as invalid_assignment;
 import 'invalid_cast_new_expr_test.dart' as invalid_cast_new_expr;
 import 'invalid_immutable_annotation_test.dart' as invalid_immutable_annotation;
@@ -22,15 +34,33 @@
     as invalid_override_different_default_values_positional;
 import 'invalid_required_param_test.dart' as invalid_required_param;
 import 'invalid_sealed_annotation_test.dart' as invalid_sealed_annotation;
+import 'invalid_visibility_annotation_test.dart'
+    as invalid_visibility_annotation;
+import 'list_element_type_not_assignable_test.dart'
+    as list_element_type_not_assignable;
+import 'map_entry_not_in_map_test.dart' as map_entry_not_in_map;
+import 'map_key_type_not_assignable_test.dart' as map_key_type_not_assignable;
+import 'map_value_type_not_assignable_test.dart'
+    as map_value_type_not_assignable;
+import 'missing_return_test.dart' as missing_return;
 import 'mixin_on_sealed_class_test.dart' as mixin_on_sealed_class;
 import 'must_be_immutable_test.dart' as must_be_immutable;
 import 'must_call_super_test.dart' as must_call_super;
-import 'subtype_of_sealed_class_test.dart' as subtype_of_sealed_class;
+import 'non_bool_condition_test.dart' as non_bool_condition;
+import 'non_constant_list_element_test.dart' as non_constant_list_element;
 import 'non_constant_map_element_test.dart' as non_constant_map_element;
+import 'non_constant_set_element_test.dart' as non_constant_set_element;
+import 'not_iterable_spread_test.dart' as not_iterable_spread;
+import 'not_map_spread_test.dart' as not_map_spread;
+import 'set_element_type_not_assignable_test.dart'
+    as set_element_type_not_assignable;
+import 'subtype_of_sealed_class_test.dart' as subtype_of_sealed_class;
 import 'top_level_instance_getter_test.dart' as top_level_instance_getter;
 import 'top_level_instance_method_test.dart' as top_level_instance_method;
 import 'type_check_is_not_null_test.dart' as type_check_is_not_null;
 import 'type_check_is_null_test.dart' as type_check_is_null;
+import 'unchecked_use_of_nullable_value_test.dart'
+    as unchecked_use_of_nullable_value;
 import 'undefined_getter_test.dart' as undefined_getter;
 import 'undefined_hidden_name_test.dart' as undefined_hidden_name;
 import 'undefined_operator_test.dart' as undefined_operator;
@@ -55,13 +85,21 @@
 
 main() {
   defineReflectiveSuite(() {
+    ambiguous_set_or_map_literal.main();
     argument_type_not_assignable.main();
     can_be_null_after_null_aware.main();
     const_constructor_param_type_mismatch.main();
+    const_constructor_with_mixin_with_field.main();
+    const_eval_throws_exception.main();
+    const_map_key_expression_type_implements_equals.main();
+    const_set_element_type_implements_equals.main();
+    const_spread_expected_list_or_set.main();
+    const_spread_expected_map.main();
     dead_code.main();
     deprecated_member_use.main();
     division_optimization.main();
     equal_keys_in_map.main();
+    expression_in_map.main();
     invalid_assignment.main();
     invalid_cast_new_expr.main();
     invalid_immutable_annotation.main();
@@ -70,15 +108,28 @@
     invalid_override_different_default_values_positional.main();
     invalid_required_param.main();
     invalid_sealed_annotation.main();
+    invalid_visibility_annotation.main();
+    list_element_type_not_assignable.main();
+    map_entry_not_in_map.main();
+    map_key_type_not_assignable.main();
+    map_value_type_not_assignable.main();
+    missing_return.main();
     mixin_on_sealed_class.main();
     must_be_immutable.main();
     must_call_super.main();
-    subtype_of_sealed_class.main();
+    non_bool_condition.main();
+    non_constant_list_element.main();
     non_constant_map_element.main();
+    non_constant_set_element.main();
+    not_iterable_spread.main();
+    not_map_spread.main();
+    set_element_type_not_assignable.main();
+    subtype_of_sealed_class.main();
     top_level_instance_getter.main();
     top_level_instance_method.main();
     type_check_is_not_null.main();
     type_check_is_null.main();
+    unchecked_use_of_nullable_value.main();
     undefined_getter.main();
     undefined_hidden_name.main();
     undefined_operator.main();
diff --git a/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart b/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
index dbb41eb..5ac8dc9 100644
--- a/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
@@ -37,6 +37,22 @@
 f() => [a, b, c];
 ''');
   }
+
+  void test_missingComma_afterIf() {
+    testRecovery('''
+f() => [a, if (x) b c];
+''', [ParserErrorCode.EXPECTED_ELSE_OR_COMMA], '''
+f() => [a, if (x) b, c];
+''', enableControlFlowCollections: true);
+  }
+
+  void test_missingComma_afterIfElse() {
+    testRecovery('''
+f() => [a, if (x) b else y c];
+''', [ParserErrorCode.EXPECTED_TOKEN], '''
+f() => [a, if (x) b else y, c];
+''', enableControlFlowCollections: true);
+  }
 }
 
 /**
@@ -72,6 +88,22 @@
 ''');
   }
 
+  void test_missingComma_afterIf() {
+    testRecovery('''
+f() => {a: b, if (x) c: d e: f};
+''', [ParserErrorCode.EXPECTED_ELSE_OR_COMMA], '''
+f() => {a: b, if (x) c: d, e: f};
+''', enableControlFlowCollections: true);
+  }
+
+  void test_missingComma_afterIfElse() {
+    testRecovery('''
+f() => {a: b, if (x) c: d else y: z e: f};
+''', [ParserErrorCode.EXPECTED_TOKEN], '''
+f() => {a: b, if (x) c: d else y: z, e: f};
+''', enableControlFlowCollections: true);
+  }
+
   void test_missingKey() {
     testRecovery('''
 f() => {: b};
@@ -259,8 +291,7 @@
     testUserDefinableOperatorWithSuper('^');
   }
 
-  @failingTest
-  void test_initializerList_missingComma() {
+  void test_initializerList_missingComma_assert() {
     // https://github.com/dart-lang/sdk/issues/33241
     testRecovery('''
 class Test {
@@ -277,6 +308,40 @@
 ''');
   }
 
+  void test_initializerList_missingComma_field() {
+    // https://github.com/dart-lang/sdk/issues/33241
+    testRecovery('''
+class Test {
+  Test()
+    : assert(true)
+      x = 2;
+}
+''', [ParserErrorCode.EXPECTED_TOKEN], '''
+class Test {
+  Test()
+    : assert(true),
+      x = 2;
+}
+''');
+  }
+
+  void test_initializerList_missingComma_thisField() {
+    // https://github.com/dart-lang/sdk/issues/33241
+    testRecovery('''
+class Test {
+  Test()
+    : assert(true)
+      this.x = 2;
+}
+''', [ParserErrorCode.EXPECTED_TOKEN], '''
+class Test {
+  Test()
+    : assert(true),
+      this.x = 2;
+}
+''');
+  }
+
   void test_isExpression_missingLeft() {
     testRecovery('''
 f() {
diff --git a/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart b/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
index f42bcdd..d0cdb3b 100644
--- a/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
@@ -19,13 +19,15 @@
   void testRecovery(
       String invalidCode, List<ErrorCode> errorCodes, String validCode,
       {CompilationUnit adjustValidUnitBeforeComparison(CompilationUnit unit),
+      bool enableControlFlowCollections,
       List<ErrorCode> expectedErrorsInValidCode}) {
     CompilationUnit validUnit;
 
     // Assert that the valid code is indeed valid.
     try {
-      validUnit =
-          parseCompilationUnit(validCode, codes: expectedErrorsInValidCode);
+      validUnit = parseCompilationUnit(validCode,
+          codes: expectedErrorsInValidCode,
+          enableControlFlowCollections: enableControlFlowCollections);
       validateTokenStream(validUnit.beginToken);
     } catch (e) {
 //      print('');
@@ -39,7 +41,8 @@
     // Compare the structures before asserting valid errors.
     GatheringErrorListener listener =
         new GatheringErrorListener(checkRanges: true);
-    CompilationUnit invalidUnit = parseCompilationUnit2(invalidCode, listener);
+    CompilationUnit invalidUnit = parseCompilationUnit2(invalidCode, listener,
+        enableControlFlowCollections: enableControlFlowCollections);
     validateTokenStream(invalidUnit.beginToken);
     if (adjustValidUnitBeforeComparison != null) {
       validUnit = adjustValidUnitBeforeComparison(validUnit);
diff --git a/pkg/analyzer/test/src/fasta/test_all.dart b/pkg/analyzer/test/src/fasta/test_all.dart
index 91b1a9c..adb1d99 100644
--- a/pkg/analyzer/test/src/fasta/test_all.dart
+++ b/pkg/analyzer/test/src/fasta/test_all.dart
@@ -7,11 +7,13 @@
 import 'ast_builder_test.dart' as ast_builder;
 import 'message_coverage_test.dart' as message_coverage;
 import 'recovery/test_all.dart' as recovery;
+import 'token_utils_test.dart' as token_utils;
 
 main() {
   defineReflectiveSuite(() {
     ast_builder.main();
     message_coverage.main();
     recovery.main();
+    token_utils.main();
   }, name: 'fasta');
 }
diff --git a/pkg/analyzer/test/src/services/available_declarations_test.dart b/pkg/analyzer/test/src/services/available_declarations_test.dart
index 2fe5b77..e82719f 100644
--- a/pkg/analyzer/test/src/services/available_declarations_test.dart
+++ b/pkg/analyzer/test/src/services/available_declarations_test.dart
@@ -348,6 +348,19 @@
     ]);
   }
 
+  test_added_part_withoutLibrary() async {
+    var b = convertPath('/home/test/lib/b.dart');
+
+    newFile(b, content: r'''
+part of 'a.dart';
+''');
+    tracker.changeFile(b);
+    await _doAllTrackerWork();
+
+    _assertHasNoLibrary('package:test/a.dart');
+    _assertHasNoLibrary('package:test/b.dart');
+  }
+
   test_chooseContext_inAnalysisRoot() async {
     var homePath = convertPath('/home');
     var testPath = convertPath('/home/test');
@@ -536,6 +549,30 @@
     _assertHasLibrary('package:test/b.dart');
   }
 
+  test_deleted_library_ofPart() async {
+    var a = convertPath('/home/test/lib/a.dart');
+    var b = convertPath('/home/test/lib/b.dart');
+
+    newFile(a, content: r'''
+part 'b.dart';
+''');
+    newFile(b, content: r'''
+part of 'a.dart';
+''');
+    tracker.addContext(testAnalysisContext);
+
+    await _doAllTrackerWork();
+    _assertHasLibrary('package:test/a.dart');
+    _assertHasNoLibrary('package:test/b.dart');
+
+    deleteFile(a);
+    tracker.changeFile(a);
+    await _doAllTrackerWork();
+
+    _assertHasNoLibrary('package:test/a.dart');
+    _assertHasNoLibrary('package:test/b.dart');
+  }
+
   test_deleted_part() async {
     var a = convertPath('/home/test/lib/a.dart');
     var b = convertPath('/home/test/lib/b.dart');
@@ -575,6 +612,19 @@
     ]);
   }
 
+  test_deleted_part_withoutLibrary() async {
+    var b = convertPath('/home/test/lib/b.dart');
+
+    newFile(b, content: r'''
+part of 'a.dart';
+''');
+    tracker.addContext(testAnalysisContext);
+
+    await _doAllTrackerWork();
+    _assertHasNoLibrary('package:test/a.dart');
+    _assertHasNoLibrary('package:test/b.dart');
+  }
+
   test_updated_exported() async {
     var a = convertPath('/home/test/lib/a.dart');
     var b = convertPath('/home/test/lib/b.dart');
@@ -713,6 +763,30 @@
       _ExpectedDeclaration.class_('C'),
     ]);
   }
+
+  test_updated_part_withoutLibrary() async {
+    var b = convertPath('/home/test/lib/b.dart');
+
+    newFile(b, content: r'''
+part of 'a.dart';
+class B {}
+''');
+    tracker.addContext(testAnalysisContext);
+
+    await _doAllTrackerWork();
+    _assertHasNoLibrary('package:test/a.dart');
+    _assertHasNoLibrary('package:test/b.dart');
+
+    newFile(b, content: r'''
+part of 'a.dart';
+class B2 {}
+''');
+    tracker.changeFile(b);
+
+    await _doAllTrackerWork();
+    _assertHasNoLibrary('package:test/a.dart');
+    _assertHasNoLibrary('package:test/b.dart');
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/services/test_all.dart b/pkg/analyzer/test/src/services/test_all.dart
new file mode 100644
index 0000000..95e0ef4
--- /dev/null
+++ b/pkg/analyzer/test/src/services/test_all.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, 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 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'available_declarations_test.dart' as available_declarations;
+
+main() {
+  defineReflectiveSuite(() {
+    available_declarations.main();
+  }, name: 'services');
+}
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 63c0599..b3a61b2 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -57,13 +57,15 @@
     bool withConstElements: true,
     bool withOffsets: false,
     bool withSyntheticAccessors: false,
-    bool withSyntheticFields: false}) {
+    bool withSyntheticFields: false,
+    bool withTypes: false}) {
   var writer = new _ElementWriter(
       withCodeRanges: withCodeRanges,
       withConstElements: withConstElements,
       withOffsets: withOffsets,
       withSyntheticAccessors: withSyntheticAccessors,
-      withSyntheticFields: withSyntheticFields);
+      withSyntheticFields: withSyntheticFields,
+      withTypes: withTypes);
   writer.writeLibraryElement(library);
 
   String actualText = writer.buffer.toString();
@@ -129,6 +131,7 @@
   final bool withConstElements;
   final bool withSyntheticAccessors;
   final bool withSyntheticFields;
+  final bool withTypes;
   final StringBuffer buffer = new StringBuffer();
 
   _ElementWriter(
@@ -136,7 +139,8 @@
       this.withConstElements: true,
       this.withOffsets: false,
       this.withSyntheticAccessors: false,
-      this.withSyntheticFields: false});
+      this.withSyntheticFields: false,
+      this.withTypes: false});
 
   bool isDynamicType(DartType type) => type is DynamicTypeImpl;
 
@@ -272,7 +276,7 @@
 
     if (e is ConstructorElementImpl) {
       if (e.constantInitializers != null) {
-        writeList(' : ', '', e.constantInitializers, ', ', writeExpression);
+        writeList(' : ', '', e.constantInitializers, ', ', writeNode);
       }
     }
 
@@ -303,190 +307,6 @@
     buffer.writeln(';');
   }
 
-  void writeExpression(AstNode e, [Expression enclosing]) {
-    bool needsParenthesis = e is Expression &&
-        enclosing != null &&
-        e.precedence2 < enclosing.precedence2;
-
-    if (needsParenthesis) {
-      buffer.write('(');
-    }
-
-    if (e == null) {
-      buffer.write('<null>');
-    } else if (e is SimpleIdentifier && e.name == '#invalidConst') {
-      buffer.write('#invalidConst');
-    } else if (e is Annotation) {
-      buffer.write('@');
-      writeExpression(e.name);
-      if (e.constructorName != null) {
-        buffer.write('.');
-        writeExpression(e.constructorName);
-      }
-      if (e.arguments != null) {
-        writeList('(', ')', e.arguments.arguments, ', ', writeExpression,
-            includeEmpty: true);
-      }
-    } else if (e is AssertInitializer) {
-      buffer.write('assert(');
-      writeExpression(e.condition);
-      if (e.message != null) {
-        buffer.write(', ');
-        writeExpression(e.message);
-      }
-      buffer.write(')');
-    } else if (e is BinaryExpression) {
-      writeExpression(e.leftOperand, e);
-      buffer.write(' ');
-      buffer.write(e.operator.lexeme);
-      buffer.write(' ');
-      writeExpression(e.rightOperand, e);
-    } else if (e is BooleanLiteral) {
-      buffer.write(e.value);
-    } else if (e is ConditionalExpression) {
-      writeExpression(e.condition);
-      buffer.write(' ? ');
-      writeExpression(e.thenExpression);
-      buffer.write(' : ');
-      writeExpression(e.elseExpression);
-    } else if (e is ConstructorFieldInitializer) {
-      writeExpression(e.fieldName);
-      buffer.write(' = ');
-      writeExpression(e.expression);
-    } else if (e is ConstructorName) {
-      writeExpression(e.type);
-      if (e.name != null) {
-        buffer.write('.');
-        writeExpression(e.name);
-      }
-    } else if (e is DoubleLiteral) {
-      buffer.write(e.value);
-    } else if (e is InstanceCreationExpression) {
-      if (e.keyword != null) {
-        buffer.write(e.keyword.lexeme);
-        buffer.write(' ');
-      }
-      writeExpression(e.constructorName);
-      writeList('(', ')', e.argumentList.arguments, ', ', writeExpression,
-          includeEmpty: true);
-    } else if (e is IntegerLiteral) {
-      buffer.write(e.value);
-    } else if (e is InterpolationExpression) {
-      buffer.write(r'${');
-      writeExpression(e.expression);
-      buffer.write(r'}');
-    } else if (e is InterpolationString) {
-      buffer.write(e.value.replaceAll("'", r"\'"));
-    } else if (e is ListLiteral) {
-      if (e.constKeyword != null) {
-        buffer.write('const ');
-      }
-      if (e.typeArguments != null) {
-        writeList('<', '>', e.typeArguments.arguments, ', ', writeExpression);
-      }
-      writeList('[', ']', e.elements2, ', ', writeExpression,
-          includeEmpty: true);
-    } else if (e is Label) {
-      writeExpression(e.label);
-      buffer.write(': ');
-    } else if (e is SetOrMapLiteral) {
-      if (e.constKeyword != null) {
-        buffer.write('const ');
-      }
-      if (e.typeArguments != null) {
-        writeList('<', '>', e.typeArguments.arguments, ', ', writeExpression);
-      }
-      writeList('{', '}', e.elements2, ', ', writeExpression,
-          includeEmpty: true);
-    } else if (e is MapLiteralEntry) {
-      writeExpression(e.key);
-      buffer.write(': ');
-      writeExpression(e.value);
-    } else if (e is MethodInvocation) {
-      if (e.target != null) {
-        writeExpression(e.target);
-        buffer.write(e.operator);
-      }
-      writeExpression(e.methodName);
-      if (e.typeArguments != null) {
-        writeList('<', '>', e.typeArguments.arguments, ', ', writeExpression);
-      }
-      writeList('(', ')', e.argumentList.arguments, ', ', writeExpression,
-          includeEmpty: true);
-    } else if (e is NamedExpression) {
-      writeExpression(e.name);
-      buffer.write(e.expression);
-    } else if (e is NullLiteral) {
-      buffer.write('null');
-    } else if (e is PrefixExpression) {
-      buffer.write(e.operator.lexeme);
-      writeExpression(e.operand, e);
-    } else if (e is PrefixedIdentifier) {
-      writeExpression(e.prefix);
-      buffer.write('.');
-      writeExpression(e.identifier);
-    } else if (e is PropertyAccess) {
-      writeExpression(e.target, e);
-      buffer.write('.');
-      writeExpression(e.propertyName);
-    } else if (e is RedirectingConstructorInvocation) {
-      buffer.write('this');
-      if (e.constructorName != null) {
-        buffer.write('.');
-        writeExpression(e.constructorName);
-      }
-      writeList('(', ')', e.argumentList.arguments, ', ', writeExpression,
-          includeEmpty: true);
-    } else if (e is SimpleIdentifier) {
-      if (withConstElements) {
-        buffer.writeln();
-        buffer.write('  ' * 4);
-        buffer.write(e.name);
-        buffer.write('/*');
-        buffer.write('location: ');
-        buffer.write(_getElementLocationString(e.staticElement));
-        buffer.write('*/');
-      } else {
-        buffer.write(e.name);
-      }
-    } else if (e is SimpleStringLiteral) {
-      buffer.write("'");
-      buffer.write(e.value.replaceAll("'", r"\'"));
-      buffer.write("'");
-    } else if (e is StringInterpolation) {
-      buffer.write("'");
-      e.elements.forEach(writeExpression);
-      buffer.write("'");
-    } else if (e is SuperConstructorInvocation) {
-      buffer.write('super');
-      if (e.constructorName != null) {
-        buffer.write('.');
-        writeExpression(e.constructorName);
-      }
-      writeList('(', ')', e.argumentList.arguments, ', ', writeExpression,
-          includeEmpty: true);
-    } else if (e is SuperExpression) {
-      buffer.write('super');
-    } else if (e is SymbolLiteral) {
-      buffer.write('#');
-      writeList('', '', e.components, '.',
-          (Token token) => buffer.write(token.lexeme));
-    } else if (e is ThisExpression) {
-      buffer.write('this');
-    } else if (e is TypeName) {
-      writeExpression(e.name);
-      if (e.typeArguments != null) {
-        writeList('<', '>', e.typeArguments.arguments, ', ', writeExpression);
-      }
-    } else {
-      fail('Unsupported expression type: ${e.runtimeType}');
-    }
-
-    if (needsParenthesis) {
-      buffer.write(')');
-    }
-  }
-
   void writeFunctionElement(FunctionElement e) {
     writeDocumentation(e);
     writeMetadata(e, '', '\n');
@@ -563,6 +383,11 @@
     }
   }
 
+  void writeInterfaceTypeArgsComment(Expression e) {
+    var typeArguments = (e.staticType as InterfaceType).typeArguments;
+    writeList('/*typeArgs=', '*/', typeArguments, ',', writeType);
+  }
+
   void writeLibraryElement(LibraryElement e) {
     if (e.documentationComment != null) {
       buffer.writeln(e.documentationComment);
@@ -603,7 +428,7 @@
   void writeMetadata(Element e, String prefix, String separator) {
     if (e.metadata.isNotEmpty) {
       writeList(prefix, '', e.metadata, '$separator$prefix', (a) {
-        writeExpression((a as ElementAnnotationImpl).annotationAst);
+        writeNode((a as ElementAnnotationImpl).annotationAst);
       });
       buffer.write(separator);
     }
@@ -653,6 +478,220 @@
     }
   }
 
+  void writeNode(AstNode e, [Expression enclosing]) {
+    bool needsParenthesis = e is Expression &&
+        enclosing != null &&
+        e.precedence2 < enclosing.precedence2;
+
+    if (needsParenthesis) {
+      buffer.write('(');
+    }
+
+    if (e == null) {
+      buffer.write('<null>');
+    } else if (e is SimpleIdentifier && e.name == '#invalidConst') {
+      buffer.write('#invalidConst');
+    } else if (e is AdjacentStrings) {
+      writeList("'", "'", e.strings, '',
+          (StringLiteral s) => buffer.write(s.stringValue),
+          includeEmpty: true);
+    } else if (e is Annotation) {
+      buffer.write('@');
+      writeNode(e.name);
+      if (e.constructorName != null) {
+        buffer.write('.');
+        writeNode(e.constructorName);
+      }
+      if (e.arguments != null) {
+        writeList('(', ')', e.arguments.arguments, ', ', writeNode,
+            includeEmpty: true);
+      }
+    } else if (e is AssertInitializer) {
+      buffer.write('assert(');
+      writeNode(e.condition);
+      if (e.message != null) {
+        buffer.write(', ');
+        writeNode(e.message);
+      }
+      buffer.write(')');
+    } else if (e is BinaryExpression) {
+      writeNode(e.leftOperand, e);
+      buffer.write(' ');
+      buffer.write(e.operator.lexeme);
+      buffer.write(' ');
+      writeNode(e.rightOperand, e);
+    } else if (e is BooleanLiteral) {
+      buffer.write(e.value);
+    } else if (e is ConditionalExpression) {
+      writeNode(e.condition);
+      buffer.write(' ? ');
+      writeNode(e.thenExpression);
+      buffer.write(' : ');
+      writeNode(e.elseExpression);
+    } else if (e is ConstructorFieldInitializer) {
+      writeNode(e.fieldName);
+      buffer.write(' = ');
+      writeNode(e.expression);
+    } else if (e is ConstructorName) {
+      writeNode(e.type);
+      if (e.name != null) {
+        buffer.write('.');
+        writeNode(e.name);
+      }
+    } else if (e is DoubleLiteral) {
+      buffer.write(e.value);
+    } else if (e is InstanceCreationExpression) {
+      if (e.keyword != null) {
+        buffer.write(e.keyword.lexeme);
+        buffer.write(' ');
+      }
+      writeNode(e.constructorName);
+      writeList('(', ')', e.argumentList.arguments, ', ', writeNode,
+          includeEmpty: true);
+    } else if (e is IntegerLiteral) {
+      buffer.write(e.value);
+    } else if (e is InterpolationExpression) {
+      buffer.write(r'${');
+      writeNode(e.expression);
+      buffer.write(r'}');
+    } else if (e is InterpolationString) {
+      buffer.write(e.value.replaceAll("'", r"\'"));
+    } else if (e is ListLiteral) {
+      if (e.constKeyword != null) {
+        buffer.write('const ');
+      }
+      if (e.typeArguments != null) {
+        writeList('<', '>', e.typeArguments.arguments, ', ', writeNode);
+      } else if (withTypes) {
+        writeInterfaceTypeArgsComment(e);
+      }
+      writeList('[', ']', e.elements2, ', ', writeNode, includeEmpty: true);
+    } else if (e is Label) {
+      writeNode(e.label);
+      buffer.write(': ');
+    } else if (e is SetOrMapLiteral) {
+      if (e.constKeyword != null) {
+        buffer.write('const ');
+      }
+      if (e.typeArguments != null) {
+        writeList('<', '>', e.typeArguments.arguments, ', ', writeNode);
+      } else if (withTypes) {
+        writeInterfaceTypeArgsComment(e);
+      }
+      writeList('{', '}', e.elements2, ', ', writeNode, includeEmpty: true);
+      if (e.isMap) {
+        buffer.write('/*isMap*/');
+      }
+      if (e.isSet) {
+        buffer.write('/*isSet*/');
+      }
+    } else if (e is MapLiteralEntry) {
+      writeNode(e.key);
+      buffer.write(': ');
+      writeNode(e.value);
+    } else if (e is MethodInvocation) {
+      if (e.target != null) {
+        writeNode(e.target);
+        buffer.write(e.operator);
+      }
+      writeNode(e.methodName);
+      if (e.typeArguments != null) {
+        writeList('<', '>', e.typeArguments.arguments, ', ', writeNode);
+      }
+      writeList('(', ')', e.argumentList.arguments, ', ', writeNode,
+          includeEmpty: true);
+    } else if (e is NamedExpression) {
+      writeNode(e.name);
+      buffer.write(e.expression);
+    } else if (e is NullLiteral) {
+      buffer.write('null');
+    } else if (e is ParenthesizedExpression) {
+      writeNode(e.expression, e);
+    } else if (e is PrefixExpression) {
+      buffer.write(e.operator.lexeme);
+      writeNode(e.operand, e);
+    } else if (e is PrefixedIdentifier) {
+      writeNode(e.prefix);
+      buffer.write('.');
+      writeNode(e.identifier);
+    } else if (e is PropertyAccess) {
+      writeNode(e.target, e);
+      buffer.write('.');
+      writeNode(e.propertyName);
+    } else if (e is RedirectingConstructorInvocation) {
+      buffer.write('this');
+      if (e.constructorName != null) {
+        buffer.write('.');
+        writeNode(e.constructorName);
+      }
+      writeList('(', ')', e.argumentList.arguments, ', ', writeNode,
+          includeEmpty: true);
+    } else if (e is SimpleIdentifier) {
+      if (withConstElements) {
+        buffer.writeln();
+        buffer.write('  ' * 4);
+        buffer.write(e.name);
+        buffer.write('/*');
+        buffer.write('location: ');
+        buffer.write(_getElementLocationString(e.staticElement));
+        buffer.write('*/');
+      } else {
+        buffer.write(e.name);
+      }
+    } else if (e is SimpleStringLiteral) {
+      buffer.write("'");
+      buffer.write(e.value.replaceAll("'", r"\'"));
+      buffer.write("'");
+    } else if (e is StringInterpolation) {
+      buffer.write("'");
+      e.elements.forEach(writeNode);
+      buffer.write("'");
+    } else if (e is SuperConstructorInvocation) {
+      buffer.write('super');
+      if (e.constructorName != null) {
+        buffer.write('.');
+        writeNode(e.constructorName);
+      }
+      writeList('(', ')', e.argumentList.arguments, ', ', writeNode,
+          includeEmpty: true);
+    } else if (e is SuperExpression) {
+      buffer.write('super');
+    } else if (e is SymbolLiteral) {
+      buffer.write('#');
+      writeList('', '', e.components, '.',
+          (Token token) => buffer.write(token.lexeme));
+    } else if (e is ThisExpression) {
+      buffer.write('this');
+    } else if (e is ThrowExpression) {
+      buffer.write('throw ');
+      writeNode(e.expression);
+    } else if (e is TypeName) {
+      writeNode(e.name);
+      if (e.typeArguments != null) {
+        writeList('<', '>', e.typeArguments.arguments, ', ', writeNode);
+      }
+    } else if (e is SpreadElement) {
+      buffer.write(e.spreadOperator.lexeme);
+      writeNode(e.expression);
+    } else if (e is IfElement) {
+      buffer.write('if (');
+      writeNode(e.condition);
+      buffer.write(') ');
+      writeNode(e.thenElement);
+      var elseElement = e.elseElement;
+      if (elseElement != null) {
+        buffer.write(' else ');
+        writeNode(elseElement);
+      }
+    } else {
+      fail('Unsupported expression type: ${e.runtimeType}');
+    }
+
+    if (needsParenthesis) {
+      buffer.write(')');
+    }
+  }
+
   void writeParameterElement(ParameterElement e) {
     String defaultValueSeparator;
     Expression defaultValue;
@@ -701,7 +740,7 @@
 
     if (defaultValue != null) {
       buffer.write(defaultValueSeparator);
-      writeExpression(defaultValue);
+      writeNode(defaultValue);
     }
 
     buffer.write(closeString);
@@ -802,16 +841,13 @@
 
     if (!e.isSynthetic) {
       expect(e.getter, isNotNull);
-      expect(e.getter.isSynthetic, isTrue);
-      expect(e.getter.variable, same(e));
-      expect(e.getter.enclosingElement, same(e.enclosingElement));
+      _assertSyntheticAccessorEnclosing(e, e.getter);
+
       if (e.isFinal || e.isConst) {
         expect(e.setter, isNull);
       } else {
         expect(e.setter, isNotNull);
-        expect(e.setter.isSynthetic, isTrue);
-        expect(e.setter.variable, same(e.getter.variable));
-        expect(e.setter.enclosingElement, same(e.enclosingElement));
+        _assertSyntheticAccessorEnclosing(e, e.getter);
       }
     }
 
@@ -842,7 +878,7 @@
       Expression initializer = (e as ConstVariableElement).constantInitializer;
       if (initializer != null) {
         buffer.write(' = ');
-        writeExpression(initializer);
+        writeNode(initializer);
       }
     }
 
@@ -922,6 +958,23 @@
     }
   }
 
+  /// Assert that the [accessor] of the [property] is correctly linked to
+  /// the same enclosing element as the [property].
+  void _assertSyntheticAccessorEnclosing(
+      PropertyInducingElement property, PropertyAccessorElement accessor) {
+    expect(accessor.isSynthetic, isTrue);
+    expect(accessor.variable, same(property));
+
+    var propertyEnclosing = property.enclosingElement;
+    expect(accessor.enclosingElement, same(propertyEnclosing));
+
+    if (propertyEnclosing is CompilationUnitElement) {
+      expect(propertyEnclosing.accessors, contains(accessor));
+    } else if (propertyEnclosing is ClassElement) {
+      expect(propertyEnclosing.accessors, contains(accessor));
+    }
+  }
+
   String _getElementLocationString(Element element) {
     if (element == null) {
       return 'null';
diff --git a/pkg/analyzer/test/src/summary/expr_builder_test.dart b/pkg/analyzer/test/src/summary/expr_builder_test.dart
index 92cfb7f..67a8ae9 100644
--- a/pkg/analyzer/test/src/summary/expr_builder_test.dart
+++ b/pkg/analyzer/test/src/summary/expr_builder_test.dart
@@ -31,124 +31,6 @@
 class ExprBuilderTest extends ResynthesizeTestStrategyTwoPhase
     with ExprBuilderTestCases, ExprBuilderTestHelpers {}
 
-@reflectiveTest
-class TokensToStringTest {
-  void test_empty_list_no_space() {
-    // This is an interesting test case because "[]" is scanned as a single
-    // token, but the parser splits it into two.
-    _check('[]');
-  }
-
-  void test_empty_list_with_space() {
-    _check('[ ]');
-  }
-
-  void test_gt_gt_gt_in_type() {
-    // This is an interesting test case because ">>>" is scanned as a single
-    // token, but the parser splits it into three.
-    _check('A<B<C>>>[]');
-  }
-
-  void test_gt_gt_gt_in_type_split_both() {
-    _check('A<B<C> > >[]');
-  }
-
-  void test_gt_gt_gt_in_type_split_left() {
-    _check('A<B<C> >>[]');
-  }
-
-  void test_gt_gt_gt_in_type_split_right() {
-    _check('A<B<C>> >[]');
-  }
-
-  void test_gt_gt_in_type() {
-    // This is an interesting test case because ">>" is scanned as a single
-    // token, but the parser splits it into two.
-    _check('<A<B>>[]');
-  }
-
-  void test_gt_gt_in_type_split() {
-    _check('A<B> >[]');
-  }
-
-  void test_identifier() {
-    _check('foo');
-  }
-
-  void test_interpolation_expr_at_end_of_string() {
-    _check(r'"foo${bar}"');
-  }
-
-  void test_interpolation_expr_at_start_of_string() {
-    _check(r'"${foo}bar"');
-  }
-
-  void test_interpolation_expr_inside_string() {
-    _check(r'"foo${bar}baz"');
-  }
-
-  void test_interpolation_var_at_end_of_string() {
-    _check(r'"foo$bar"');
-  }
-
-  void test_interpolation_var_at_start_of_string() {
-    _check(r'"$foo bar"');
-  }
-
-  void test_interpolation_var_inside_string() {
-    _check(r'"foo$bar baz"');
-  }
-
-  void test_simple_string() {
-    _check('"foo"');
-  }
-
-  void _check(String originalString) {
-    var expression = _parseExpression(originalString);
-    var originalTokens =
-        _extractTokenList(expression.beginToken, expression.endToken);
-    var newString = tokensToString(expression.beginToken, expression.endToken);
-    var errorListener = AnalysisErrorListener.NULL_LISTENER;
-    var reader = new CharSequenceReader(newString);
-    var stringSource = new StringSource(newString, null);
-    var scanner = new Scanner(stringSource, reader, errorListener);
-    var startToken = scanner.tokenize();
-    var newTokens = _extractTokenList(startToken);
-    expect(newTokens, originalTokens);
-  }
-
-  List<String> _extractTokenList(Token startToken, [Token endToken]) {
-    var result = <String>[];
-    while (!startToken.isEof) {
-      if (!startToken.isSynthetic) result.add(startToken.lexeme);
-      if (identical(startToken, endToken)) break;
-      startToken = startToken.next;
-    }
-    return result;
-  }
-
-  Expression _parseExpression(String expressionString) {
-    // Note: to normalize the token string it's not sufficient to tokenize it
-    // and then pass the tokens to `tokensToString`; we also need to parse it
-    // because parsing modifies the token stream (splitting up `[]`, `>>`, and
-    // `>>>` tokens when circumstances warrant).
-    //
-    // We wrap the expression in "f() async => ...;" to ensure that the await
-    // keyword is properly parsed.
-    var sourceText = 'f() async => $expressionString;';
-    var errorListener = AnalysisErrorListener.NULL_LISTENER;
-    var reader = new CharSequenceReader(sourceText);
-    var stringSource = new StringSource(sourceText, null);
-    var scanner = new Scanner(stringSource, reader, errorListener);
-    var startToken = scanner.tokenize();
-    var parser = new Parser(stringSource, errorListener);
-    var compilationUnit = parser.parseCompilationUnit(startToken);
-    var f = compilationUnit.declarations[0] as FunctionDeclaration;
-    var body = f.functionExpression.body as ExpressionFunctionBody;
-    return body.expression;
-  }
-}
-
 /// Mixin containing test cases exercising the [ExprBuilder].  Intended to be
 /// applied to a class implementing [ResynthesizeTestStrategy], along with the
 /// mixin [ExprBuilderTestHelpers].
@@ -693,3 +575,121 @@
     return encodeLibrary(source);
   }
 }
+
+@reflectiveTest
+class TokensToStringTest {
+  void test_empty_list_no_space() {
+    // This is an interesting test case because "[]" is scanned as a single
+    // token, but the parser splits it into two.
+    _check('[]');
+  }
+
+  void test_empty_list_with_space() {
+    _check('[ ]');
+  }
+
+  void test_gt_gt_gt_in_type() {
+    // This is an interesting test case because ">>>" is scanned as a single
+    // token, but the parser splits it into three.
+    _check('A<B<C>>>[]');
+  }
+
+  void test_gt_gt_gt_in_type_split_both() {
+    _check('A<B<C> > >[]');
+  }
+
+  void test_gt_gt_gt_in_type_split_left() {
+    _check('A<B<C> >>[]');
+  }
+
+  void test_gt_gt_gt_in_type_split_right() {
+    _check('A<B<C>> >[]');
+  }
+
+  void test_gt_gt_in_type() {
+    // This is an interesting test case because ">>" is scanned as a single
+    // token, but the parser splits it into two.
+    _check('<A<B>>[]');
+  }
+
+  void test_gt_gt_in_type_split() {
+    _check('A<B> >[]');
+  }
+
+  void test_identifier() {
+    _check('foo');
+  }
+
+  void test_interpolation_expr_at_end_of_string() {
+    _check(r'"foo${bar}"');
+  }
+
+  void test_interpolation_expr_at_start_of_string() {
+    _check(r'"${foo}bar"');
+  }
+
+  void test_interpolation_expr_inside_string() {
+    _check(r'"foo${bar}baz"');
+  }
+
+  void test_interpolation_var_at_end_of_string() {
+    _check(r'"foo$bar"');
+  }
+
+  void test_interpolation_var_at_start_of_string() {
+    _check(r'"$foo bar"');
+  }
+
+  void test_interpolation_var_inside_string() {
+    _check(r'"foo$bar baz"');
+  }
+
+  void test_simple_string() {
+    _check('"foo"');
+  }
+
+  void _check(String originalString) {
+    var expression = _parseExpression(originalString);
+    var originalTokens =
+        _extractTokenList(expression.beginToken, expression.endToken);
+    var newString = tokensToString(expression.beginToken, expression.endToken);
+    var errorListener = AnalysisErrorListener.NULL_LISTENER;
+    var reader = new CharSequenceReader(newString);
+    var stringSource = new StringSource(newString, null);
+    var scanner = new Scanner(stringSource, reader, errorListener);
+    var startToken = scanner.tokenize();
+    var newTokens = _extractTokenList(startToken);
+    expect(newTokens, originalTokens);
+  }
+
+  List<String> _extractTokenList(Token startToken, [Token endToken]) {
+    var result = <String>[];
+    while (!startToken.isEof) {
+      if (!startToken.isSynthetic) result.add(startToken.lexeme);
+      if (identical(startToken, endToken)) break;
+      startToken = startToken.next;
+    }
+    return result;
+  }
+
+  Expression _parseExpression(String expressionString) {
+    // Note: to normalize the token string it's not sufficient to tokenize it
+    // and then pass the tokens to `tokensToString`; we also need to parse it
+    // because parsing modifies the token stream (splitting up `[]`, `>>`, and
+    // `>>>` tokens when circumstances warrant).
+    //
+    // We wrap the expression in "f() async => ...;" to ensure that the await
+    // keyword is properly parsed.
+    var sourceText = 'f() async => $expressionString;';
+    var errorListener = AnalysisErrorListener.NULL_LISTENER;
+    var reader = new CharSequenceReader(sourceText);
+    var stringSource = new StringSource(sourceText, null);
+    var scanner = new Scanner(stringSource, reader, errorListener);
+    var startToken = scanner.tokenize();
+    var parser = new Parser(stringSource, errorListener);
+    var compilationUnit = parser.parseCompilationUnit(startToken);
+    var f = compilationUnit.declarations[0] as FunctionDeclaration;
+    var body = f.functionExpression.body as ExpressionFunctionBody;
+    return body.expression;
+  }
+}
diff --git a/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart b/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart
index 1061dba..e5bc13c 100644
--- a/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart
+++ b/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart
@@ -2,20 +2,13 @@
 // 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 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/package_bundle_reader.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/api/general.dart';
-import 'package:analyzer/src/task/dart.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(ResynthesizerResultProviderTest);
     defineReflectiveTests(SummaryDataStoreTest);
   });
 }
@@ -31,125 +24,6 @@
 }
 
 @reflectiveTest
-class ResynthesizerResultProviderTest {
-  _SourceFactoryMock sourceFactory = new _SourceFactoryMock();
-  _InternalAnalysisContextMock context = new _InternalAnalysisContextMock();
-  UniversalCachePartition cachePartition;
-
-  Source source1 = new _SourceMock('package:p1/u1.dart', '/p1/lib/u1.dart');
-  Source source2 = new _SourceMock('package:p1/u2.dart', '/p1/lib/u2.dart');
-  Source source3 = new _SourceMock('package:p2/u1.dart', '/p2/lib/u1.dart');
-  CacheEntry entry1;
-  CacheEntry entry2;
-  CacheEntry entry3;
-
-  _PackageBundleMock bundle = new _PackageBundleMock();
-  _UnlinkedUnitMock unlinkedUnit1 = new _UnlinkedUnitMock();
-  _UnlinkedUnitMock unlinkedUnit2 = new _UnlinkedUnitMock();
-  _LinkedLibraryMock linkedLibrary = new _LinkedLibraryMock();
-
-  SummaryDataStore dataStore = new SummaryDataStore(<String>[]);
-  _TestResynthesizerResultProvider provider;
-
-  void setUp() {
-    cachePartition = new UniversalCachePartition(context);
-    entry1 = new CacheEntry(source1);
-    entry2 = new CacheEntry(source2);
-    entry3 = new CacheEntry(source3);
-    cachePartition.put(entry1);
-    cachePartition.put(entry2);
-    cachePartition.put(entry3);
-
-    sourceFactory.resolvedUriMap['package:p1/u1.dart'] = source1;
-    sourceFactory.resolvedUriMap['package:p1/u2.dart'] = source2;
-    context.sourceFactory = sourceFactory;
-
-    bundle.unlinkedUnitUris = <String>[
-      'package:p1/u1.dart',
-      'package:p1/u2.dart'
-    ];
-    bundle.unlinkedUnits = <UnlinkedUnit>[unlinkedUnit1, unlinkedUnit2];
-    bundle.linkedLibraryUris = <String>['package:p1/u1.dart'];
-    bundle.linkedLibraries = <LinkedLibrary>[linkedLibrary];
-    dataStore.addBundle('/p1.ds', bundle);
-
-    unlinkedUnit1.isPartOf = false;
-    unlinkedUnit2.isPartOf = true;
-
-    var namespace1 = _namespaceWithParts(['package:p1/u2.dart']);
-    var namespace2 = _namespaceWithParts([]);
-    unlinkedUnit1.publicNamespace = namespace1;
-    unlinkedUnit2.publicNamespace = namespace2;
-
-    provider = new _TestResynthesizerResultProvider(context, dataStore);
-    provider.sourcesWithResults.add(source1);
-    provider.sourcesWithResults.add(source2);
-  }
-
-  test_compute_CONTAINING_LIBRARIES_librarySource() {
-    bool success = provider.compute(entry1, CONTAINING_LIBRARIES);
-    expect(success, isTrue);
-    expect(entry1.getValue(CONTAINING_LIBRARIES), unorderedEquals([source1]));
-  }
-
-  test_compute_CONTAINING_LIBRARIES_partSource() {
-    bool success = provider.compute(entry2, CONTAINING_LIBRARIES);
-    expect(success, isTrue);
-    expect(entry2.getValue(CONTAINING_LIBRARIES), unorderedEquals([source1]));
-  }
-
-  test_compute_LINE_INFO_emptyLineStarts() {
-    unlinkedUnit1.lineStarts = <int>[];
-    bool success = provider.compute(entry1, LINE_INFO);
-    expect(success, isFalse);
-  }
-
-  test_compute_LINE_INFO_hasLineStarts() {
-    unlinkedUnit1.lineStarts = <int>[10, 20, 30];
-    bool success = provider.compute(entry1, LINE_INFO);
-    expect(success, isTrue);
-    expect(entry1.getValue(LINE_INFO).lineStarts, <int>[10, 20, 30]);
-  }
-
-  test_compute_MODIFICATION_TIME_hasResult() {
-    bool success = provider.compute(entry1, MODIFICATION_TIME);
-    expect(success, isTrue);
-    expect(entry1.getValue(MODIFICATION_TIME), 0);
-  }
-
-  test_compute_MODIFICATION_TIME_noResult() {
-    bool success = provider.compute(entry3, MODIFICATION_TIME);
-    expect(success, isFalse);
-    expect(entry3.getState(MODIFICATION_TIME), CacheState.INVALID);
-  }
-
-  test_compute_SOURCE_KIND_librarySource() {
-    bool success = provider.compute(entry1, SOURCE_KIND);
-    expect(success, isTrue);
-    expect(entry1.getValue(SOURCE_KIND), SourceKind.LIBRARY);
-  }
-
-  test_compute_SOURCE_KIND_librarySource_isPartOf() {
-    unlinkedUnit1.isPartOf = true;
-    bool success = provider.compute(entry1, SOURCE_KIND);
-    expect(success, isTrue);
-    expect(entry1.getValue(SOURCE_KIND), SourceKind.PART);
-  }
-
-  test_compute_SOURCE_KIND_noResults() {
-    bool success = provider.compute(entry3, SOURCE_KIND);
-    expect(success, isFalse);
-    expect(entry3.getState(SOURCE_KIND), CacheState.INVALID);
-  }
-
-  test_compute_SOURCE_KIND_partSource() {
-    bool success = provider.compute(entry2, SOURCE_KIND);
-    expect(success, isTrue);
-    expect(entry2.getValue(SOURCE_KIND), SourceKind.PART);
-  }
-}
-
-@reflectiveTest
 class SummaryDataStoreTest {
   SummaryDataStore dataStore =
       new SummaryDataStore(<String>[], disallowOverlappingSummaries: true);
@@ -289,16 +163,6 @@
   }
 }
 
-class _InternalAnalysisContextMock implements InternalAnalysisContext {
-  @override
-  SourceFactory sourceFactory;
-
-  @override
-  noSuchMethod(Invocation invocation) {
-    throw new StateError('Unexpected invocation of ${invocation.memberName}');
-  }
-}
-
 class _LinkedLibraryMock implements LinkedLibrary {
   @override
   noSuchMethod(Invocation invocation) {
@@ -328,54 +192,6 @@
   }
 }
 
-class _SourceFactoryMock implements SourceFactory {
-  Map<String, Source> resolvedUriMap = <String, Source>{};
-
-  @override
-  noSuchMethod(Invocation invocation) {
-    throw new StateError('Unexpected invocation of ${invocation.memberName}');
-  }
-
-  @override
-  Source resolveUri(Source containingSource, String containedUri) {
-    return resolvedUriMap[containedUri];
-  }
-}
-
-class _SourceMock implements Source {
-  @override
-  final Uri uri;
-
-  @override
-  final String fullName;
-
-  _SourceMock(String uriStr, this.fullName) : uri = Uri.parse(uriStr);
-
-  @override
-  Source get librarySource => null;
-
-  @override
-  Source get source => this;
-
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
-  @override
-  String toString() => '$uri ($fullName)';
-}
-
-class _TestResynthesizerResultProvider extends ResynthesizerResultProvider {
-  final Set<Source> sourcesWithResults = new Set<Source>();
-
-  _TestResynthesizerResultProvider(
-      InternalAnalysisContext context, SummaryDataStore dataStore)
-      : super(context, null, dataStore);
-
-  @override
-  bool hasResultsForSource(Source source) {
-    return sourcesWithResults.contains(source);
-  }
-}
-
 class _UnlinkedPublicNamespaceMock implements UnlinkedPublicNamespace {
   @override
   List<String> parts;
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index efbdbf9..32edf88 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -3,9 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/src/summary/summary_sdk.dart';
 import 'package:analyzer/src/summary2/link.dart';
-import 'package:analyzer/src/summary2/linked_bundle_context.dart';
-import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -23,10 +27,94 @@
 class ResynthesizeAst2Test extends ResynthesizeTestStrategyTwoPhase
     with ResynthesizeTestCases {
   @override
+  bool get isAstBasedSummary => true;
+
+  @override
   Future<LibraryElementImpl> checkLibrary(String text,
       {bool allowErrors = false, bool dumpSummaries = false}) async {
-    var source = addTestSource(text);
+    var dartCoreSource = sourceFactory.forUri('dart:core');
+    var dartCoreCode = getFile(dartCoreSource.fullName).readAsStringSync();
+    dartCoreCode = r'''
+library dart.core;
 
+abstract class Comparable<T> {
+  int compareTo(T other);
+}
+
+class Iterable<T> {}
+
+class Iterator<T> {}
+
+class List<T> {}
+
+class Map<K, V> {}
+
+abstract class Null {}
+
+class Object {
+  const Object();
+}
+
+abstract class String {
+  int get length;
+  String operator +(String other);
+}
+
+class Set<T> {}
+
+abstract class Symbol {}
+
+abstract class Type {}
+
+abstract class bool {}
+
+abstract class double extends num {}
+
+abstract class int extends num {
+  bool get isEven => false;
+  bool get isNegative;
+  
+  int operator &(int other);
+  int operator -();
+  int operator <<(int shiftAmount);
+  int operator >>(int shiftAmount);
+  int operator ^(int other);
+  int operator |(int other);
+  int operator ~();
+}
+
+abstract class num implements Comparable<num> {
+  bool operator <(num other);
+  bool operator <=(num other);
+  bool operator ==(Object other);
+  bool operator >(num other);
+  bool operator >=(num other);
+  
+  double operator /(num other);
+  double toDouble();
+  
+  int operator <<(int other);
+  int operator >>(int other);
+  int operator ^(int other);
+  int operator |(int other);
+  int operator ~();
+  int operator ~/(num other);
+  
+  int round();
+  int toInt();
+  num abs();
+  
+  num operator %(num other);
+  num operator *(num other);
+  num operator +(num other);
+  num operator -();
+  num operator -(num other);
+}
+''';
+
+    var dartCoreResult = _link(dartCoreSource, dartCoreCode);
+
+    var source = addTestSource(text);
     var unit = parseText(text, experimentStatus: experimentStatus);
 
     // TODO(scheglov) add other libraries
@@ -34,66 +122,39 @@
       source: {source: unit},
     };
 
+    for (var otherLibrarySource in otherLibrarySources) {
+      var text = getFile(otherLibrarySource.fullName).readAsStringSync();
+      var unit = parseText(text, experimentStatus: experimentStatus);
+      libraryUnitMap[otherLibrarySource] = {otherLibrarySource: unit};
+    }
+
+    var linkResult = link(
+      AnalysisOptionsImpl(),
+      sourceFactory,
+      [dartCoreResult.bundle],
+      libraryUnitMap,
+    );
+
+    var analysisContext = _FakeAnalysisContext(sourceFactory);
+
     var rootReference = Reference.root();
-    var linkResult = link(rootReference, libraryUnitMap);
+    rootReference.getChild('dart:core').getChild('dynamic').element =
+        DynamicElementImpl.instance;
 
-    var libraryLinkResult = linkResult.libraries[source];
-    var defaultUnitResult = libraryLinkResult.units[source];
-
-    var linkedBundleContext = LinkedBundleContext(linkResult.references);
-    var linkedUnitContext = LinkedUnitContext(
-      linkedBundleContext,
-      defaultUnitResult.tokens,
+    var elementFactory = LinkedElementFactory(
+      analysisContext,
+      null,
+      rootReference,
     );
+    elementFactory.addBundle(dartCoreResult.bundle);
+    elementFactory.addBundle(linkResult.bundle);
 
-    // TODO(scheglov) use actual names
-    // TODO(scheglov) support parts
-    var libraryElement = LibraryElementImpl(null, null, '', -1, 0);
-    var unitElement = CompilationUnitElementImpl.forLinkedNode(
-      libraryElement,
-      linkedUnitContext,
-      rootReference.getChild('${libraryLinkResult.source.uri}'),
-      defaultUnitResult.node,
-    );
-    libraryElement.definingCompilationUnit = unitElement;
+    var dartCore = elementFactory.libraryOfUri('dart:core');
+    var typeProvider = SummaryTypeProvider()..initializeCore(dartCore);
+    analysisContext.typeProvider = typeProvider;
+    analysisContext.typeSystem = Dart2TypeSystem(typeProvider);
 
-    return libraryElement;
-  }
-
-  @override
-  @failingTest
-  test_class_alias() async {
-    await super.test_class_alias();
-  }
-
-  @override
-  @failingTest
-  test_class_alias_abstract() async {
-    await super.test_class_alias_abstract();
-  }
-
-  @override
-  @failingTest
-  test_class_alias_documented() async {
-    await super.test_class_alias_documented();
-  }
-
-  @override
-  @failingTest
-  test_class_alias_documented_tripleSlash() async {
-    await super.test_class_alias_documented_tripleSlash();
-  }
-
-  @override
-  @failingTest
-  test_class_alias_documented_withLeadingNonDocumentation() async {
-    await super.test_class_alias_documented_withLeadingNonDocumentation();
-  }
-
-  @override
-  @failingTest
-  test_class_alias_generic() async {
-    await super.test_class_alias_generic();
+    return elementFactory.libraryOfUri('${source.uri}');
   }
 
   @override
@@ -118,36 +179,6 @@
 
   @override
   @failingTest
-  test_class_alias_with_mixin_members() async {
-    await super.test_class_alias_with_mixin_members();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_explicit_type_params() async {
-    await super.test_class_constructor_explicit_type_params();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_dynamic_dynamic() async {
-    await super.test_class_constructor_field_formal_dynamic_dynamic();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_dynamic_typed() async {
-    await super.test_class_constructor_field_formal_dynamic_typed();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_dynamic_untyped() async {
-    await super.test_class_constructor_field_formal_dynamic_untyped();
-  }
-
-  @override
-  @failingTest
   test_class_constructor_field_formal_functionTyped_noReturnType() async {
     await super
         .test_class_constructor_field_formal_functionTyped_noReturnType();
@@ -168,48 +199,6 @@
 
   @override
   @failingTest
-  test_class_constructor_field_formal_no_matching_field() async {
-    await super.test_class_constructor_field_formal_no_matching_field();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_typed_dynamic() async {
-    await super.test_class_constructor_field_formal_typed_dynamic();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_typed_typed() async {
-    await super.test_class_constructor_field_formal_typed_typed();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_typed_untyped() async {
-    await super.test_class_constructor_field_formal_typed_untyped();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_untyped_dynamic() async {
-    await super.test_class_constructor_field_formal_untyped_dynamic();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_untyped_typed() async {
-    await super.test_class_constructor_field_formal_untyped_typed();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_untyped_untyped() async {
-    await super.test_class_constructor_field_formal_untyped_untyped();
-  }
-
-  @override
-  @failingTest
   test_class_constructor_fieldFormal_named_noDefault() async {
     await super.test_class_constructor_fieldFormal_named_noDefault();
   }
@@ -234,258 +223,6 @@
 
   @override
   @failingTest
-  test_class_constructor_implicit_type_params() async {
-    await super.test_class_constructor_implicit_type_params();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_params() async {
-    await super.test_class_constructor_params();
-  }
-
-  @override
-  @failingTest
-  test_class_documented() async {
-    await super.test_class_documented();
-  }
-
-  @override
-  @failingTest
-  test_class_documented_mix() async {
-    await super.test_class_documented_mix();
-  }
-
-  @override
-  @failingTest
-  test_class_documented_tripleSlash() async {
-    await super.test_class_documented_tripleSlash();
-  }
-
-  @override
-  @failingTest
-  test_class_documented_with_references() async {
-    await super.test_class_documented_with_references();
-  }
-
-  @override
-  @failingTest
-  test_class_documented_with_windows_line_endings() async {
-    await super.test_class_documented_with_windows_line_endings();
-  }
-
-  @override
-  @failingTest
-  test_class_documented_withLeadingNotDocumentation() async {
-    await super.test_class_documented_withLeadingNotDocumentation();
-  }
-
-  @override
-  @failingTest
-  test_class_documented_withMetadata() async {
-    await super.test_class_documented_withMetadata();
-  }
-
-  @override
-  @failingTest
-  test_class_field_const() async {
-    await super.test_class_field_const();
-  }
-
-  @override
-  @failingTest
-  test_class_field_implicit_type() async {
-    await super.test_class_field_implicit_type();
-  }
-
-  @override
-  @failingTest
-  test_class_field_static() async {
-    await super.test_class_field_static();
-  }
-
-  @override
-  @failingTest
-  test_class_fields() async {
-    await super.test_class_fields();
-  }
-
-  @override
-  @failingTest
-  test_class_getter_abstract() async {
-    await super.test_class_getter_abstract();
-  }
-
-  @override
-  @failingTest
-  test_class_getter_external() async {
-    await super.test_class_getter_external();
-  }
-
-  @override
-  @failingTest
-  test_class_getter_implicit_return_type() async {
-    await super.test_class_getter_implicit_return_type();
-  }
-
-  @override
-  @failingTest
-  test_class_getter_static() async {
-    await super.test_class_getter_static();
-  }
-
-  @override
-  @failingTest
-  test_class_getters() async {
-    await super.test_class_getters();
-  }
-
-  @override
-  @failingTest
-  test_class_implicitField_getterFirst() async {
-    await super.test_class_implicitField_getterFirst();
-  }
-
-  @override
-  @failingTest
-  test_class_implicitField_setterFirst() async {
-    await super.test_class_implicitField_setterFirst();
-  }
-
-  @override
-  @failingTest
-  test_class_interfaces_unresolved() async {
-    await super.test_class_interfaces_unresolved();
-  }
-
-  @override
-  @failingTest
-  test_class_method_abstract() async {
-    await super.test_class_method_abstract();
-  }
-
-  @override
-  @failingTest
-  test_class_method_external() async {
-    await super.test_class_method_external();
-  }
-
-  @override
-  @failingTest
-  test_class_method_params() async {
-    await super.test_class_method_params();
-  }
-
-  @override
-  @failingTest
-  test_class_method_static() async {
-    await super.test_class_method_static();
-  }
-
-  @override
-  @failingTest
-  test_class_methods() async {
-    await super.test_class_methods();
-  }
-
-  @override
-  @failingTest
-  test_class_mixins_generic() async {
-    await super.test_class_mixins_generic();
-  }
-
-  @override
-  @failingTest
-  test_class_mixins_unresolved() async {
-    await super.test_class_mixins_unresolved();
-  }
-
-  @override
-  @failingTest
-  test_class_setter_abstract() async {
-    await super.test_class_setter_abstract();
-  }
-
-  @override
-  @failingTest
-  test_class_setter_external() async {
-    await super.test_class_setter_external();
-  }
-
-  @override
-  @failingTest
-  test_class_setter_implicit_param_type() async {
-    await super.test_class_setter_implicit_param_type();
-  }
-
-  @override
-  @failingTest
-  test_class_setter_implicit_return_type() async {
-    await super.test_class_setter_implicit_return_type();
-  }
-
-  @override
-  @failingTest
-  test_class_setter_invalid_named_parameter() async {
-    await super.test_class_setter_invalid_named_parameter();
-  }
-
-  @override
-  @failingTest
-  test_class_setter_invalid_no_parameter() async {
-    await super.test_class_setter_invalid_no_parameter();
-  }
-
-  @override
-  @failingTest
-  test_class_setter_invalid_optional_parameter() async {
-    await super.test_class_setter_invalid_optional_parameter();
-  }
-
-  @override
-  @failingTest
-  test_class_setter_invalid_too_many_parameters() async {
-    await super.test_class_setter_invalid_too_many_parameters();
-  }
-
-  @override
-  @failingTest
-  test_class_setter_static() async {
-    await super.test_class_setter_static();
-  }
-
-  @override
-  @failingTest
-  test_class_setters() async {
-    await super.test_class_setters();
-  }
-
-  @override
-  @failingTest
-  test_class_supertype_typeArguments() async {
-    await super.test_class_supertype_typeArguments();
-  }
-
-  @override
-  @failingTest
-  test_class_supertype_unresolved() async {
-    await super.test_class_supertype_unresolved();
-  }
-
-  @override
-  @failingTest
-  test_class_type_parameters() async {
-    await super.test_class_type_parameters();
-  }
-
-  @override
-  @failingTest
-  test_class_type_parameters_bound() async {
-    await super.test_class_type_parameters_bound();
-  }
-
-  @override
-  @failingTest
   test_class_type_parameters_f_bound_complex() async {
     await super.test_class_type_parameters_f_bound_complex();
   }
@@ -498,12 +235,6 @@
 
   @override
   @failingTest
-  test_closure_executable_with_return_type_from_closure() async {
-    await super.test_closure_executable_with_return_type_from_closure();
-  }
-
-  @override
-  @failingTest
   test_closure_generic() async {
     await super.test_closure_generic();
   }
@@ -612,36 +343,6 @@
 
   @override
   @failingTest
-  test_const_invalid_intLiteral() async {
-    await super.test_const_invalid_intLiteral();
-  }
-
-  @override
-  @failingTest
-  test_const_invalid_topLevel() async {
-    await super.test_const_invalid_topLevel();
-  }
-
-  @override
-  @failingTest
-  test_const_invalid_typeMismatch() async {
-    await super.test_const_invalid_typeMismatch();
-  }
-
-  @override
-  @failingTest
-  test_const_invokeConstructor_generic_named() async {
-    await super.test_const_invokeConstructor_generic_named();
-  }
-
-  @override
-  @failingTest
-  test_const_invokeConstructor_generic_named_imported() async {
-    await super.test_const_invokeConstructor_generic_named_imported();
-  }
-
-  @override
-  @failingTest
   test_const_invokeConstructor_generic_named_imported_withPrefix() async {
     await super
         .test_const_invokeConstructor_generic_named_imported_withPrefix();
@@ -649,24 +350,6 @@
 
   @override
   @failingTest
-  test_const_invokeConstructor_generic_noTypeArguments() async {
-    await super.test_const_invokeConstructor_generic_noTypeArguments();
-  }
-
-  @override
-  @failingTest
-  test_const_invokeConstructor_generic_unnamed() async {
-    await super.test_const_invokeConstructor_generic_unnamed();
-  }
-
-  @override
-  @failingTest
-  test_const_invokeConstructor_generic_unnamed_imported() async {
-    await super.test_const_invokeConstructor_generic_unnamed_imported();
-  }
-
-  @override
-  @failingTest
   test_const_invokeConstructor_generic_unnamed_imported_withPrefix() async {
     await super
         .test_const_invokeConstructor_generic_unnamed_imported_withPrefix();
@@ -680,12 +363,6 @@
 
   @override
   @failingTest
-  test_const_invokeConstructor_named_imported() async {
-    await super.test_const_invokeConstructor_named_imported();
-  }
-
-  @override
-  @failingTest
   test_const_invokeConstructor_named_imported_withPrefix() async {
     await super.test_const_invokeConstructor_named_imported_withPrefix();
   }
@@ -698,12 +375,6 @@
 
   @override
   @failingTest
-  test_const_invokeConstructor_named_unresolved2() async {
-    await super.test_const_invokeConstructor_named_unresolved2();
-  }
-
-  @override
-  @failingTest
   test_const_invokeConstructor_named_unresolved3() async {
     await super.test_const_invokeConstructor_named_unresolved3();
   }
@@ -716,114 +387,36 @@
 
   @override
   @failingTest
-  test_const_invokeConstructor_named_unresolved5() async {
-    await super.test_const_invokeConstructor_named_unresolved5();
-  }
-
-  @override
-  @failingTest
   test_const_invokeConstructor_named_unresolved6() async {
     await super.test_const_invokeConstructor_named_unresolved6();
   }
 
   @override
   @failingTest
-  test_const_invokeConstructor_unnamed() async {
-    await super.test_const_invokeConstructor_unnamed();
-  }
-
-  @override
-  @failingTest
-  test_const_invokeConstructor_unnamed_imported() async {
-    await super.test_const_invokeConstructor_unnamed_imported();
-  }
-
-  @override
-  @failingTest
   test_const_invokeConstructor_unnamed_imported_withPrefix() async {
     await super.test_const_invokeConstructor_unnamed_imported_withPrefix();
   }
 
   @override
   @failingTest
-  test_const_invokeConstructor_unnamed_unresolved() async {
-    await super.test_const_invokeConstructor_unnamed_unresolved();
-  }
-
-  @override
-  @failingTest
   test_const_invokeConstructor_unnamed_unresolved2() async {
     await super.test_const_invokeConstructor_unnamed_unresolved2();
   }
 
   @override
   @failingTest
-  test_const_invokeConstructor_unnamed_unresolved3() async {
-    await super.test_const_invokeConstructor_unnamed_unresolved3();
-  }
-
-  @override
-  @failingTest
-  test_const_length_ofClassConstField() async {
-    await super.test_const_length_ofClassConstField();
-  }
-
-  @override
-  @failingTest
-  test_const_length_ofClassConstField_imported() async {
-    await super.test_const_length_ofClassConstField_imported();
-  }
-
-  @override
-  @failingTest
   test_const_length_ofClassConstField_imported_withPrefix() async {
     await super.test_const_length_ofClassConstField_imported_withPrefix();
   }
 
   @override
   @failingTest
-  test_const_length_ofStringLiteral() async {
-    await super.test_const_length_ofStringLiteral();
-  }
-
-  @override
-  @failingTest
-  test_const_length_ofTopLevelVariable() async {
-    await super.test_const_length_ofTopLevelVariable();
-  }
-
-  @override
-  @failingTest
-  test_const_length_ofTopLevelVariable_imported() async {
-    await super.test_const_length_ofTopLevelVariable_imported();
-  }
-
-  @override
-  @failingTest
   test_const_length_ofTopLevelVariable_imported_withPrefix() async {
     await super.test_const_length_ofTopLevelVariable_imported_withPrefix();
   }
 
   @override
   @failingTest
-  test_const_length_staticMethod() async {
-    await super.test_const_length_staticMethod();
-  }
-
-  @override
-  @failingTest
-  test_const_list_inferredType() async {
-    await super.test_const_list_inferredType();
-  }
-
-  @override
-  @failingTest
-  test_const_map_inferredType() async {
-    await super.test_const_map_inferredType();
-  }
-
-  @override
-  @failingTest
   test_const_parameterDefaultValue_initializingFormal_functionTyped() async {
     await super
         .test_const_parameterDefaultValue_initializingFormal_functionTyped();
@@ -844,36 +437,12 @@
 
   @override
   @failingTest
-  test_const_parameterDefaultValue_normal() async {
-    await super.test_const_parameterDefaultValue_normal();
-  }
-
-  @override
-  @failingTest
-  test_const_reference_staticField() async {
-    await super.test_const_reference_staticField();
-  }
-
-  @override
-  @failingTest
-  test_const_reference_staticField_imported() async {
-    await super.test_const_reference_staticField_imported();
-  }
-
-  @override
-  @failingTest
   test_const_reference_staticField_imported_withPrefix() async {
     await super.test_const_reference_staticField_imported_withPrefix();
   }
 
   @override
   @failingTest
-  test_const_reference_staticMethod() async {
-    await super.test_const_reference_staticMethod();
-  }
-
-  @override
-  @failingTest
   test_const_reference_staticMethod_imported() async {
     await super.test_const_reference_staticMethod_imported();
   }
@@ -886,36 +455,18 @@
 
   @override
   @failingTest
-  test_const_reference_topLevelFunction() async {
-    await super.test_const_reference_topLevelFunction();
-  }
-
-  @override
-  @failingTest
   test_const_reference_topLevelFunction_generic() async {
     await super.test_const_reference_topLevelFunction_generic();
   }
 
   @override
   @failingTest
-  test_const_reference_topLevelFunction_imported() async {
-    await super.test_const_reference_topLevelFunction_imported();
-  }
-
-  @override
-  @failingTest
   test_const_reference_topLevelFunction_imported_withPrefix() async {
     await super.test_const_reference_topLevelFunction_imported_withPrefix();
   }
 
   @override
   @failingTest
-  test_const_reference_topLevelVariable() async {
-    await super.test_const_reference_topLevelVariable();
-  }
-
-  @override
-  @failingTest
   test_const_reference_topLevelVariable_imported() async {
     await super.test_const_reference_topLevelVariable_imported();
   }
@@ -928,12 +479,6 @@
 
   @override
   @failingTest
-  test_const_reference_type() async {
-    await super.test_const_reference_type();
-  }
-
-  @override
-  @failingTest
   test_const_reference_type_functionType() async {
     await super.test_const_reference_type_functionType();
   }
@@ -958,96 +503,12 @@
 
   @override
   @failingTest
-  test_const_reference_unresolved_prefix0() async {
-    await super.test_const_reference_unresolved_prefix0();
-  }
-
-  @override
-  @failingTest
-  test_const_reference_unresolved_prefix1() async {
-    await super.test_const_reference_unresolved_prefix1();
-  }
-
-  @override
-  @failingTest
   test_const_reference_unresolved_prefix2() async {
     await super.test_const_reference_unresolved_prefix2();
   }
 
   @override
   @failingTest
-  test_const_topLevel_binary() async {
-    await super.test_const_topLevel_binary();
-  }
-
-  @override
-  @failingTest
-  test_const_topLevel_conditional() async {
-    await super.test_const_topLevel_conditional();
-  }
-
-  @override
-  @failingTest
-  test_const_topLevel_identical() async {
-    await super.test_const_topLevel_identical();
-  }
-
-  @override
-  @failingTest
-  test_const_topLevel_ifNull() async {
-    await super.test_const_topLevel_ifNull();
-  }
-
-  @override
-  @failingTest
-  test_const_topLevel_literal() async {
-    await super.test_const_topLevel_literal();
-  }
-
-  @override
-  @failingTest
-  test_const_topLevel_parenthesis() async {
-    await super.test_const_topLevel_parenthesis();
-  }
-
-  @override
-  @failingTest
-  test_const_topLevel_prefix() async {
-    await super.test_const_topLevel_prefix();
-  }
-
-  @override
-  @failingTest
-  test_const_topLevel_super() async {
-    await super.test_const_topLevel_super();
-  }
-
-  @override
-  @failingTest
-  test_const_topLevel_this() async {
-    await super.test_const_topLevel_this();
-  }
-
-  @override
-  @failingTest
-  test_const_topLevel_throw() async {
-    await super.test_const_topLevel_throw();
-  }
-
-  @override
-  @failingTest
-  test_const_topLevel_typedList() async {
-    await super.test_const_topLevel_typedList();
-  }
-
-  @override
-  @failingTest
-  test_const_topLevel_typedList_imported() async {
-    await super.test_const_topLevel_typedList_imported();
-  }
-
-  @override
-  @failingTest
   test_const_topLevel_typedList_importedWithPrefix() async {
     await super.test_const_topLevel_typedList_importedWithPrefix();
   }
@@ -1060,36 +521,6 @@
 
   @override
   @failingTest
-  test_const_topLevel_typedMap() async {
-    await super.test_const_topLevel_typedMap();
-  }
-
-  @override
-  @failingTest
-  test_const_topLevel_untypedList() async {
-    await super.test_const_topLevel_untypedList();
-  }
-
-  @override
-  @failingTest
-  test_const_topLevel_untypedMap() async {
-    await super.test_const_topLevel_untypedMap();
-  }
-
-  @override
-  @failingTest
-  test_constExpr_pushReference_enum_field() async {
-    await super.test_constExpr_pushReference_enum_field();
-  }
-
-  @override
-  @failingTest
-  test_constExpr_pushReference_enum_method() async {
-    await super.test_constExpr_pushReference_enum_method();
-  }
-
-  @override
-  @failingTest
   test_constExpr_pushReference_field_simpleIdentifier() async {
     await super.test_constExpr_pushReference_field_simpleIdentifier();
   }
@@ -1102,12 +533,6 @@
 
   @override
   @failingTest
-  test_constructor_documented() async {
-    await super.test_constructor_documented();
-  }
-
-  @override
-  @failingTest
   test_constructor_initializers_assertInvocation() async {
     await super.test_constructor_initializers_assertInvocation();
   }
@@ -1217,19 +642,6 @@
 
   @override
   @failingTest
-  test_constructor_redirected_factory_named_unresolved_class() async {
-    await super.test_constructor_redirected_factory_named_unresolved_class();
-  }
-
-  @override
-  @failingTest
-  test_constructor_redirected_factory_named_unresolved_constructor() async {
-    await super
-        .test_constructor_redirected_factory_named_unresolved_constructor();
-  }
-
-  @override
-  @failingTest
   test_constructor_redirected_factory_unnamed() async {
     await super.test_constructor_redirected_factory_unnamed();
   }
@@ -1266,12 +678,6 @@
 
   @override
   @failingTest
-  test_constructor_redirected_factory_unnamed_unresolved() async {
-    await super.test_constructor_redirected_factory_unnamed_unresolved();
-  }
-
-  @override
-  @failingTest
   test_constructor_redirected_thisInvocation_named() async {
     await super.test_constructor_redirected_thisInvocation_named();
   }
@@ -1302,12 +708,6 @@
 
   @override
   @failingTest
-  test_constructor_withCycles_nonConst() async {
-    await super.test_constructor_withCycles_nonConst();
-  }
-
-  @override
-  @failingTest
   test_defaultValue_genericFunction() async {
     await super.test_defaultValue_genericFunction();
   }
@@ -1350,36 +750,6 @@
 
   @override
   @failingTest
-  test_enum_documented() async {
-    await super.test_enum_documented();
-  }
-
-  @override
-  @failingTest
-  test_enum_value_documented() async {
-    await super.test_enum_value_documented();
-  }
-
-  @override
-  @failingTest
-  test_enum_values() async {
-    await super.test_enum_values();
-  }
-
-  @override
-  @failingTest
-  test_enums() async {
-    await super.test_enums();
-  }
-
-  @override
-  @failingTest
-  test_error_extendsEnum() async {
-    await super.test_error_extendsEnum();
-  }
-
-  @override
-  @failingTest
   test_executable_parameter_type_typedef() async {
     await super.test_executable_parameter_type_typedef();
   }
@@ -1494,36 +864,18 @@
 
   @override
   @failingTest
-  test_expr_invalid_typeParameter_asPrefix() async {
-    await super.test_expr_invalid_typeParameter_asPrefix();
-  }
-
-  @override
-  @failingTest
   test_field_covariant() async {
     await super.test_field_covariant();
   }
 
   @override
   @failingTest
-  test_field_documented() async {
-    await super.test_field_documented();
-  }
-
-  @override
-  @failingTest
   test_field_formal_param_inferred_type_implicit() async {
     await super.test_field_formal_param_inferred_type_implicit();
   }
 
   @override
   @failingTest
-  test_field_inferred_type_nonStatic_explicit_initialized() async {
-    await super.test_field_inferred_type_nonStatic_explicit_initialized();
-  }
-
-  @override
-  @failingTest
   test_field_inferred_type_nonStatic_implicit_initialized() async {
     await super.test_field_inferred_type_nonStatic_implicit_initialized();
   }
@@ -1578,12 +930,6 @@
 
   @override
   @failingTest
-  test_field_typed() async {
-    await super.test_field_typed();
-  }
-
-  @override
-  @failingTest
   test_field_untyped() async {
     await super.test_field_untyped();
   }
@@ -1602,18 +948,6 @@
 
   @override
   @failingTest
-  test_function_documented() async {
-    await super.test_function_documented();
-  }
-
-  @override
-  @failingTest
-  test_function_entry_point() async {
-    await super.test_function_entry_point();
-  }
-
-  @override
-  @failingTest
   test_function_entry_point_in_export() async {
     await super.test_function_entry_point_in_export();
   }
@@ -1632,36 +966,6 @@
 
   @override
   @failingTest
-  test_function_external() async {
-    await super.test_function_external();
-  }
-
-  @override
-  @failingTest
-  test_function_parameter_final() async {
-    await super.test_function_parameter_final();
-  }
-
-  @override
-  @failingTest
-  test_function_parameter_kind_named() async {
-    await super.test_function_parameter_kind_named();
-  }
-
-  @override
-  @failingTest
-  test_function_parameter_kind_positional() async {
-    await super.test_function_parameter_kind_positional();
-  }
-
-  @override
-  @failingTest
-  test_function_parameter_kind_required() async {
-    await super.test_function_parameter_kind_required();
-  }
-
-  @override
-  @failingTest
   test_function_parameter_parameters() async {
     await super.test_function_parameter_parameters();
   }
@@ -1680,42 +984,6 @@
 
   @override
   @failingTest
-  test_function_parameter_type() async {
-    await super.test_function_parameter_type();
-  }
-
-  @override
-  @failingTest
-  test_function_parameters() async {
-    await super.test_function_parameters();
-  }
-
-  @override
-  @failingTest
-  test_function_return_type() async {
-    await super.test_function_return_type();
-  }
-
-  @override
-  @failingTest
-  test_function_return_type_implicit() async {
-    await super.test_function_return_type_implicit();
-  }
-
-  @override
-  @failingTest
-  test_function_return_type_void() async {
-    await super.test_function_return_type_void();
-  }
-
-  @override
-  @failingTest
-  test_function_type_parameter() async {
-    await super.test_function_type_parameter();
-  }
-
-  @override
-  @failingTest
   test_function_type_parameter_with_function_typed_parameter() async {
     await super.test_function_type_parameter_with_function_typed_parameter();
   }
@@ -1728,12 +996,6 @@
 
   @override
   @failingTest
-  test_functions() async {
-    await super.test_functions();
-  }
-
-  @override
-  @failingTest
   test_futureOr() async {
     await super.test_futureOr();
   }
@@ -1752,12 +1014,6 @@
 
   @override
   @failingTest
-  test_generic_gClass_gMethodStatic() async {
-    await super.test_generic_gClass_gMethodStatic();
-  }
-
-  @override
-  @failingTest
   test_genericFunction_asFunctionReturnType() async {
     await super.test_genericFunction_asFunctionReturnType();
   }
@@ -1794,48 +1050,12 @@
 
   @override
   @failingTest
-  test_getter_documented() async {
-    await super.test_getter_documented();
-  }
-
-  @override
-  @failingTest
-  test_getter_external() async {
-    await super.test_getter_external();
-  }
-
-  @override
-  @failingTest
   test_getter_inferred_type_nonStatic_implicit_return() async {
     await super.test_getter_inferred_type_nonStatic_implicit_return();
   }
 
   @override
   @failingTest
-  test_getters() async {
-    await super.test_getters();
-  }
-
-  @override
-  @failingTest
-  test_implicitTopLevelVariable_getterFirst() async {
-    await super.test_implicitTopLevelVariable_getterFirst();
-  }
-
-  @override
-  @failingTest
-  test_implicitTopLevelVariable_setterFirst() async {
-    await super.test_implicitTopLevelVariable_setterFirst();
-  }
-
-  @override
-  @failingTest
-  test_import_configurations_useDefault() async {
-    await super.test_import_configurations_useDefault();
-  }
-
-  @override
-  @failingTest
   test_import_configurations_useFirst() async {
     await super.test_import_configurations_useFirst();
   }
@@ -1885,7 +1105,9 @@
   @override
   @failingTest
   test_import_short_absolute() async {
-    await super.test_import_short_absolute();
+    // TODO(scheglov) fails on Windows
+    fail('test_import_short_absolute on Windows');
+//    await super.test_import_short_absolute();
   }
 
   @override
@@ -1896,30 +1118,12 @@
 
   @override
   @failingTest
-  test_imports() async {
-    await super.test_imports();
-  }
-
-  @override
-  @failingTest
   test_infer_generic_typedef_simple() async {
     await super.test_infer_generic_typedef_simple();
   }
 
   @override
   @failingTest
-  test_infer_instanceCreation_fromArguments() async {
-    await super.test_infer_instanceCreation_fromArguments();
-  }
-
-  @override
-  @failingTest
-  test_infer_property_set() async {
-    await super.test_infer_property_set();
-  }
-
-  @override
-  @failingTest
   test_inference_issue_32394() async {
     await super.test_inference_issue_32394();
   }
@@ -1932,49 +1136,6 @@
 
   @override
   @failingTest
-  test_inferred_function_type_for_variable_in_generic_function() async {
-    await super.test_inferred_function_type_for_variable_in_generic_function();
-  }
-
-  @override
-  @failingTest
-  test_inferred_function_type_in_generic_class_constructor() async {
-    await super.test_inferred_function_type_in_generic_class_constructor();
-  }
-
-  @override
-  @failingTest
-  test_inferred_function_type_in_generic_class_getter() async {
-    await super.test_inferred_function_type_in_generic_class_getter();
-  }
-
-  @override
-  @failingTest
-  test_inferred_function_type_in_generic_class_in_generic_method() async {
-    await super
-        .test_inferred_function_type_in_generic_class_in_generic_method();
-  }
-
-  @override
-  @failingTest
-  test_inferred_function_type_in_generic_class_setter() async {
-    await super.test_inferred_function_type_in_generic_class_setter();
-  }
-
-  @override
-  @failingTest
-  test_inferred_function_type_in_generic_closure() async {
-    await super.test_inferred_function_type_in_generic_closure();
-  }
-
-  @override
-  @failingTest
-  test_inferred_generic_function_type_in_generic_closure() async {
-    await super.test_inferred_generic_function_type_in_generic_closure();
-  }
-
-  @override
-  @failingTest
   test_inferred_type_is_typedef() async {
     await super.test_inferred_type_is_typedef();
   }
@@ -2059,12 +1220,6 @@
 
   @override
   @failingTest
-  test_inheritance_errors() async {
-    await super.test_inheritance_errors();
-  }
-
-  @override
-  @failingTest
   test_initializer_executable_with_return_type_from_closure() async {
     await super.test_initializer_executable_with_return_type_from_closure();
   }
@@ -2106,13 +1261,6 @@
 
   @override
   @failingTest
-  test_initializer_executable_with_return_type_from_closure_local() async {
-    await super
-        .test_initializer_executable_with_return_type_from_closure_local();
-  }
-
-  @override
-  @failingTest
   test_instantiateToBounds_boundRefersToEarlierTypeArgument() async {
     await super.test_instantiateToBounds_boundRefersToEarlierTypeArgument();
   }
@@ -2155,36 +1303,18 @@
 
   @override
   @failingTest
-  test_invalid_annotation_unprefixed_constructor() async {
-    await super.test_invalid_annotation_unprefixed_constructor();
-  }
-
-  @override
-  @failingTest
   test_invalid_importPrefix_asTypeArgument() async {
     await super.test_invalid_importPrefix_asTypeArgument();
   }
 
   @override
   @failingTest
-  test_invalid_nameConflict_imported() async {
-    await super.test_invalid_nameConflict_imported();
-  }
-
-  @override
-  @failingTest
   test_invalid_nameConflict_imported_exported() async {
     await super.test_invalid_nameConflict_imported_exported();
   }
 
   @override
   @failingTest
-  test_invalid_nameConflict_local() async {
-    await super.test_invalid_nameConflict_local();
-  }
-
-  @override
-  @failingTest
   test_invalid_setterParameter_fieldFormalParameter() async {
     await super.test_invalid_setterParameter_fieldFormalParameter();
   }
@@ -2221,54 +1351,6 @@
 
   @override
   @failingTest
-  test_library_name_with_spaces() async {
-    await super.test_library_name_with_spaces();
-  }
-
-  @override
-  @failingTest
-  test_library_named() async {
-    await super.test_library_named();
-  }
-
-  @override
-  @failingTest
-  test_localFunctions() async {
-    await super.test_localFunctions();
-  }
-
-  @override
-  @failingTest
-  test_localFunctions_inMethod() async {
-    await super.test_localFunctions_inMethod();
-  }
-
-  @override
-  @failingTest
-  test_localFunctions_inTopLevelGetter() async {
-    await super.test_localFunctions_inTopLevelGetter();
-  }
-
-  @override
-  @failingTest
-  test_localLabels_inMethod() async {
-    await super.test_localLabels_inMethod();
-  }
-
-  @override
-  @failingTest
-  test_localLabels_inTopLevelFunction() async {
-    await super.test_localLabels_inTopLevelFunction();
-  }
-
-  @override
-  @failingTest
-  test_main_class_alias() async {
-    await super.test_main_class_alias();
-  }
-
-  @override
-  @failingTest
   test_main_class_alias_via_export() async {
     await super.test_main_class_alias_via_export();
   }
@@ -2281,36 +1363,18 @@
 
   @override
   @failingTest
-  test_main_getter() async {
-    await super.test_main_getter();
-  }
-
-  @override
-  @failingTest
   test_main_getter_via_export() async {
     await super.test_main_getter_via_export();
   }
 
   @override
   @failingTest
-  test_main_typedef() async {
-    await super.test_main_typedef();
-  }
-
-  @override
-  @failingTest
   test_main_typedef_via_export() async {
     await super.test_main_typedef_via_export();
   }
 
   @override
   @failingTest
-  test_main_variable() async {
-    await super.test_main_variable();
-  }
-
-  @override
-  @failingTest
   test_main_variable_via_export() async {
     await super.test_main_variable_via_export();
   }
@@ -2335,84 +1399,24 @@
 
   @override
   @failingTest
-  test_metadata_classDeclaration() async {
-    await super.test_metadata_classDeclaration();
-  }
-
-  @override
-  @failingTest
-  test_metadata_classTypeAlias() async {
-    await super.test_metadata_classTypeAlias();
-  }
-
-  @override
-  @failingTest
-  test_metadata_constructor_call_named() async {
-    await super.test_metadata_constructor_call_named();
-  }
-
-  @override
-  @failingTest
   test_metadata_constructor_call_named_prefixed() async {
     await super.test_metadata_constructor_call_named_prefixed();
   }
 
   @override
   @failingTest
-  test_metadata_constructor_call_unnamed() async {
-    await super.test_metadata_constructor_call_unnamed();
-  }
-
-  @override
-  @failingTest
   test_metadata_constructor_call_unnamed_prefixed() async {
     await super.test_metadata_constructor_call_unnamed_prefixed();
   }
 
   @override
   @failingTest
-  test_metadata_constructor_call_with_args() async {
-    await super.test_metadata_constructor_call_with_args();
-  }
-
-  @override
-  @failingTest
-  test_metadata_constructorDeclaration_named() async {
-    await super.test_metadata_constructorDeclaration_named();
-  }
-
-  @override
-  @failingTest
-  test_metadata_constructorDeclaration_unnamed() async {
-    await super.test_metadata_constructorDeclaration_unnamed();
-  }
-
-  @override
-  @failingTest
-  test_metadata_enumConstantDeclaration() async {
-    await super.test_metadata_enumConstantDeclaration();
-  }
-
-  @override
-  @failingTest
-  test_metadata_enumDeclaration() async {
-    await super.test_metadata_enumDeclaration();
-  }
-
-  @override
-  @failingTest
   test_metadata_exportDirective() async {
     await super.test_metadata_exportDirective();
   }
 
   @override
   @failingTest
-  test_metadata_fieldDeclaration() async {
-    await super.test_metadata_fieldDeclaration();
-  }
-
-  @override
-  @failingTest
   test_metadata_fieldFormalParameter() async {
     await super.test_metadata_fieldFormalParameter();
   }
@@ -2425,30 +1429,6 @@
 
   @override
   @failingTest
-  test_metadata_functionDeclaration_function() async {
-    await super.test_metadata_functionDeclaration_function();
-  }
-
-  @override
-  @failingTest
-  test_metadata_functionDeclaration_getter() async {
-    await super.test_metadata_functionDeclaration_getter();
-  }
-
-  @override
-  @failingTest
-  test_metadata_functionDeclaration_setter() async {
-    await super.test_metadata_functionDeclaration_setter();
-  }
-
-  @override
-  @failingTest
-  test_metadata_functionTypeAlias() async {
-    await super.test_metadata_functionTypeAlias();
-  }
-
-  @override
-  @failingTest
   test_metadata_functionTypedFormalParameter() async {
     await super.test_metadata_functionTypedFormalParameter();
   }
@@ -2479,24 +1459,6 @@
 
   @override
   @failingTest
-  test_metadata_methodDeclaration_getter() async {
-    await super.test_metadata_methodDeclaration_getter();
-  }
-
-  @override
-  @failingTest
-  test_metadata_methodDeclaration_method() async {
-    await super.test_metadata_methodDeclaration_method();
-  }
-
-  @override
-  @failingTest
-  test_metadata_methodDeclaration_setter() async {
-    await super.test_metadata_methodDeclaration_setter();
-  }
-
-  @override
-  @failingTest
   test_metadata_partDirective() async {
     await super.test_metadata_partDirective();
   }
@@ -2509,54 +1471,12 @@
 
   @override
   @failingTest
-  test_metadata_simpleFormalParameter() async {
-    await super.test_metadata_simpleFormalParameter();
-  }
-
-  @override
-  @failingTest
   test_metadata_simpleFormalParameter_withDefault() async {
     await super.test_metadata_simpleFormalParameter_withDefault();
   }
 
   @override
   @failingTest
-  test_metadata_topLevelVariableDeclaration() async {
-    await super.test_metadata_topLevelVariableDeclaration();
-  }
-
-  @override
-  @failingTest
-  test_metadata_typeParameter_ofClass() async {
-    await super.test_metadata_typeParameter_ofClass();
-  }
-
-  @override
-  @failingTest
-  test_metadata_typeParameter_ofClassTypeAlias() async {
-    await super.test_metadata_typeParameter_ofClassTypeAlias();
-  }
-
-  @override
-  @failingTest
-  test_metadata_typeParameter_ofFunction() async {
-    await super.test_metadata_typeParameter_ofFunction();
-  }
-
-  @override
-  @failingTest
-  test_metadata_typeParameter_ofTypedef() async {
-    await super.test_metadata_typeParameter_ofTypedef();
-  }
-
-  @override
-  @failingTest
-  test_method_documented() async {
-    await super.test_method_documented();
-  }
-
-  @override
-  @failingTest
   test_method_inferred_type_nonStatic_implicit_param() async {
     await super.test_method_inferred_type_nonStatic_implicit_param();
   }
@@ -2569,30 +1489,12 @@
 
   @override
   @failingTest
-  test_method_type_parameter() async {
-    await super.test_method_type_parameter();
-  }
-
-  @override
-  @failingTest
-  test_method_type_parameter_in_generic_class() async {
-    await super.test_method_type_parameter_in_generic_class();
-  }
-
-  @override
-  @failingTest
   test_method_type_parameter_with_function_typed_parameter() async {
     await super.test_method_type_parameter_with_function_typed_parameter();
   }
 
   @override
   @failingTest
-  test_methodInvocation_implicitCall() async {
-    await super.test_methodInvocation_implicitCall();
-  }
-
-  @override
-  @failingTest
   test_mixin() async {
     await super.test_mixin();
   }
@@ -2631,86 +1533,6 @@
 
   @override
   @failingTest
-  test_nested_generic_functions_in_generic_class_with_function_typed_params() async {
-    await super
-        .test_nested_generic_functions_in_generic_class_with_function_typed_params();
-  }
-
-  @override
-  @failingTest
-  test_nested_generic_functions_in_generic_class_with_local_variables() async {
-    await super
-        .test_nested_generic_functions_in_generic_class_with_local_variables();
-  }
-
-  @override
-  @failingTest
-  test_nested_generic_functions_with_function_typed_param() async {
-    await super.test_nested_generic_functions_with_function_typed_param();
-  }
-
-  @override
-  @failingTest
-  test_nested_generic_functions_with_local_variables() async {
-    await super.test_nested_generic_functions_with_local_variables();
-  }
-
-  @override
-  @failingTest
-  test_operator() async {
-    await super.test_operator();
-  }
-
-  @override
-  @failingTest
-  test_operator_equal() async {
-    await super.test_operator_equal();
-  }
-
-  @override
-  @failingTest
-  test_operator_external() async {
-    await super.test_operator_external();
-  }
-
-  @override
-  @failingTest
-  test_operator_greater_equal() async {
-    await super.test_operator_greater_equal();
-  }
-
-  @override
-  @failingTest
-  test_operator_index() async {
-    await super.test_operator_index();
-  }
-
-  @override
-  @failingTest
-  test_operator_index_set() async {
-    await super.test_operator_index_set();
-  }
-
-  @override
-  @failingTest
-  test_operator_less_equal() async {
-    await super.test_operator_less_equal();
-  }
-
-  @override
-  @failingTest
-  test_parameter() async {
-    await super.test_parameter();
-  }
-
-  @override
-  @failingTest
-  test_parameter_covariant() async {
-    await super.test_parameter_covariant();
-  }
-
-  @override
-  @failingTest
   test_parameter_covariant_inherited() async {
     await super.test_parameter_covariant_inherited();
   }
@@ -2741,30 +1563,12 @@
 
   @override
   @failingTest
-  test_parameterTypeNotInferred_constructor() async {
-    await super.test_parameterTypeNotInferred_constructor();
-  }
-
-  @override
-  @failingTest
   test_parameterTypeNotInferred_initializingFormal() async {
     await super.test_parameterTypeNotInferred_initializingFormal();
   }
 
   @override
   @failingTest
-  test_parameterTypeNotInferred_staticMethod() async {
-    await super.test_parameterTypeNotInferred_staticMethod();
-  }
-
-  @override
-  @failingTest
-  test_parameterTypeNotInferred_topLevelFunction() async {
-    await super.test_parameterTypeNotInferred_topLevelFunction();
-  }
-
-  @override
-  @failingTest
   test_parts() async {
     await super.test_parts();
   }
@@ -2783,84 +1587,24 @@
 
   @override
   @failingTest
-  test_propagated_type_refers_to_closure() async {
-    await super.test_propagated_type_refers_to_closure();
-  }
-
-  @override
-  @failingTest
-  test_setter_covariant() async {
-    await super.test_setter_covariant();
-  }
-
-  @override
-  @failingTest
-  test_setter_documented() async {
-    await super.test_setter_documented();
-  }
-
-  @override
-  @failingTest
-  test_setter_external() async {
-    await super.test_setter_external();
-  }
-
-  @override
-  @failingTest
-  test_setter_inferred_type_conflictingInheritance() async {
-    await super.test_setter_inferred_type_conflictingInheritance();
-  }
-
-  @override
-  @failingTest
   test_setter_inferred_type_nonStatic_implicit_param() async {
     await super.test_setter_inferred_type_nonStatic_implicit_param();
   }
 
   @override
   @failingTest
-  test_setter_inferred_type_static_implicit_return() async {
-    await super.test_setter_inferred_type_static_implicit_return();
-  }
-
-  @override
-  @failingTest
-  test_setter_inferred_type_top_level_implicit_return() async {
-    await super.test_setter_inferred_type_top_level_implicit_return();
-  }
-
-  @override
-  @failingTest
-  test_setters() async {
-    await super.test_setters();
-  }
-
-  @override
-  @failingTest
   test_syntheticFunctionType_genericClosure() async {
     await super.test_syntheticFunctionType_genericClosure();
   }
 
   @override
   @failingTest
-  test_syntheticFunctionType_genericClosure_inGenericFunction() async {
-    await super.test_syntheticFunctionType_genericClosure_inGenericFunction();
-  }
-
-  @override
-  @failingTest
   test_syntheticFunctionType_inGenericClass() async {
     await super.test_syntheticFunctionType_inGenericClass();
   }
 
   @override
   @failingTest
-  test_syntheticFunctionType_inGenericFunction() async {
-    await super.test_syntheticFunctionType_inGenericFunction();
-  }
-
-  @override
-  @failingTest
   test_syntheticFunctionType_noArguments() async {
     await super.test_syntheticFunctionType_noArguments();
   }
@@ -2873,42 +1617,12 @@
 
   @override
   @failingTest
-  test_type_arguments_explicit_dynamic_dynamic() async {
-    await super.test_type_arguments_explicit_dynamic_dynamic();
-  }
-
-  @override
-  @failingTest
-  test_type_arguments_explicit_dynamic_int() async {
-    await super.test_type_arguments_explicit_dynamic_int();
-  }
-
-  @override
-  @failingTest
-  test_type_arguments_explicit_String_dynamic() async {
-    await super.test_type_arguments_explicit_String_dynamic();
-  }
-
-  @override
-  @failingTest
-  test_type_arguments_explicit_String_int() async {
-    await super.test_type_arguments_explicit_String_int();
-  }
-
-  @override
-  @failingTest
   test_type_arguments_implicit() async {
     await super.test_type_arguments_implicit();
   }
 
   @override
   @failingTest
-  test_type_dynamic() async {
-    await super.test_type_dynamic();
-  }
-
-  @override
-  @failingTest
   test_type_inference_based_on_loadLibrary() async {
     await super.test_type_inference_based_on_loadLibrary();
   }
@@ -2999,30 +1713,12 @@
 
   @override
   @failingTest
-  test_type_reference_to_class() async {
-    await super.test_type_reference_to_class();
-  }
-
-  @override
-  @failingTest
-  test_type_reference_to_class_with_type_arguments() async {
-    await super.test_type_reference_to_class_with_type_arguments();
-  }
-
-  @override
-  @failingTest
   test_type_reference_to_class_with_type_arguments_implicit() async {
     await super.test_type_reference_to_class_with_type_arguments_implicit();
   }
 
   @override
   @failingTest
-  test_type_reference_to_enum() async {
-    await super.test_type_reference_to_enum();
-  }
-
-  @override
-  @failingTest
   test_type_reference_to_import() async {
     await super.test_type_reference_to_import();
   }
@@ -3095,24 +1791,12 @@
 
   @override
   @failingTest
-  test_type_unresolved() async {
-    await super.test_type_unresolved();
-  }
-
-  @override
-  @failingTest
   test_type_unresolved_prefixed() async {
     await super.test_type_unresolved_prefixed();
   }
 
   @override
   @failingTest
-  test_typedef_documented() async {
-    await super.test_typedef_documented();
-  }
-
-  @override
-  @failingTest
   test_typedef_generic() async {
     await super.test_typedef_generic();
   }
@@ -3143,66 +1827,12 @@
 
   @override
   @failingTest
-  test_typedef_parameter_type() async {
-    await super.test_typedef_parameter_type();
-  }
-
-  @override
-  @failingTest
-  test_typedef_parameter_type_generic() async {
-    await super.test_typedef_parameter_type_generic();
-  }
-
-  @override
-  @failingTest
-  test_typedef_parameters() async {
-    await super.test_typedef_parameters();
-  }
-
-  @override
-  @failingTest
   test_typedef_parameters_named() async {
     await super.test_typedef_parameters_named();
   }
 
   @override
   @failingTest
-  test_typedef_return_type() async {
-    await super.test_typedef_return_type();
-  }
-
-  @override
-  @failingTest
-  test_typedef_return_type_generic() async {
-    await super.test_typedef_return_type_generic();
-  }
-
-  @override
-  @failingTest
-  test_typedef_return_type_implicit() async {
-    await super.test_typedef_return_type_implicit();
-  }
-
-  @override
-  @failingTest
-  test_typedef_return_type_void() async {
-    await super.test_typedef_return_type_void();
-  }
-
-  @override
-  @failingTest
-  test_typedef_type_parameters() async {
-    await super.test_typedef_type_parameters();
-  }
-
-  @override
-  @failingTest
-  test_typedef_type_parameters_bound() async {
-    await super.test_typedef_type_parameters_bound();
-  }
-
-  @override
-  @failingTest
   test_typedef_type_parameters_bound_recursive() async {
     await super.test_typedef_type_parameters_bound_recursive();
   }
@@ -3233,49 +1863,12 @@
 
   @override
   @failingTest
-  test_typedefs() async {
-    await super.test_typedefs();
-  }
-
-  @override
-  @failingTest
-  test_unresolved_annotation_instanceCreation_argument_this() async {
-    await super.test_unresolved_annotation_instanceCreation_argument_this();
-  }
-
-  @override
-  @failingTest
-  test_unresolved_annotation_namedConstructorCall_noClass() async {
-    await super.test_unresolved_annotation_namedConstructorCall_noClass();
-  }
-
-  @override
-  @failingTest
-  test_unresolved_annotation_namedConstructorCall_noConstructor() async {
-    await super.test_unresolved_annotation_namedConstructorCall_noConstructor();
-  }
-
-  @override
-  @failingTest
-  test_unresolved_annotation_prefixedIdentifier_badPrefix() async {
-    await super.test_unresolved_annotation_prefixedIdentifier_badPrefix();
-  }
-
-  @override
-  @failingTest
   test_unresolved_annotation_prefixedIdentifier_noDeclaration() async {
     await super.test_unresolved_annotation_prefixedIdentifier_noDeclaration();
   }
 
   @override
   @failingTest
-  test_unresolved_annotation_prefixedNamedConstructorCall_badPrefix() async {
-    await super
-        .test_unresolved_annotation_prefixedNamedConstructorCall_badPrefix();
-  }
-
-  @override
-  @failingTest
   test_unresolved_annotation_prefixedNamedConstructorCall_noClass() async {
     await super
         .test_unresolved_annotation_prefixedNamedConstructorCall_noClass();
@@ -3290,13 +1883,6 @@
 
   @override
   @failingTest
-  test_unresolved_annotation_prefixedUnnamedConstructorCall_badPrefix() async {
-    await super
-        .test_unresolved_annotation_prefixedUnnamedConstructorCall_badPrefix();
-  }
-
-  @override
-  @failingTest
   test_unresolved_annotation_prefixedUnnamedConstructorCall_noClass() async {
     await super
         .test_unresolved_annotation_prefixedUnnamedConstructorCall_noClass();
@@ -3304,18 +1890,6 @@
 
   @override
   @failingTest
-  test_unresolved_annotation_simpleIdentifier() async {
-    await super.test_unresolved_annotation_simpleIdentifier();
-  }
-
-  @override
-  @failingTest
-  test_unresolved_annotation_unnamedConstructorCall_noClass() async {
-    await super.test_unresolved_annotation_unnamedConstructorCall_noClass();
-  }
-
-  @override
-  @failingTest
   test_unresolved_export() async {
     await super.test_unresolved_export();
   }
@@ -3334,36 +1908,6 @@
 
   @override
   @failingTest
-  test_unused_type_parameter() async {
-    await super.test_unused_type_parameter();
-  }
-
-  @override
-  @failingTest
-  test_variable() async {
-    await super.test_variable();
-  }
-
-  @override
-  @failingTest
-  test_variable_const() async {
-    await super.test_variable_const();
-  }
-
-  @override
-  @failingTest
-  test_variable_documented() async {
-    await super.test_variable_documented();
-  }
-
-  @override
-  @failingTest
-  test_variable_final() async {
-    await super.test_variable_final();
-  }
-
-  @override
-  @failingTest
   test_variable_getterInLib_setterInPart() async {
     await super.test_variable_getterInLib_setterInPart();
   }
@@ -3382,48 +1926,6 @@
 
   @override
   @failingTest
-  test_variable_implicit_type() async {
-    await super.test_variable_implicit_type();
-  }
-
-  @override
-  @failingTest
-  test_variable_inferred_type_implicit_initialized() async {
-    await super.test_variable_inferred_type_implicit_initialized();
-  }
-
-  @override
-  @failingTest
-  test_variable_initializer() async {
-    await super.test_variable_initializer();
-  }
-
-  @override
-  @failingTest
-  test_variable_initializer_final() async {
-    await super.test_variable_initializer_final();
-  }
-
-  @override
-  @failingTest
-  test_variable_initializer_final_untyped() async {
-    await super.test_variable_initializer_final_untyped();
-  }
-
-  @override
-  @failingTest
-  test_variable_initializer_untyped() async {
-    await super.test_variable_initializer_untyped();
-  }
-
-  @override
-  @failingTest
-  test_variable_propagatedType_const_noDep() async {
-    await super.test_variable_propagatedType_const_noDep();
-  }
-
-  @override
-  @failingTest
   test_variable_propagatedType_final_dep_inLib() async {
     await super.test_variable_propagatedType_final_dep_inLib();
   }
@@ -3436,25 +1938,38 @@
 
   @override
   @failingTest
-  test_variable_propagatedType_final_noDep() async {
-    await super.test_variable_propagatedType_final_noDep();
-  }
-
-  @override
-  @failingTest
-  test_variable_propagatedType_implicit_dep() async {
-    await super.test_variable_propagatedType_implicit_dep();
-  }
-
-  @override
-  @failingTest
   test_variable_setterInPart_getterInPart() async {
     await super.test_variable_setterInPart_getterInPart();
   }
 
-  @override
-  @failingTest
-  test_variables() async {
-    await super.test_variables();
+  LinkResult _link(Source source, String code) {
+    var unit = parseText(code, experimentStatus: experimentStatus);
+
+    // TODO(scheglov) add other libraries
+    var libraryUnitMap = {
+      source: {source: unit},
+    };
+
+    return link(
+      AnalysisOptionsImpl(),
+      sourceFactory,
+      [],
+      libraryUnitMap,
+    );
   }
 }
+
+class _FakeAnalysisContext implements AnalysisContext {
+  final SourceFactory sourceFactory;
+  TypeProvider typeProvider;
+  Dart2TypeSystem typeSystem;
+
+  _FakeAnalysisContext(this.sourceFactory);
+
+  @override
+  AnalysisOptions get analysisOptions {
+    return AnalysisOptionsImpl();
+  }
+
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
index 985f379..a931ac3 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
@@ -24,7 +24,7 @@
 
 @reflectiveTest
 class ResynthesizeAstStrongTest extends ResynthesizeTestStrategyTwoPhase
-    with ResynthesizeTestCases, ResynthesizeTestHelpers {
+    with ResynthesizeTestCases, GetElementTestCases, ResynthesizeTestHelpers {
   @failingTest // See dartbug.com/32290
   test_const_constructor_inferred_args() =>
       super.test_const_constructor_inferred_args();
@@ -35,6 +35,9 @@
   @failingTest // See dartbug.com/33441
   test_const_map_inferredType() => super.test_const_map_inferredType();
 
+  @failingTest // See dartbug.com/33441
+  test_const_set_inferredType() => super.test_const_set_inferredType();
+
   @override
   @failingTest
   test_syntheticFunctionType_inGenericClass() async {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 3f672e4..bb73374 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -9,8 +9,8 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/resynthesize.dart';
@@ -30,7 +30,6 @@
  */
 abstract class AbstractResynthesizeTest with ResourceProviderMixin {
   DeclaredVariables declaredVariables = new DeclaredVariables();
-  AnalysisOptionsImpl analysisOptions = AnalysisOptionsImpl();
   SourceFactory sourceFactory;
   MockSdk sdk;
 
@@ -107,6 +106,104 @@
 /// Mixin containing test cases exercising summary resynthesis.  Intended to be
 /// applied to a class implementing [ResynthesizeTestStrategy], along with the
 /// mixin [ResynthesizeTestHelpers].
+mixin GetElementTestCases implements ResynthesizeTestHelpers {
+  test_getElement_class() async {
+    var resynthesized = _validateGetElement(
+      'class C { m() {} }',
+      ['C'],
+    );
+    expect(resynthesized, isClassElement);
+  }
+
+  test_getElement_constructor_named() async {
+    var resynthesized = _validateGetElement(
+      'class C { C.named(); }',
+      ['C', 'named'],
+    );
+    expect(resynthesized, isConstructorElement);
+  }
+
+  test_getElement_constructor_unnamed() async {
+    var resynthesized = _validateGetElement(
+      'class C { C(); }',
+      ['C', ''],
+    );
+    expect(resynthesized, isConstructorElement);
+  }
+
+  test_getElement_field() async {
+    var resynthesized = _validateGetElement(
+      'class C { var f; }',
+      ['C', 'f'],
+    );
+    expect(resynthesized, isFieldElement);
+  }
+
+  test_getElement_getter() async {
+    var resynthesized = _validateGetElement(
+      'class C { get f => null; }',
+      ['C', 'f?'],
+    );
+    expect(resynthesized, isPropertyAccessorElement);
+  }
+
+  test_getElement_method() async {
+    var resynthesized = _validateGetElement(
+      'class C { m() {} }',
+      ['C', 'm'],
+    );
+    expect(resynthesized, isMethodElement);
+  }
+
+  test_getElement_operator() async {
+    var resynthesized = _validateGetElement(
+      'class C { operator+(x) => null; }',
+      ['C', '+'],
+    );
+    expect(resynthesized, isMethodElement);
+  }
+
+  test_getElement_setter() async {
+    var resynthesized = _validateGetElement(
+      'class C { void set f(value) {} }',
+      ['C', 'f='],
+    );
+    expect(resynthesized, isPropertyAccessorElement);
+  }
+
+  test_getElement_unit() async {
+    var resynthesized = _validateGetElement('class C {}', []);
+    expect(resynthesized, isCompilationUnitElement);
+  }
+
+  /**
+   * Encode the library [text] into a summary and then use
+   * [TestSummaryResynthesizer.getElement] to retrieve just the element with
+   * the specified [names] from the resynthesized summary.
+   */
+  Element _validateGetElement(String text, List<String> names) {
+    Source source = addTestSource(text);
+    SummaryResynthesizer resynthesizer = encodeLibrary(source);
+
+    var locationComponents = [
+      source.uri.toString(),
+      source.uri.toString(),
+    ]..addAll(names);
+    var location = ElementLocationImpl.con3(locationComponents);
+
+    Element result = resynthesizer.getElement(location);
+    checkMinimalResynthesisWork(resynthesizer, source.uri, [source.uri]);
+    // Check that no other summaries needed to be resynthesized to resynthesize
+    // the library element.
+    expect(resynthesizer.resynthesisCount, 3);
+    expect(result.location, location);
+    return result;
+  }
+}
+
+/// Mixin containing test cases exercising summary resynthesis.  Intended to be
+/// applied to a class implementing [ResynthesizeTestStrategy], along with the
+/// mixin [ResynthesizeTestHelpers].
 mixin ResynthesizeTestCases implements ResynthesizeTestHelpers {
   test_class_abstract() async {
     var library = await checkLibrary('abstract class C {}');
@@ -2459,6 +2556,34 @@
 ''');
   }
 
+  test_const_list_if() async {
+    experimentStatus = ExperimentStatus(control_flow_collections: true);
+    var library = await checkLibrary('''
+const Object x = const <int>[if (true) 1];
+''');
+    checkElementText(
+        library,
+        '''
+const Object x = const <
+        int/*location: dart:core;int*/>[if (true) 1];
+''',
+        withTypes: true);
+  }
+
+  test_const_list_if_else() async {
+    experimentStatus = ExperimentStatus(control_flow_collections: true);
+    var library = await checkLibrary('''
+const Object x = const <int>[if (true) 1 else 2];
+''');
+    checkElementText(
+        library,
+        '''
+const Object x = const <
+        int/*location: dart:core;int*/>[if (true) 1 else 2];
+''',
+        withTypes: true);
+  }
+
   test_const_list_inferredType() async {
     // The summary needs to contain enough information so that when the constant
     // is resynthesized, the constant value can get the type that was computed
@@ -2466,10 +2591,95 @@
     var library = await checkLibrary('''
 const Object x = const [1];
 ''');
-    checkElementText(library, '''
+    if (isAstBasedSummary) {
+      checkElementText(
+          library,
+          '''
+const Object x = const /*typeArgs=int*/[1];
+''',
+          withTypes: true);
+    } else {
+      checkElementText(library, '''
 const Object x = const <
         int/*location: dart:core;int*/>[1];
 ''');
+    }
+  }
+
+  test_const_list_spread() async {
+    experimentStatus = ExperimentStatus(spread_collections: true);
+    var library = await checkLibrary('''
+const Object x = const <int>[...<int>[1]];
+''');
+    if (isAstBasedSummary) {
+      checkElementText(
+          library,
+          '''
+const Object x = const <
+        int/*location: dart:core;int*/>[...<
+        int/*location: dart:core;int*/>[1]];
+''',
+          withTypes: true);
+    } else {
+      checkElementText(library, '''
+const Object x = const <
+        int/*location: dart:core;int*/>[...const <
+        int/*location: dart:core;int*/>[1]];
+''');
+    }
+  }
+
+  test_const_list_spread_null_aware() async {
+    experimentStatus = ExperimentStatus(spread_collections: true);
+    var library = await checkLibrary('''
+const Object x = const <int>[...?<int>[1]];
+''');
+    if (isAstBasedSummary) {
+      checkElementText(
+          library,
+          '''
+const Object x = const <
+        int/*location: dart:core;int*/>[...?<
+        int/*location: dart:core;int*/>[1]];
+''',
+          withTypes: true);
+    } else {
+      checkElementText(library, '''
+const Object x = const <
+        int/*location: dart:core;int*/>[...?const <
+        int/*location: dart:core;int*/>[1]];
+''');
+    }
+  }
+
+  test_const_map_if() async {
+    experimentStatus = ExperimentStatus(control_flow_collections: true);
+    var library = await checkLibrary('''
+const Object x = const <int, int>{if (true) 1: 2};
+''');
+    checkElementText(
+        library,
+        '''
+const Object x = const <
+        int/*location: dart:core;int*/,
+        int/*location: dart:core;int*/>{if (true) 1: 2}/*isMap*/;
+''',
+        withTypes: true);
+  }
+
+  test_const_map_if_else() async {
+    experimentStatus = ExperimentStatus(control_flow_collections: true);
+    var library = await checkLibrary('''
+const Object x = const <int, int>{if (true) 1: 2 else 3: 4];
+''');
+    checkElementText(
+        library,
+        '''
+const Object x = const <
+        int/*location: dart:core;int*/,
+        int/*location: dart:core;int*/>{if (true) 1: 2 else 3: 4}/*isMap*/;
+''',
+        withTypes: true);
   }
 
   test_const_map_inferredType() async {
@@ -2479,11 +2689,74 @@
     var library = await checkLibrary('''
 const Object x = const {1: 1.0};
 ''');
-    checkElementText(library, '''
+    if (isAstBasedSummary) {
+      checkElementText(
+          library,
+          '''
+const Object x = const /*typeArgs=int,double*/{1: 1.0}/*isMap*/;
+''',
+          withTypes: true);
+    } else {
+      checkElementText(library, '''
 const Object x = const <
         int/*location: dart:core;int*/,
-        double/*location: dart:core;double*/>{1: 1.0};
+        double/*location: dart:core;double*/>{1: 1.0}/*isMap*/;
 ''');
+    }
+  }
+
+  test_const_map_spread() async {
+    experimentStatus = ExperimentStatus(spread_collections: true);
+    var library = await checkLibrary('''
+const Object x = const <int, int>{...<int, int>{1: 2}};
+''');
+    if (isAstBasedSummary) {
+      checkElementText(
+          library,
+          '''
+const Object x = const <
+        int/*location: dart:core;int*/,
+        int/*location: dart:core;int*/>{...<
+        int/*location: dart:core;int*/,
+        int/*location: dart:core;int*/>{1: 2}/*isMap*/}/*isMap*/;
+''',
+          withTypes: true);
+    } else {
+      checkElementText(library, '''
+const Object x = const <
+        int/*location: dart:core;int*/,
+        int/*location: dart:core;int*/>{...const <
+        int/*location: dart:core;int*/,
+        int/*location: dart:core;int*/>{1: 2}/*isMap*/}/*isMap*/;
+''');
+    }
+  }
+
+  test_const_map_spread_null_aware() async {
+    experimentStatus = ExperimentStatus(spread_collections: true);
+    var library = await checkLibrary('''
+const Object x = const <int, int>{...?<int, int>{1: 2}};
+''');
+    if (isAstBasedSummary) {
+      checkElementText(
+          library,
+          '''
+const Object x = const <
+        int/*location: dart:core;int*/,
+        int/*location: dart:core;int*/>{...?<
+        int/*location: dart:core;int*/,
+        int/*location: dart:core;int*/>{1: 2}/*isMap*/}/*isMap*/;
+''',
+          withTypes: true);
+    } else {
+      checkElementText(library, '''
+const Object x = const <
+        int/*location: dart:core;int*/,
+        int/*location: dart:core;int*/>{...?const <
+        int/*location: dart:core;int*/,
+        int/*location: dart:core;int*/>{1: 2}/*isMap*/}/*isMap*/;
+''');
+    }
   }
 
   test_const_parameterDefaultValue_initializingFormal_functionTyped() async {
@@ -2926,6 +3199,102 @@
 ''');
   }
 
+  test_const_set_if() async {
+    experimentStatus = ExperimentStatus(control_flow_collections: true);
+    var library = await checkLibrary('''
+const Object x = const <int>{if (true) 1};
+''');
+    checkElementText(
+        library,
+        '''
+const Object x = const <
+        int/*location: dart:core;int*/>{if (true) 1}/*isSet*/;
+''',
+        withTypes: true);
+  }
+
+  test_const_set_if_else() async {
+    experimentStatus = ExperimentStatus(control_flow_collections: true);
+    var library = await checkLibrary('''
+const Object x = const <int>{if (true) 1 else 2];
+''');
+    checkElementText(
+        library,
+        '''
+const Object x = const <
+        int/*location: dart:core;int*/>{if (true) 1 else 2}/*isSet*/;
+''',
+        withTypes: true);
+  }
+
+  test_const_set_inferredType() async {
+    // The summary needs to contain enough information so that when the constant
+    // is resynthesized, the constant value can get the type that was computed
+    // by type inference.
+    var library = await checkLibrary('''
+const Object x = const {1};
+''');
+    if (isAstBasedSummary) {
+      checkElementText(
+          library,
+          '''
+const Object x = const /*typeArgs=int*/{1}/*isSet*/;
+''',
+          withTypes: true);
+    } else {
+      checkElementText(library, '''
+const Object x = const <
+        int/*location: dart:core;int*/>{1}/*isSet*/;
+''');
+    }
+  }
+
+  test_const_set_spread() async {
+    experimentStatus = ExperimentStatus(spread_collections: true);
+    var library = await checkLibrary('''
+const Object x = const <int>{...<int>{1}};
+''');
+    if (isAstBasedSummary) {
+      checkElementText(
+          library,
+          '''
+const Object x = const <
+        int/*location: dart:core;int*/>{...<
+        int/*location: dart:core;int*/>{1}/*isSet*/}/*isSet*/;
+''',
+          withTypes: true);
+    } else {
+      checkElementText(library, '''
+const Object x = const <
+        int/*location: dart:core;int*/>{...const <
+        int/*location: dart:core;int*/>{1}/*isSet*/}/*isSet*/;
+''');
+    }
+  }
+
+  test_const_set_spread_null_aware() async {
+    experimentStatus = ExperimentStatus(spread_collections: true);
+    var library = await checkLibrary('''
+const Object x = const <int>{...?<int>{1}};
+''');
+    if (isAstBasedSummary) {
+      checkElementText(
+          library,
+          '''
+const Object x = const <
+        int/*location: dart:core;int*/>{...?<
+        int/*location: dart:core;int*/>{1}/*isSet*/}/*isSet*/;
+''',
+          withTypes: true);
+    } else {
+      checkElementText(library, '''
+const Object x = const <
+        int/*location: dart:core;int*/>{...?const <
+        int/*location: dart:core;int*/>{1}/*isSet*/}/*isSet*/;
+''');
+    }
+  }
+
   test_const_topLevel_binary() async {
     var library = await checkLibrary(r'''
 const vEqual = 1 == 2;
@@ -2973,18 +3342,30 @@
     var library = await checkLibrary(r'''
 const vConditional = (1 == 2) ? 11 : 22;
 ''');
-    checkElementText(library, r'''
+    if (isAstBasedSummary) {
+      checkElementText(library, r'''
+const int vConditional = (1 == 2) ? 11 : 22;
+''');
+    } else {
+      checkElementText(library, r'''
 const int vConditional = 1 == 2 ? 11 : 22;
 ''');
+    }
   }
 
   test_const_topLevel_identical() async {
     var library = await checkLibrary(r'''
 const vIdentical = (1 == 2) ? 11 : 22;
 ''');
-    checkElementText(library, r'''
+    if (isAstBasedSummary) {
+      checkElementText(library, r'''
+const int vIdentical = (1 == 2) ? 11 : 22;
+''');
+    } else {
+      checkElementText(library, r'''
 const int vIdentical = 1 == 2 ? 11 : 22;
 ''');
+    }
   }
 
   test_const_topLevel_ifNull() async {
@@ -3076,10 +3457,16 @@
     var library = await checkLibrary(r'''
 const c = throw 42;
 ''');
-    // This is a bug.
-    checkElementText(library, r'''
+    if (isAstBasedSummary) {
+      checkElementText(library, r'''
+const dynamic c = throw 42;
+''');
+    } else {
+      // This is a bug.
+      checkElementText(library, r'''
 const dynamic c;
 ''');
+    }
   }
 
   test_const_topLevel_typedList() async {
@@ -3159,17 +3546,34 @@
     checkElementText(library, r'''
 const Map<dynamic, int> vDynamic1 = const <
         dynamic/*location: dynamic*/,
-        int/*location: dart:core;int*/>{};
+        int/*location: dart:core;int*/>{}/*isMap*/;
 const Map<int, dynamic> vDynamic2 = const <
         int/*location: dart:core;int*/,
-        dynamic/*location: dynamic*/>{};
+        dynamic/*location: dynamic*/>{}/*isMap*/;
 const Map<int, String> vInterface = const <
         int/*location: dart:core;int*/,
-        String/*location: dart:core;String*/>{};
+        String/*location: dart:core;String*/>{}/*isMap*/;
 const Map<int, List<String>> vInterfaceWithTypeArguments = const <
         int/*location: dart:core;int*/,
         List/*location: dart:core;List*/<
-        String/*location: dart:core;String*/>>{};
+        String/*location: dart:core;String*/>>{}/*isMap*/;
+''');
+  }
+
+  test_const_topLevel_typedSet() async {
+    var library = await checkLibrary(r'''
+const vDynamic1 = const <dynamic>{};
+const vInterface = const <int>{};
+const vInterfaceWithTypeArguments = const <List<String>>{};
+''');
+    checkElementText(library, r'''
+const Set<dynamic> vDynamic1 = const <
+        dynamic/*location: dynamic*/>{}/*isSet*/;
+const Set<int> vInterface = const <
+        int/*location: dart:core;int*/>{}/*isSet*/;
+const Set<List<String>> vInterfaceWithTypeArguments = const <
+        List/*location: dart:core;List*/<
+        String/*location: dart:core;String*/>>{}/*isSet*/;
 ''');
   }
 
@@ -3187,7 +3591,16 @@
 const v = const {0: 'aaa', 1: 'bbb', 2: 'ccc'};
 ''');
     checkElementText(library, r'''
-const Map<int, String> v = const {0: 'aaa', 1: 'bbb', 2: 'ccc'};
+const Map<int, String> v = const {0: 'aaa', 1: 'bbb', 2: 'ccc'}/*isMap*/;
+''');
+  }
+
+  test_const_topLevel_untypedSet() async {
+    var library = await checkLibrary(r'''
+const v = const {0, 1, 2};
+''');
+    checkElementText(library, r'''
+const Set<int> v = const {0, 1, 2}/*isSet*/;
 ''');
   }
 
@@ -4911,75 +5324,6 @@
 ''');
   }
 
-  test_getElement_class() async {
-    var resynthesized = _validateGetElement(
-      'class C { m() {} }',
-      ['C'],
-    );
-    expect(resynthesized, isClassElement);
-  }
-
-  test_getElement_constructor_named() async {
-    var resynthesized = _validateGetElement(
-      'class C { C.named(); }',
-      ['C', 'named'],
-    );
-    expect(resynthesized, isConstructorElement);
-  }
-
-  test_getElement_constructor_unnamed() async {
-    var resynthesized = _validateGetElement(
-      'class C { C(); }',
-      ['C', ''],
-    );
-    expect(resynthesized, isConstructorElement);
-  }
-
-  test_getElement_field() async {
-    var resynthesized = _validateGetElement(
-      'class C { var f; }',
-      ['C', 'f'],
-    );
-    expect(resynthesized, isFieldElement);
-  }
-
-  test_getElement_getter() async {
-    var resynthesized = _validateGetElement(
-      'class C { get f => null; }',
-      ['C', 'f?'],
-    );
-    expect(resynthesized, isPropertyAccessorElement);
-  }
-
-  test_getElement_method() async {
-    var resynthesized = _validateGetElement(
-      'class C { m() {} }',
-      ['C', 'm'],
-    );
-    expect(resynthesized, isMethodElement);
-  }
-
-  test_getElement_operator() async {
-    var resynthesized = _validateGetElement(
-      'class C { operator+(x) => null; }',
-      ['C', '+'],
-    );
-    expect(resynthesized, isMethodElement);
-  }
-
-  test_getElement_setter() async {
-    var resynthesized = _validateGetElement(
-      'class C { void set f(value) {} }',
-      ['C', 'f='],
-    );
-    expect(resynthesized, isPropertyAccessorElement);
-  }
-
-  test_getElement_unit() async {
-    var resynthesized = _validateGetElement('class C {}', []);
-    expect(resynthesized, isCompilationUnitElement);
-  }
-
   test_getter_documented() async {
     var library = await checkLibrary('''
 // Extra comment so doc comment offset != 0
@@ -6778,6 +7122,23 @@
 ''');
   }
 
+  test_metadata_simpleFormalParameter_method() async {
+    var library = await checkLibrary('''
+const a = null;
+
+class C {
+  m(@a x) {}
+}
+''');
+    checkElementText(library, r'''
+class C {
+  dynamic m(@
+        a/*location: test.dart;a?*/ dynamic x) {}
+}
+const dynamic a = null;
+''');
+  }
+
   test_metadata_simpleFormalParameter_withDefault() async {
     var library = await checkLibrary('const a = null; f([@a x = null]) {}');
     checkElementText(library, r'''
@@ -7670,6 +8031,21 @@
 ''');
   }
 
+  test_type_inference_multiplyDefinedElement() async {
+    addLibrarySource('/a.dart', 'class C {}');
+    addLibrarySource('/b.dart', 'class C {}');
+    var library = await checkLibrary('''
+import 'a.dart';
+import 'b.dart';
+var v = C;
+''');
+    checkElementText(library, r'''
+import 'a.dart';
+import 'b.dart';
+dynamic v;
+''');
+  }
+
   test_type_inference_nested_function() async {
     var library = await checkLibrary('''
 var x = (t) => (u) => t + u;
@@ -8684,30 +9060,6 @@
 int j;
 ''');
   }
-
-  /**
-   * Encode the library [text] into a summary and then use
-   * [TestSummaryResynthesizer.getElement] to retrieve just the element with
-   * the specified [names] from the resynthesized summary.
-   */
-  Element _validateGetElement(String text, List<String> names) {
-    Source source = addTestSource(text);
-    SummaryResynthesizer resynthesizer = encodeLibrary(source);
-
-    var locationComponents = [
-      source.uri.toString(),
-      source.uri.toString(),
-    ]..addAll(names);
-    var location = ElementLocationImpl.con3(locationComponents);
-
-    Element result = resynthesizer.getElement(location);
-    checkMinimalResynthesisWork(resynthesizer, source.uri, [source.uri]);
-    // Check that no other summaries needed to be resynthesized to resynthesize
-    // the library element.
-    expect(resynthesizer.resynthesisCount, 3);
-    expect(result.location, location);
-    return result;
-  }
 }
 
 /// Mixin containing helper methods for testing summary resynthesis.  Intended
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index 9d73270..e5a4dfb 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -2754,6 +2754,72 @@
         ]);
   }
 
+  test_constExpr_list_if() {
+    experimentStatus = ExperimentStatus(
+        control_flow_collections: true, spread_collections: true);
+    UnlinkedVariable variable =
+        serializeVariableText('const v = [if (true) 1];');
+    assertUnlinkedConst(variable.initializer.bodyExpr, '[if (true) 1]',
+        operators: [
+          UnlinkedExprOperation.pushTrue,
+          UnlinkedExprOperation.pushInt,
+          UnlinkedExprOperation.ifElement,
+          UnlinkedExprOperation.makeUntypedList
+        ],
+        ints: [
+          1,
+          1
+        ]);
+  }
+
+  test_constExpr_list_if_else() {
+    experimentStatus = ExperimentStatus(
+        control_flow_collections: true, spread_collections: true);
+    UnlinkedVariable variable =
+        serializeVariableText('const v = [if (true) 1 else 2];');
+    assertUnlinkedConst(variable.initializer.bodyExpr, '[if (true) 1 else 2]',
+        operators: [
+          UnlinkedExprOperation.pushTrue,
+          UnlinkedExprOperation.pushInt,
+          UnlinkedExprOperation.pushInt,
+          UnlinkedExprOperation.ifElseElement,
+          UnlinkedExprOperation.makeUntypedList
+        ],
+        ints: [
+          1,
+          2,
+          1
+        ]);
+  }
+
+  test_constExpr_list_spread() {
+    experimentStatus = ExperimentStatus(
+        control_flow_collections: true, spread_collections: true);
+    UnlinkedVariable variable = serializeVariableText('const v = [...[]];');
+    assertUnlinkedConst(variable.initializer.bodyExpr, '[...[]]', operators: [
+      UnlinkedExprOperation.makeUntypedList,
+      UnlinkedExprOperation.spreadElement,
+      UnlinkedExprOperation.makeUntypedList
+    ], ints: [
+      0,
+      1
+    ]);
+  }
+
+  test_constExpr_list_spread_null_aware() {
+    experimentStatus = ExperimentStatus(
+        control_flow_collections: true, spread_collections: true);
+    UnlinkedVariable variable = serializeVariableText('const v = [...?[]];');
+    assertUnlinkedConst(variable.initializer.bodyExpr, '[...?[]]', operators: [
+      UnlinkedExprOperation.makeUntypedList,
+      UnlinkedExprOperation.nullAwareSpreadElement,
+      UnlinkedExprOperation.makeUntypedList
+    ], ints: [
+      0,
+      1
+    ]);
+  }
+
   test_constExpr_makeSymbol() {
     UnlinkedVariable variable = serializeVariableText('const v = #a.bb.ccc;');
     assertUnlinkedConst(variable.initializer.bodyExpr, '#a.bb.ccc',
@@ -2884,11 +2950,14 @@
         operators: [
           UnlinkedExprOperation.pushInt,
           UnlinkedExprOperation.pushString,
+          UnlinkedExprOperation.makeMapLiteralEntry,
           UnlinkedExprOperation.pushInt,
           UnlinkedExprOperation.pushString,
+          UnlinkedExprOperation.makeMapLiteralEntry,
           UnlinkedExprOperation.pushInt,
           UnlinkedExprOperation.pushString,
-          UnlinkedExprOperation.makeTypedMap
+          UnlinkedExprOperation.makeMapLiteralEntry,
+          UnlinkedExprOperation.makeTypedMap2
         ],
         ints: [
           11,
@@ -2917,11 +2986,14 @@
         operators: [
           UnlinkedExprOperation.pushInt,
           UnlinkedExprOperation.pushString,
+          UnlinkedExprOperation.makeMapLiteralEntry,
           UnlinkedExprOperation.pushInt,
           UnlinkedExprOperation.pushString,
+          UnlinkedExprOperation.makeMapLiteralEntry,
           UnlinkedExprOperation.pushInt,
           UnlinkedExprOperation.pushString,
-          UnlinkedExprOperation.makeTypedMap
+          UnlinkedExprOperation.makeMapLiteralEntry,
+          UnlinkedExprOperation.makeTypedMap2
         ],
         ints: [
           11,
@@ -3078,11 +3150,14 @@
         operators: [
           UnlinkedExprOperation.pushInt,
           UnlinkedExprOperation.pushString,
+          UnlinkedExprOperation.makeMapLiteralEntry,
           UnlinkedExprOperation.pushInt,
           UnlinkedExprOperation.pushString,
+          UnlinkedExprOperation.makeMapLiteralEntry,
           UnlinkedExprOperation.pushInt,
           UnlinkedExprOperation.pushString,
-          UnlinkedExprOperation.makeUntypedMap
+          UnlinkedExprOperation.makeMapLiteralEntry,
+          UnlinkedExprOperation.makeUntypedSetOrMap
         ],
         ints: [
           11,
@@ -3108,12 +3183,129 @@
         UnlinkedExprOperation.pushInt,
         UnlinkedExprOperation.pushInt,
         UnlinkedExprOperation.pushInt,
-        UnlinkedExprOperation.makeUntypedSet
+        UnlinkedExprOperation.makeUntypedSetOrMap
       ],
       ints: [11, 22, 33, 3],
     );
   }
 
+  test_constExpr_map_if() {
+    experimentStatus = ExperimentStatus(
+        control_flow_collections: true, spread_collections: true);
+    UnlinkedVariable variable =
+        serializeVariableText('const v = <int, int>{if (true) 1 : 2};');
+    assertUnlinkedConst(
+        variable.initializer.bodyExpr, '<int, int>{if (true) 1 : 2}',
+        operators: [
+          UnlinkedExprOperation.pushTrue,
+          UnlinkedExprOperation.pushInt,
+          UnlinkedExprOperation.pushInt,
+          UnlinkedExprOperation.makeMapLiteralEntry,
+          UnlinkedExprOperation.ifElement,
+          UnlinkedExprOperation.makeTypedMap2
+        ],
+        ints: [
+          1,
+          2,
+          1
+        ],
+        referenceValidators: [
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum),
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum)
+        ]);
+  }
+
+  test_constExpr_map_if_else() {
+    experimentStatus = ExperimentStatus(
+        control_flow_collections: true, spread_collections: true);
+    UnlinkedVariable variable = serializeVariableText(
+        'const v = <int, int>{if (true) 1 : 2 else 3 : 4};');
+    assertUnlinkedConst(
+        variable.initializer.bodyExpr, '<int, int>{if (true) 1 : 2 else 3 : 4}',
+        operators: [
+          UnlinkedExprOperation.pushTrue,
+          UnlinkedExprOperation.pushInt,
+          UnlinkedExprOperation.pushInt,
+          UnlinkedExprOperation.makeMapLiteralEntry,
+          UnlinkedExprOperation.pushInt,
+          UnlinkedExprOperation.pushInt,
+          UnlinkedExprOperation.makeMapLiteralEntry,
+          UnlinkedExprOperation.ifElseElement,
+          UnlinkedExprOperation.makeTypedMap2
+        ],
+        ints: [
+          1,
+          2,
+          3,
+          4,
+          1
+        ],
+        referenceValidators: [
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum),
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum)
+        ]);
+  }
+
+  test_constExpr_map_spread() {
+    experimentStatus = ExperimentStatus(
+        control_flow_collections: true, spread_collections: true);
+    UnlinkedVariable variable =
+        serializeVariableText('const v = <int, String>{...<int, String>{}};');
+    assertUnlinkedConst(
+        variable.initializer.bodyExpr, '<int, String>{...<int, String>{}}',
+        operators: [
+          UnlinkedExprOperation.makeTypedMap2,
+          UnlinkedExprOperation.spreadElement,
+          UnlinkedExprOperation.makeTypedMap2
+        ],
+        ints: [
+          0,
+          1
+        ],
+        referenceValidators: [
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum),
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'String',
+              expectedKind: ReferenceKind.classOrEnum),
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum),
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'String',
+              expectedKind: ReferenceKind.classOrEnum)
+        ]);
+  }
+
+  test_constExpr_map_spread_null_aware() {
+    experimentStatus = ExperimentStatus(
+        control_flow_collections: true, spread_collections: true);
+    UnlinkedVariable variable =
+        serializeVariableText('const v = <int, String>{...?<int, String>{}};');
+    assertUnlinkedConst(
+        variable.initializer.bodyExpr, '<int, String>{...?<int, String>{}}',
+        operators: [
+          UnlinkedExprOperation.makeTypedMap2,
+          UnlinkedExprOperation.nullAwareSpreadElement,
+          UnlinkedExprOperation.makeTypedMap2
+        ],
+        ints: [
+          0,
+          1
+        ],
+        referenceValidators: [
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum),
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'String',
+              expectedKind: ReferenceKind.classOrEnum),
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum),
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'String',
+              expectedKind: ReferenceKind.classOrEnum)
+        ]);
+  }
+
   test_constExpr_parenthesized() {
     UnlinkedVariable variable = serializeVariableText('const v = (1 + 2) * 3;');
     assertUnlinkedConst(variable.initializer.bodyExpr, '(1 + 2) * 3',
@@ -3832,6 +4024,99 @@
         operators: [UnlinkedExprOperation.pushTrue]);
   }
 
+  test_constExpr_set_if() {
+    experimentStatus = ExperimentStatus(
+        control_flow_collections: true, spread_collections: true);
+    UnlinkedVariable variable =
+        serializeVariableText('const v = <int>{if (true) 1};');
+    assertUnlinkedConst(variable.initializer.bodyExpr, '<int>{if (true) 1}',
+        operators: [
+          UnlinkedExprOperation.pushTrue,
+          UnlinkedExprOperation.pushInt,
+          UnlinkedExprOperation.ifElement,
+          UnlinkedExprOperation.makeTypedSet
+        ],
+        ints: [
+          1,
+          1
+        ],
+        referenceValidators: [
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum)
+        ]);
+  }
+
+  test_constExpr_set_if_else() {
+    experimentStatus = ExperimentStatus(
+        control_flow_collections: true, spread_collections: true);
+    UnlinkedVariable variable =
+        serializeVariableText('const v = <int>{if (true) 1 else 2};');
+    assertUnlinkedConst(
+        variable.initializer.bodyExpr, '<int>{if (true) 1 else 2}',
+        operators: [
+          UnlinkedExprOperation.pushTrue,
+          UnlinkedExprOperation.pushInt,
+          UnlinkedExprOperation.pushInt,
+          UnlinkedExprOperation.ifElseElement,
+          UnlinkedExprOperation.makeTypedSet
+        ],
+        ints: [
+          1,
+          2,
+          1
+        ],
+        referenceValidators: [
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum)
+        ]);
+  }
+
+  test_constExpr_set_spread() {
+    experimentStatus = ExperimentStatus(
+        control_flow_collections: true, spread_collections: true);
+    UnlinkedVariable variable =
+        serializeVariableText('const v = <int>{...<int>{}};');
+    assertUnlinkedConst(variable.initializer.bodyExpr, '<int>{...<int>{}}',
+        operators: [
+          UnlinkedExprOperation.makeTypedSet,
+          UnlinkedExprOperation.spreadElement,
+          UnlinkedExprOperation.makeTypedSet
+        ],
+        ints: [
+          0,
+          1
+        ],
+        referenceValidators: [
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum),
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum)
+        ]);
+  }
+
+  test_constExpr_set_spread_null_aware() {
+    experimentStatus = ExperimentStatus(
+        control_flow_collections: true, spread_collections: true);
+    UnlinkedVariable variable =
+        serializeVariableText('const v = <int>{...?<int>{}};');
+    assertUnlinkedConst(variable.initializer.bodyExpr, '<int>{...?<int>{}}',
+        operators: [
+          UnlinkedExprOperation.makeTypedSet,
+          UnlinkedExprOperation.nullAwareSpreadElement,
+          UnlinkedExprOperation.makeTypedSet
+        ],
+        ints: [
+          0,
+          1
+        ],
+        referenceValidators: [
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum),
+          (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+              expectedKind: ReferenceKind.classOrEnum)
+        ]);
+  }
+
   test_constructor() {
     String text = 'class C { C(); }';
     UnlinkedExecutable executable =
@@ -7383,7 +7668,7 @@
         'var v = <int, String>{11: "aaa", 22: "bbb", 33: "ccc"};');
     assertUnlinkedConst(variable.initializer.bodyExpr,
         '<int, String>{11: "aaa", 22: "bbb", 33: "ccc"}',
-        operators: [UnlinkedExprOperation.makeTypedMap],
+        operators: [UnlinkedExprOperation.makeTypedMap2],
         ints: [0],
         referenceValidators: [
           (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
@@ -7429,11 +7714,14 @@
         operators: [
           UnlinkedExprOperation.pushInt,
           UnlinkedExprOperation.pushString,
+          UnlinkedExprOperation.makeMapLiteralEntry,
           UnlinkedExprOperation.pushInt,
           UnlinkedExprOperation.pushString,
+          UnlinkedExprOperation.makeMapLiteralEntry,
           UnlinkedExprOperation.pushInt,
           UnlinkedExprOperation.pushString,
-          UnlinkedExprOperation.makeUntypedMap
+          UnlinkedExprOperation.makeMapLiteralEntry,
+          UnlinkedExprOperation.makeUntypedSetOrMap
         ],
         ints: [11, 22, 33, 3],
         strings: ['aaa', 'bbb', 'ccc'],
@@ -7448,7 +7736,7 @@
           UnlinkedExprOperation.pushInt,
           UnlinkedExprOperation.pushInt,
           UnlinkedExprOperation.pushInt,
-          UnlinkedExprOperation.makeUntypedSet
+          UnlinkedExprOperation.makeUntypedSetOrMap
         ],
         ints: [11, 22, 33, 3],
         forTypeInferenceOnly: true);
diff --git a/pkg/analyzer/test/src/summary/test_strategies.dart b/pkg/analyzer/test/src/summary/test_strategies.dart
index 0ceebdf..eed8b58 100644
--- a/pkg/analyzer/test/src/summary/test_strategies.dart
+++ b/pkg/analyzer/test/src/summary/test_strategies.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -42,9 +43,11 @@
   Scanner scanner =
       new Scanner(null, reader, AnalysisErrorListener.NULL_LISTENER);
   Token token = scanner.tokenize();
-  Parser parser =
-      new Parser(NonExistingSource.unknown, AnalysisErrorListener.NULL_LISTENER)
-        ..enableNonNullable = experimentStatus.non_nullable;
+  Parser parser = new Parser(
+      NonExistingSource.unknown, AnalysisErrorListener.NULL_LISTENER)
+    ..enableNonNullable = experimentStatus.non_nullable
+    ..enableSpreadCollections = experimentStatus.spread_collections
+    ..enableControlFlowCollections = experimentStatus.control_flow_collections;
   CompilationUnit unit = parser.parseCompilationUnit(token);
   unit.lineInfo = new LineInfo(scanner.lineStarts);
   return unit;
@@ -98,6 +101,8 @@
 
   set declaredVariables(DeclaredVariables declaredVariables);
 
+  bool get isAstBasedSummary => false;
+
   MemoryResourceProvider get resourceProvider;
 
   void set testFile(String value);
@@ -132,6 +137,9 @@
 
   PackageBundleAssembler bundleAssembler = new PackageBundleAssembler();
 
+  @override
+  bool get isAstBasedSummary => false;
+
   TestSummaryResynthesizer encodeLibrary(Source source) {
     _serializeLibrary(source);
 
@@ -169,8 +177,11 @@
         .map((Source source) => source.uri.toString())
         .toSet();
 
-    Map<String, LinkedLibrary> linkedSummaries =
-        link(nonSdkLibraryUris, getDependency, getUnit, declaredVariables.get);
+    var analysisOptions = AnalysisOptionsImpl()
+      ..enabledExperiments = experimentStatus.toStringList();
+
+    Map<String, LinkedLibrary> linkedSummaries = link(nonSdkLibraryUris,
+        getDependency, getUnit, declaredVariables, analysisOptions);
 
     var analysisContext = RestrictedAnalysisContext(
       analysisOptions,
@@ -216,7 +227,8 @@
         contents = '';
       }
 
-      CompilationUnit unit = parseText(contents);
+      CompilationUnit unit =
+          parseText(contents, experimentStatus: experimentStatus);
 
       UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
       bundleAssembler.addUnlinkedUnit(source, unlinkedUnit);
@@ -244,7 +256,7 @@
     UnlinkedUnit definingUnit = _getUnlinkedUnit(librarySource);
     if (definingUnit != null) {
       LinkedLibraryBuilder linkedLibrary = prelink(librarySource.uri.toString(),
-          definingUnit, getPart, getImport, declaredVariables.get);
+          definingUnit, getPart, getImport, declaredVariables);
       linkedLibrary.dependencies.skip(1).forEach((LinkedDependency d) {
         Source source = sourceFactory.forUri(d.uri);
         _serializeLibrary(source);
@@ -265,6 +277,7 @@
   final Map<String, UnlinkedUnit> uriToUnlinkedUnit;
 
   final Map<String, LinkedLibrary> uriToLinkedLibrary;
+
   SerializedMockSdk._(this.uriToUnlinkedUnit, this.uriToLinkedLibrary);
 
   static SerializedMockSdk _serializeMockSdk() {
@@ -370,11 +383,12 @@
     }
 
     linked = new LinkedLibrary.fromBuffer(prelink(
-        _linkerInputs._testDartUri.toString(),
-        _linkerInputs._unlinkedDefiningUnit,
-        getPart,
-        getImport,
-        (String declaredVariable) => null).toBuffer());
+            _linkerInputs._testDartUri.toString(),
+            _linkerInputs._unlinkedDefiningUnit,
+            getPart,
+            getImport,
+            DeclaredVariables())
+        .toBuffer());
     _validateLinkedLibrary(linked);
   }
 }
@@ -434,9 +448,9 @@
     Map<String, LinkedLibraryBuilder> linkedLibraries = setupForLink(
         _linkerInputs.linkedLibraries,
         _linkerInputs.getUnit,
-        _linkerInputs.getDeclaredVariable);
+        _linkerInputs.declaredVariables);
     linker = new Linker(linkedLibraries, _linkerInputs.getDependency,
-        _linkerInputs.getUnit, null);
+        _linkerInputs.getUnit, null, analysisOptions);
   }
 }
 
@@ -474,11 +488,9 @@
       this._dependentLinkedLibraries,
       this._dependentUnlinkedUnits);
 
-  Set<String> get linkedLibraries => _uriToUnit.keys.toSet();
+  DeclaredVariables get declaredVariables => DeclaredVariables();
 
-  String getDeclaredVariable(String name) {
-    return null;
-  }
+  Set<String> get linkedLibraries => _uriToUnit.keys.toSet();
 
   LinkedLibrary getDependency(String absoluteUri) {
     Map<String, LinkedLibrary> sdkLibraries =
@@ -521,6 +533,9 @@
 
   _LinkerInputs _linkerInputs;
 
+  AnalysisOptions get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = experimentStatus.toStringList();
+
   bool get _allowMissingFiles;
 
   @override
@@ -545,7 +560,8 @@
         linkerInputs.linkedLibraries,
         linkerInputs.getDependency,
         linkerInputs.getUnit,
-        linkerInputs.getDeclaredVariable);
+        linkerInputs.declaredVariables,
+        analysisOptions);
     linkedLibraries.forEach(assembler.addLinkedLibrary);
     linkerInputs._uriToUnit.forEach((String uri, UnlinkedUnit unit) {
       assembler.addUnlinkedUnitViaUri(uri, unit);
@@ -609,7 +625,8 @@
         _linkerInputs.linkedLibraries,
         _linkerInputs.getDependency,
         _linkerInputs.getUnit,
-        (name) => null)[_linkerInputs._testDartUri.toString()];
+        DeclaredVariables(),
+        analysisOptions)[_linkerInputs._testDartUri.toString()];
     expect(linked, isNotNull);
     _validateLinkedLibrary(linked);
     unlinkedUnits = <UnlinkedUnit>[_linkerInputs._unlinkedDefiningUnit];
diff --git a/pkg/analyzer/test/src/summary/top_level_inference_test.dart b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
index b2c8847..b4d8961 100644
--- a/pkg/analyzer/test/src/summary/top_level_inference_test.dart
+++ b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
@@ -374,12 +374,6 @@
   @override
   List<String> get enabledExperiments =>
       [EnableString.spread_collections, EnableString.control_flow_collections];
-
-  @failingTest
-  @override
-  test_initializer_untypedMap() async {
-    await super.test_initializer_untypedMap();
-  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart b/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart
index f97c7a7..53f650d 100644
--- a/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart
+++ b/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart
@@ -6,7 +6,12 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/summary2/ast_binary_reader.dart';
 import 'package:analyzer/src/summary2/ast_binary_writer.dart';
+import 'package:analyzer/src/summary2/linked_bundle_context.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
+import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/linking_bundle_context.dart';
 import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/tokens_writer.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -122,15 +127,26 @@
     var originalUnit = parseResult.unit;
     var originalCode = originalUnit.toSource();
 
-    var writer = new AstBinaryWriter();
-    var builder = writer.writeNode(originalUnit);
-    writer.writeReferences();
-
-    var reader = AstBinaryReader(
-      Reference.root(),
-      writer.referenceBuilder,
-      writer.tokens,
+    var tokensResult = TokensWriter().writeTokens(
+      originalUnit.beginToken,
+      originalUnit.endToken,
     );
+    var tokensContext = tokensResult.toContext();
+
+    var rootReference = Reference.root();
+    var dynamicRef = rootReference.getChild('dart:core').getChild('dynamic');
+
+    var linkingBundleContext = LinkingBundleContext(dynamicRef);
+    var writer = new AstBinaryWriter(linkingBundleContext, tokensContext);
+    var builder = writer.writeNode(originalUnit);
+
+    var bundleContext = LinkedBundleContext(
+      LinkedElementFactory(null, null, rootReference),
+      linkingBundleContext.referencesBuilder,
+    );
+    var unitContext = LinkedUnitContext(bundleContext, tokensContext);
+
+    var reader = AstBinaryReader(unitContext);
     var deserializedUnit = reader.readNode(builder);
     var deserializedCode = deserializedUnit.toSource();
 
diff --git a/pkg/analyzer/test/src/summary2/test_all.dart b/pkg/analyzer/test/src/summary2/test_all.dart
new file mode 100644
index 0000000..f77acf5
--- /dev/null
+++ b/pkg/analyzer/test/src/summary2/test_all.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, 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 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'ast_binary_writer_test.dart' as ast_binary_writer;
+
+main() {
+  defineReflectiveSuite(() {
+    ast_binary_writer.main();
+  }, name: 'summary2');
+}
diff --git a/pkg/analyzer/test/src/task/dart_work_manager_test.dart b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
deleted file mode 100644
index 1a83d55..0000000
--- a/pkg/analyzer/test/src/task/dart_work_manager_test.dart
+++ /dev/null
@@ -1,994 +0,0 @@
-// Copyright (c) 2015, 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 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/error/error.dart' show AnalysisError;
-import 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/dart/scanner/scanner.dart' show ScannerErrorCode;
-import 'package:analyzer/src/generated/engine.dart'
-    show
-        AnalysisContext,
-        AnalysisErrorInfo,
-        AnalysisErrorInfoImpl,
-        AnalysisOptions,
-        AnalysisOptionsImpl,
-        CacheState,
-        ChangeNoticeImpl,
-        InternalAnalysisContext;
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/api/general.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/dart.dart';
-import 'package:analyzer/src/task/dart_work_manager.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../../generated/test_support.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(DartWorkManagerTest);
-  });
-}
-
-@reflectiveTest
-class DartWorkManagerTest {
-  _InternalAnalysisContextMock context = new _InternalAnalysisContextMock();
-  AnalysisCache cache;
-  DartWorkManager manager;
-
-  CaughtException caughtException = new CaughtException(null, null);
-
-  Source source1 = new TestSource('1.dart');
-  Source source2 = new TestSource('2.dart');
-  Source source3 = new TestSource('3.dart');
-  Source source4 = new TestSource('4.dart');
-  CacheEntry entry1;
-  CacheEntry entry2;
-  CacheEntry entry3;
-  CacheEntry entry4;
-
-  void expect_librarySourceQueue(List<Source> sources) {
-    expect(manager.librarySourceQueue, unorderedEquals(sources));
-  }
-
-  void expect_unknownSourceQueue(List<Source> sources) {
-    expect(manager.unknownSourceQueue, unorderedEquals(sources));
-  }
-
-  void setUp() {
-    cache = context.analysisCache;
-    manager = new DartWorkManager(context);
-    entry1 = _getOrCreateEntry(source1);
-    entry2 = _getOrCreateEntry(source2);
-    entry3 = _getOrCreateEntry(source3);
-    entry4 = _getOrCreateEntry(source4);
-  }
-
-  void test_applyChange_add() {
-    // add source1
-    manager.applyChange([source1], [], []);
-    expect_unknownSourceQueue([source1]);
-    expect_librarySourceQueue([]);
-    // add source2
-    manager.applyChange([source2], [], []);
-    expect_librarySourceQueue([]);
-    expect_unknownSourceQueue([source1, source2]);
-  }
-
-  void test_applyChange_add_duplicate() {
-    // add source1
-    manager.applyChange([source1], [], []);
-    expect_unknownSourceQueue([source1]);
-    expect_librarySourceQueue([]);
-    // add source2
-    manager.applyChange([source1], [], []);
-    expect_librarySourceQueue([]);
-    expect_unknownSourceQueue([source1]);
-  }
-
-  void test_applyChange_addRemove() {
-    manager.applyChange([source1, source2], [], [source2, source3]);
-    expect_unknownSourceQueue([source1]);
-    expect_librarySourceQueue([]);
-  }
-
-  void test_applyChange_change() {
-    manager.librarySourceQueue.addAll([source1, source3]);
-    manager.unknownSourceQueue.addAll([source4]);
-    // change source1
-    manager.applyChange([], [source1], []);
-    expect_librarySourceQueue([source3]);
-    expect_unknownSourceQueue([source4, source1]);
-  }
-
-  /**
-   * When we perform limited invalidation, we keep [SOURCE_KIND] valid. So, we
-   * don't need to put such sources into [DartWorkManager.unknownSourceQueue],
-   * and remove from [DartWorkManager.librarySourceQueue].
-   */
-  void test_applyChange_change_hasSourceKind() {
-    entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
-    manager.librarySourceQueue.addAll([source1, source2]);
-    manager.unknownSourceQueue.addAll([source3]);
-    // change source1
-    manager.applyChange([], [source1, source2], []);
-    expect_librarySourceQueue([source1]);
-    expect_unknownSourceQueue([source2, source3]);
-  }
-
-  void test_applyChange_remove() {
-    manager.librarySourceQueue.addAll([source1, source3]);
-    manager.unknownSourceQueue.addAll([source4]);
-    // remove source1
-    manager.applyChange([], [], [source1]);
-    expect_librarySourceQueue([source3]);
-    expect_unknownSourceQueue([source4]);
-    // remove source3
-    manager.applyChange([], [], [source3]);
-    expect_librarySourceQueue([]);
-    expect_unknownSourceQueue([source4]);
-    // remove source4
-    manager.applyChange([], [], [source4]);
-    expect_librarySourceQueue([]);
-    expect_unknownSourceQueue([]);
-  }
-
-  void test_applyChange_updatePartsLibraries_changeLibrary() {
-    Source part1 = new TestSource('part1.dart');
-    Source part2 = new TestSource('part2.dart');
-    Source part3 = new TestSource('part3.dart');
-    Source library1 = new TestSource('library1.dart');
-    Source library2 = new TestSource('library2.dart');
-    manager.partLibrariesMap[part1] = [library1, library2];
-    manager.partLibrariesMap[part2] = [library2];
-    manager.partLibrariesMap[part3] = [library1];
-    manager.libraryPartsMap[library1] = [part1, part3];
-    manager.libraryPartsMap[library2] = [part1, part2];
-    _getOrCreateEntry(part1).setValue(CONTAINING_LIBRARIES, [], []);
-    expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.VALID);
-    // change library1
-    manager.applyChange([], [library1], []);
-    expect(manager.partLibrariesMap[part1], unorderedEquals([library2]));
-    expect(manager.partLibrariesMap[part2], unorderedEquals([library2]));
-    expect(manager.partLibrariesMap[part3], unorderedEquals([]));
-    expect(manager.libraryPartsMap[library1], isNull);
-    expect(manager.libraryPartsMap[library2], [part1, part2]);
-    expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.INVALID);
-  }
-
-  void test_applyChange_updatePartsLibraries_changePart() {
-    Source part1 = new TestSource('part1.dart');
-    Source part2 = new TestSource('part2.dart');
-    Source part3 = new TestSource('part3.dart');
-    Source library1 = new TestSource('library1.dart');
-    Source library2 = new TestSource('library2.dart');
-    manager.partLibrariesMap[part1] = [library1, library2];
-    manager.partLibrariesMap[part2] = [library2];
-    manager.partLibrariesMap[part3] = [library1];
-    manager.libraryPartsMap[library1] = [part1, part3];
-    manager.libraryPartsMap[library2] = [part1, part2];
-    _getOrCreateEntry(part1).setValue(CONTAINING_LIBRARIES, [], []);
-    expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.VALID);
-    // change part1
-    manager.applyChange([], [part1], []);
-    expect(manager.partLibrariesMap[part2], unorderedEquals([library2]));
-    expect(manager.partLibrariesMap[part3], unorderedEquals([library1]));
-    expect(manager.libraryPartsMap[library1], [part1, part3]);
-    expect(manager.libraryPartsMap[library2], [part1, part2]);
-    expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.INVALID);
-  }
-
-  void test_applyChange_updatePartsLibraries_removeLibrary() {
-    Source part1 = new TestSource('part1.dart');
-    Source part2 = new TestSource('part2.dart');
-    Source part3 = new TestSource('part3.dart');
-    Source library1 = new TestSource('library1.dart');
-    Source library2 = new TestSource('library2.dart');
-    manager.partLibrariesMap[part1] = [library1, library2];
-    manager.partLibrariesMap[part2] = [library2];
-    manager.partLibrariesMap[part3] = [library1];
-    manager.libraryPartsMap[library1] = [part1, part3];
-    manager.libraryPartsMap[library2] = [part1, part2];
-    // remove library1
-    manager.applyChange([], [], [library1]);
-    expect(manager.partLibrariesMap[part1], unorderedEquals([library2]));
-    expect(manager.partLibrariesMap[part2], unorderedEquals([library2]));
-    expect(manager.partLibrariesMap[part3], unorderedEquals([]));
-    expect(manager.libraryPartsMap[library1], isNull);
-    expect(manager.libraryPartsMap[library2], [part1, part2]);
-  }
-
-  void test_applyChange_updatePartsLibraries_removePart() {
-    Source part1 = new TestSource('part1.dart');
-    Source part2 = new TestSource('part2.dart');
-    Source part3 = new TestSource('part3.dart');
-    Source library1 = new TestSource('library1.dart');
-    Source library2 = new TestSource('library2.dart');
-    manager.partLibrariesMap[part1] = [library1, library2];
-    manager.partLibrariesMap[part2] = [library2];
-    manager.partLibrariesMap[part3] = [library1];
-    manager.libraryPartsMap[library1] = [part1, part3];
-    manager.libraryPartsMap[library2] = [part1, part2];
-    // remove part1
-    manager.applyChange([], [], [part1]);
-    expect(manager.partLibrariesMap[part1], isNull);
-    expect(manager.partLibrariesMap[part2], unorderedEquals([library2]));
-    expect(manager.partLibrariesMap[part3], unorderedEquals([library1]));
-    expect(manager.libraryPartsMap[library1], [part1, part3]);
-    expect(manager.libraryPartsMap[library2], [part1, part2]);
-  }
-
-  void test_applyPriorityTargets_isLibrary_computeErrors() {
-    context.setShouldErrorsBeAnalyzed(source2, true);
-    context.setShouldErrorsBeAnalyzed(source3, true);
-    entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
-    entry2.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
-    entry3.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
-    manager.priorityResultQueue
-        .add(new TargetedResult(source1, LIBRARY_ERRORS_READY));
-    manager.priorityResultQueue
-        .add(new TargetedResult(source2, LIBRARY_ERRORS_READY));
-    // -source1 +source3
-    manager.applyPriorityTargets([source2, source3]);
-    expect(
-        manager.priorityResultQueue,
-        unorderedEquals([
-          new TargetedResult(source2, LIBRARY_ERRORS_READY),
-          new TargetedResult(source3, LIBRARY_ERRORS_READY)
-        ]));
-    // get next request
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source2);
-    expect(request.result, LIBRARY_ERRORS_READY);
-  }
-
-  void test_applyPriorityTargets_isLibrary_computeUnit() {
-    context.setShouldErrorsBeAnalyzed(source2, false);
-    context.setShouldErrorsBeAnalyzed(source3, false);
-    entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
-    entry2.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
-    entry3.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
-    manager.priorityResultQueue
-        .add(new TargetedResult(source1, LIBRARY_ERRORS_READY));
-    manager.priorityResultQueue
-        .add(new TargetedResult(source2, LIBRARY_ERRORS_READY));
-    // -source1 +source3
-    manager.applyPriorityTargets([source2, source3]);
-    expect(
-        manager.priorityResultQueue,
-        unorderedEquals([
-          new TargetedResult(
-              new LibrarySpecificUnit(source2, source2), RESOLVED_UNIT),
-          new TargetedResult(
-              new LibrarySpecificUnit(source3, source3), RESOLVED_UNIT),
-        ]));
-  }
-
-  void test_applyPriorityTargets_isPart() {
-    entry1.setValue(SOURCE_KIND, SourceKind.PART, []);
-    entry2.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
-    entry3.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
-    // +source2 +source3
-    context.getLibrariesContainingMap[source1] = <Source>[source2, source3];
-    manager.applyPriorityTargets([source1]);
-    expect(
-        manager.priorityResultQueue,
-        unorderedEquals([
-          new TargetedResult(source2, LIBRARY_ERRORS_READY),
-          new TargetedResult(source3, LIBRARY_ERRORS_READY)
-        ]));
-    // get next request
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source2);
-    expect(request.result, LIBRARY_ERRORS_READY);
-  }
-
-  void test_applyPriorityTargets_isUnknown() {
-    manager.applyPriorityTargets([source2, source3]);
-    expect(
-        manager.priorityResultQueue,
-        unorderedEquals([
-          new TargetedResult(source2, SOURCE_KIND),
-          new TargetedResult(source3, SOURCE_KIND)
-        ]));
-    // get next request
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source2);
-    expect(request.result, SOURCE_KIND);
-  }
-
-  void test_getErrors() {
-    AnalysisError error1 =
-        new AnalysisError(source1, 1, 0, ScannerErrorCode.MISSING_DIGIT);
-    AnalysisError error2 =
-        new AnalysisError(source1, 2, 0, ScannerErrorCode.MISSING_DIGIT);
-    context.getLibrariesContainingMap[source1] = <Source>[source2];
-    entry1.setValue(SCAN_ERRORS, <AnalysisError>[error1], []);
-    context
-        .getCacheEntry(new LibrarySpecificUnit(source2, source1))
-        .setValue(VERIFY_ERRORS, <AnalysisError>[error2], []);
-    List<AnalysisError> errors = manager.getErrors(source1);
-    expect(errors, unorderedEquals([error1, error2]));
-  }
-
-  void test_getErrors_hasFullList() {
-    AnalysisError error1 =
-        new AnalysisError(source1, 1, 0, ScannerErrorCode.MISSING_DIGIT);
-    AnalysisError error2 =
-        new AnalysisError(source1, 2, 0, ScannerErrorCode.MISSING_DIGIT);
-    context.getLibrariesContainingMap[source1] = <Source>[source2];
-    entry1.setValue(DART_ERRORS, <AnalysisError>[error1, error2], []);
-    List<AnalysisError> errors = manager.getErrors(source1);
-    expect(errors, unorderedEquals([error1, error2]));
-  }
-
-  void test_getLibrariesContainingPart() {
-    context.aboutToComputeEverything = false;
-    Source part1 = new TestSource('part1.dart');
-    Source part2 = new TestSource('part2.dart');
-    Source part3 = new TestSource('part3.dart');
-    Source library1 = new TestSource('library1.dart');
-    Source library2 = new TestSource('library2.dart');
-    manager.partLibrariesMap[part1] = [library1, library2];
-    manager.partLibrariesMap[part2] = [library2];
-    manager.libraryPartsMap[library1] = [part1];
-    manager.libraryPartsMap[library2] = [part1, part2];
-    // getLibrariesContainingPart
-    expect(manager.getLibrariesContainingPart(part1),
-        unorderedEquals([library1, library2]));
-    expect(
-        manager.getLibrariesContainingPart(part2), unorderedEquals([library2]));
-    expect(manager.getLibrariesContainingPart(part3), isEmpty);
-  }
-
-  void test_getLibrariesContainingPart_askResultProvider() {
-    Source part1 = new TestSource('part1.dart');
-    Source part2 = new TestSource('part2.dart');
-    Source part3 = new TestSource('part3.dart');
-    Source library1 = new TestSource('library1.dart');
-    Source library2 = new TestSource('library2.dart');
-    // configure AnalysisContext mock
-    context.aboutToComputeResultMap[CONTAINING_LIBRARIES] =
-        (CacheEntry entry, ResultDescriptor result) {
-      if (entry.target == part1) {
-        entry.setValue(result as ResultDescriptor<List<Source>>,
-            <Source>[library1, library2], []);
-        return true;
-      }
-      if (entry.target == part2) {
-        entry.setValue(
-            result as ResultDescriptor<List<Source>>, <Source>[library2], []);
-        return true;
-      }
-      return false;
-    };
-    // getLibrariesContainingPart
-    expect(manager.getLibrariesContainingPart(part1),
-        unorderedEquals([library1, library2]));
-    expect(
-        manager.getLibrariesContainingPart(part2), unorderedEquals([library2]));
-    expect(manager.getLibrariesContainingPart(part3), isEmpty);
-  }
-
-  void test_getLibrariesContainingPart_inSDK() {
-    _SourceMock part = new _SourceMock('part.dart');
-    part.isInSystemLibrary = true;
-    // SDK work manager
-    _DartWorkManagerMock sdkDartWorkManagerMock = new _DartWorkManagerMock();
-    sdkDartWorkManagerMock.librariesContainingPartMap[part] = <Source>[
-      source2,
-      source3
-    ];
-    // SDK context mock
-    _InternalAnalysisContextMock sdkContextMock =
-        new _InternalAnalysisContextMock();
-    sdkContextMock.workManagers = <WorkManager>[sdkDartWorkManagerMock];
-    // SDK mock
-    _DartSdkMock sdkMock = new _DartSdkMock();
-    sdkMock.context = sdkContextMock;
-    // SourceFactory mock
-    _SourceFactoryMock sourceFactory = new _SourceFactoryMock();
-    sourceFactory.dartSdk = sdkMock;
-    context.sourceFactory = sourceFactory;
-    // SDK source mock
-    _SourceMock source = new _SourceMock('test.dart');
-    source.source = source;
-    source.isInSystemLibrary = true;
-    // validate
-    expect(manager.getLibrariesContainingPart(part),
-        unorderedEquals([source2, source3]));
-  }
-
-  void test_getNextResult_hasLibraries_firstIsError() {
-    entry1.setErrorState(caughtException, [LIBRARY_ERRORS_READY]);
-    manager.librarySourceQueue.addAll([source1, source2]);
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source2);
-    expect(request.result, LIBRARY_ERRORS_READY);
-    // source1 is out, source2 is waiting
-    expect_librarySourceQueue([source2]);
-  }
-
-  void test_getNextResult_hasLibraries_firstIsInvalid() {
-    entry1.setState(LIBRARY_ERRORS_READY, CacheState.INVALID);
-    manager.librarySourceQueue.addAll([source1, source2]);
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source1);
-    expect(request.result, LIBRARY_ERRORS_READY);
-    // no changes until computed
-    expect_librarySourceQueue([source1, source2]);
-  }
-
-  void test_getNextResult_hasLibraries_firstIsValid() {
-    entry1.setValue(LIBRARY_ERRORS_READY, true, []);
-    manager.librarySourceQueue.addAll([source1, source2]);
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source2);
-    expect(request.result, LIBRARY_ERRORS_READY);
-    // source1 is out, source2 is waiting
-    expect_librarySourceQueue([source2]);
-  }
-
-  void test_getNextResult_hasPriority_firstIsError() {
-    manager.addPriorityResult(source1, SOURCE_KIND);
-    manager.addPriorityResult(source2, SOURCE_KIND);
-    expect(
-        manager.priorityResultQueue,
-        unorderedEquals([
-          new TargetedResult(source1, SOURCE_KIND),
-          new TargetedResult(source2, SOURCE_KIND)
-        ]));
-    // configure state and get next result
-    entry1.setErrorState(caughtException, [SOURCE_KIND]);
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source2);
-    expect(request.result, SOURCE_KIND);
-    // source1 is out, source2 is waiting
-    expect(manager.priorityResultQueue,
-        unorderedEquals([new TargetedResult(source2, SOURCE_KIND)]));
-  }
-
-  void test_getNextResult_hasPriority_firstIsValid() {
-    manager.addPriorityResult(source1, SOURCE_KIND);
-    manager.addPriorityResult(source2, SOURCE_KIND);
-    expect(
-        manager.priorityResultQueue,
-        unorderedEquals([
-          new TargetedResult(source1, SOURCE_KIND),
-          new TargetedResult(source2, SOURCE_KIND)
-        ]));
-    // configure state and get next result
-    entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source2);
-    expect(request.result, SOURCE_KIND);
-    // source1 is out, source2 is waiting
-    expect(manager.priorityResultQueue,
-        unorderedEquals([new TargetedResult(source2, SOURCE_KIND)]));
-  }
-
-  void test_getNextResult_hasUnknown_firstIsError() {
-    entry1.setErrorState(caughtException, [SOURCE_KIND]);
-    manager.unknownSourceQueue.addAll([source1, source2]);
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source2);
-    expect(request.result, SOURCE_KIND);
-    // source1 is out, source2 is waiting
-    expect_librarySourceQueue([]);
-    expect_unknownSourceQueue([source2]);
-  }
-
-  void test_getNextResult_hasUnknown_firstIsInvalid() {
-    manager.unknownSourceQueue.addAll([source1, source2]);
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source1);
-    expect(request.result, SOURCE_KIND);
-    // no changes until computed
-    expect_librarySourceQueue([]);
-    expect_unknownSourceQueue([source1, source2]);
-  }
-
-  void test_getNextResult_hasUnknown_firstIsValid() {
-    entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
-    manager.unknownSourceQueue.addAll([source1, source2]);
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source2);
-    expect(request.result, SOURCE_KIND);
-    // source1 is out, source2 is waiting
-    expect_librarySourceQueue([]);
-    expect_unknownSourceQueue([source2]);
-  }
-
-  void test_getNextResult_nothingToDo() {
-    TargetedResult request = manager.getNextResult();
-    expect(request, isNull);
-  }
-
-  void test_getNextResultPriority_hasLibrary() {
-    manager.librarySourceQueue.addAll([source1]);
-    expect(manager.getNextResultPriority(), WorkOrderPriority.NORMAL);
-  }
-
-  void test_getNextResultPriority_hasPriority() {
-    manager.addPriorityResult(source1, SOURCE_KIND);
-    expect(manager.getNextResultPriority(), WorkOrderPriority.PRIORITY);
-  }
-
-  void test_getNextResultPriority_hasUnknown() {
-    manager.unknownSourceQueue.addAll([source1]);
-    expect(manager.getNextResultPriority(), WorkOrderPriority.NORMAL);
-  }
-
-  void test_getNextResultPriority_nothingToDo() {
-    expect(manager.getNextResultPriority(), WorkOrderPriority.NONE);
-  }
-
-  void test_onAnalysisOptionsChanged() {
-    context.everythingExists = true;
-    // set cache values
-    entry1.setValue(PARSED_UNIT, AstTestFactory.compilationUnit(), []);
-    entry1.setValue(IMPORTED_LIBRARIES, <Source>[], []);
-    entry1.setValue(EXPLICITLY_IMPORTED_LIBRARIES, <Source>[], []);
-    entry1.setValue(EXPORTED_LIBRARIES, <Source>[], []);
-    entry1.setValue(INCLUDED_PARTS, <Source>[], []);
-    // configure LibrarySpecificUnit
-    LibrarySpecificUnit unitTarget = new LibrarySpecificUnit(source2, source3);
-    CacheEntry unitEntry = new CacheEntry(unitTarget);
-    cache.put(unitEntry);
-    unitEntry.setValue(BUILD_LIBRARY_ERRORS, <AnalysisError>[], []);
-    expect(unitEntry.getState(BUILD_LIBRARY_ERRORS), CacheState.VALID);
-    // notify
-    manager.onAnalysisOptionsChanged();
-    // resolution is invalidated
-    expect(unitEntry.getState(BUILD_LIBRARY_ERRORS), CacheState.INVALID);
-    // ...but URIs are still value
-    expect(entry1.getState(PARSED_UNIT), CacheState.VALID);
-    expect(entry1.getState(IMPORTED_LIBRARIES), CacheState.VALID);
-    expect(entry1.getState(EXPLICITLY_IMPORTED_LIBRARIES), CacheState.VALID);
-    expect(entry1.getState(EXPORTED_LIBRARIES), CacheState.VALID);
-    expect(entry1.getState(INCLUDED_PARTS), CacheState.VALID);
-  }
-
-  void test_onResultInvalidated_scheduleInvalidatedLibraries() {
-    // make source3 implicit
-    entry3.explicitlyAdded = false;
-    // set SOURCE_KIND
-    entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
-    entry2.setValue(SOURCE_KIND, SourceKind.PART, []);
-    entry3.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
-    // set LIBRARY_ERRORS_READY for source1 and source3
-    entry1.setValue(LIBRARY_ERRORS_READY, true, []);
-    entry3.setValue(LIBRARY_ERRORS_READY, true, []);
-    // invalidate LIBRARY_ERRORS_READY for source1, schedule it
-    entry1.setState(LIBRARY_ERRORS_READY, CacheState.INVALID);
-    expect_librarySourceQueue([source1]);
-    // invalidate LIBRARY_ERRORS_READY for source3, implicit, not scheduled
-    entry3.setState(LIBRARY_ERRORS_READY, CacheState.INVALID);
-    expect_librarySourceQueue([source1]);
-  }
-
-  void test_onSourceFactoryChanged() {
-    context.everythingExists = true;
-    // set cache values
-    entry1.setValue(PARSED_UNIT, AstTestFactory.compilationUnit(), []);
-    entry1.setValue(IMPORTED_LIBRARIES, <Source>[], []);
-    entry1.setValue(EXPLICITLY_IMPORTED_LIBRARIES, <Source>[], []);
-    entry1.setValue(EXPORTED_LIBRARIES, <Source>[], []);
-    entry1.setValue(INCLUDED_PARTS, <Source>[], []);
-    entry1.setValue(LIBRARY_SPECIFIC_UNITS, <LibrarySpecificUnit>[], []);
-    entry1.setValue(UNITS, <Source>[], []);
-    // configure LibrarySpecificUnit
-    LibrarySpecificUnit unitTarget = new LibrarySpecificUnit(source2, source3);
-    CacheEntry unitEntry = new CacheEntry(unitTarget);
-    cache.put(unitEntry);
-    unitEntry.setValue(BUILD_LIBRARY_ERRORS, <AnalysisError>[], []);
-    expect(unitEntry.getState(BUILD_LIBRARY_ERRORS), CacheState.VALID);
-    // notify
-    manager.onSourceFactoryChanged();
-    // resolution is invalidated
-    expect(unitEntry.getState(BUILD_LIBRARY_ERRORS), CacheState.INVALID);
-    // ...and URIs resolution too
-    expect(entry1.getState(PARSED_UNIT), CacheState.INVALID);
-    expect(entry1.getState(IMPORTED_LIBRARIES), CacheState.INVALID);
-    expect(entry1.getState(EXPLICITLY_IMPORTED_LIBRARIES), CacheState.INVALID);
-    expect(entry1.getState(EXPORTED_LIBRARIES), CacheState.INVALID);
-    expect(entry1.getState(INCLUDED_PARTS), CacheState.INVALID);
-    expect(entry1.getState(LIBRARY_SPECIFIC_UNITS), CacheState.INVALID);
-    expect(entry1.getState(UNITS), CacheState.INVALID);
-  }
-
-  void test_resultsComputed_errors_forLibrarySpecificUnit() {
-    LineInfo lineInfo = new LineInfo([0]);
-    AnalysisError error1 =
-        new AnalysisError(source1, 1, 0, ScannerErrorCode.MISSING_DIGIT);
-    AnalysisError error2 =
-        new AnalysisError(source1, 2, 0, ScannerErrorCode.MISSING_DIGIT);
-    context.getLibrariesContainingMap[source1] = <Source>[source2];
-    context.errorsMap[source1] =
-        new AnalysisErrorInfoImpl([error1, error2], lineInfo);
-    entry1.setValue(LINE_INFO, lineInfo, []);
-    entry1.setValue(SCAN_ERRORS, <AnalysisError>[error1], []);
-    AnalysisTarget unitTarget = new LibrarySpecificUnit(source2, source1);
-    context
-        .getCacheEntry(unitTarget)
-        .setValue(VERIFY_ERRORS, <AnalysisError>[error2], []);
-    // RESOLVED_UNIT is ready, set errors
-    manager.resultsComputed(
-        unitTarget, {RESOLVED_UNIT: AstTestFactory.compilationUnit()});
-    // all of the errors are included
-    ChangeNoticeImpl notice = context.getNotice(source1);
-    expect(notice.errors, unorderedEquals([error1, error2]));
-    expect(notice.lineInfo, lineInfo);
-  }
-
-  void test_resultsComputed_errors_forSource() {
-    LineInfo lineInfo = new LineInfo([0]);
-    AnalysisError error1 =
-        new AnalysisError(source1, 1, 0, ScannerErrorCode.MISSING_DIGIT);
-    AnalysisError error2 =
-        new AnalysisError(source1, 2, 0, ScannerErrorCode.MISSING_DIGIT);
-    context.getLibrariesContainingMap[source1] = <Source>[source2];
-    context.errorsMap[source1] =
-        new AnalysisErrorInfoImpl([error1, error2], lineInfo);
-    entry1.setValue(LINE_INFO, lineInfo, []);
-    entry1.setValue(SCAN_ERRORS, <AnalysisError>[error1], []);
-    entry1.setValue(PARSE_ERRORS, <AnalysisError>[error2], []);
-    // PARSED_UNIT is ready, set errors
-    manager.resultsComputed(
-        source1, {PARSED_UNIT: AstTestFactory.compilationUnit()});
-    // all of the errors are included
-    ChangeNoticeImpl notice = context.getNotice(source1);
-    expect(notice.errors, unorderedEquals([error1, error2]));
-    expect(notice.lineInfo, lineInfo);
-  }
-
-  void test_resultsComputed_includedParts_updatePartLibraries() {
-    Source part1 = new TestSource('part1.dart');
-    Source part2 = new TestSource('part2.dart');
-    Source part3 = new TestSource('part3.dart');
-    Source library1 = new TestSource('library1.dart');
-    Source library2 = new TestSource('library2.dart');
-    _getOrCreateEntry(part1).setValue(CONTAINING_LIBRARIES, [], []);
-    expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.VALID);
-    // configure AnalysisContext mock
-    context.prioritySources = <Source>[];
-    context.analyzeAllErrors = false;
-    // library1 parts
-    manager.resultsComputed(library1, <ResultDescriptor, dynamic>{
-      INCLUDED_PARTS: [part1, part2],
-      SOURCE_KIND: SourceKind.LIBRARY
-    });
-    expect(manager.partLibrariesMap[part1], [library1]);
-    expect(manager.partLibrariesMap[part2], [library1]);
-    expect(manager.partLibrariesMap[part3], isNull);
-    expect(manager.libraryPartsMap[library1], [part1, part2]);
-    expect(manager.libraryPartsMap[library2], isNull);
-    // library2 parts
-    manager.resultsComputed(library2, <ResultDescriptor, dynamic>{
-      INCLUDED_PARTS: [part2, part3],
-      SOURCE_KIND: SourceKind.LIBRARY
-    });
-    expect(manager.partLibrariesMap[part1], [library1]);
-    expect(manager.partLibrariesMap[part2], [library1, library2]);
-    expect(manager.partLibrariesMap[part3], [library2]);
-    expect(manager.libraryPartsMap[library1], [part1, part2]);
-    expect(manager.libraryPartsMap[library2], [part2, part3]);
-    // part1 CONTAINING_LIBRARIES
-    expect(cache.getState(part1, CONTAINING_LIBRARIES), CacheState.INVALID);
-  }
-
-  void test_resultsComputed_inSDK() {
-    _DartWorkManagerMock sdkDartWorkManagerMock = new _DartWorkManagerMock();
-    // SDK context mock
-    _InternalAnalysisContextMock sdkContextMock =
-        new _InternalAnalysisContextMock();
-    sdkContextMock.workManagers = <WorkManager>[sdkDartWorkManagerMock];
-    // SDK mock
-    _DartSdkMock sdkMock = new _DartSdkMock();
-    sdkMock.context = sdkContextMock;
-    // SourceFactory mock
-    _SourceFactoryMock sourceFactory = new _SourceFactoryMock();
-    sourceFactory.dartSdk = sdkMock;
-    context.sourceFactory = sourceFactory;
-    // SDK source mock
-    _SourceMock source = new _SourceMock('test.dart');
-    source.source = source;
-    source.isInSystemLibrary = true;
-    // notify and validate
-    Map<ResultDescriptor, dynamic> outputs = <ResultDescriptor, dynamic>{};
-    manager.resultsComputed(source, outputs);
-    var bySourceMap = sdkDartWorkManagerMock.resultsComputedCounts[source];
-    expect(bySourceMap, isNotNull);
-    expect(bySourceMap[outputs], 1);
-  }
-
-  void test_resultsComputed_noSourceKind() {
-    manager.unknownSourceQueue.addAll([source1, source2]);
-    manager.resultsComputed(source1, {});
-    expect_librarySourceQueue([]);
-    expect_unknownSourceQueue([source1, source2]);
-  }
-
-  void test_resultsComputed_notDart() {
-    manager.unknownSourceQueue.addAll([source1, source2]);
-    manager.resultsComputed(new TestSource('test.html'), {});
-    expect_librarySourceQueue([]);
-    expect_unknownSourceQueue([source1, source2]);
-  }
-
-  void test_resultsComputed_parsedUnit() {
-    LineInfo lineInfo = new LineInfo([0]);
-    context.getLibrariesContainingMap[source1] = <Source>[];
-    context.errorsMap[source1] = new AnalysisErrorInfoImpl([], lineInfo);
-    entry1.setValue(LINE_INFO, lineInfo, []);
-    CompilationUnit unit = AstTestFactory.compilationUnit();
-    manager.resultsComputed(source1, {PARSED_UNIT: unit});
-    ChangeNoticeImpl notice = context.getNotice(source1);
-    expect(notice.parsedDartUnit, unit);
-    expect(notice.resolvedDartUnit, isNull);
-    expect(notice.lineInfo, lineInfo);
-  }
-
-  void test_resultsComputed_resolvedUnit() {
-    LineInfo lineInfo = new LineInfo([0]);
-    context.getLibrariesContainingMap[source2] = <Source>[];
-    context.errorsMap[source2] = new AnalysisErrorInfoImpl([], lineInfo);
-    entry2.setValue(LINE_INFO, lineInfo, []);
-    CompilationUnit unit = AstTestFactory.compilationUnit();
-    manager.resultsComputed(
-        new LibrarySpecificUnit(source1, source2), {RESOLVED_UNIT: unit});
-    ChangeNoticeImpl notice = context.getNotice(source2);
-    expect(notice.parsedDartUnit, isNull);
-    expect(notice.resolvedDartUnit, unit);
-    expect(notice.lineInfo, lineInfo);
-  }
-
-  void test_resultsComputed_sourceKind_isLibrary() {
-    manager.unknownSourceQueue.addAll([source1, source2, source3]);
-    context.prioritySources = <Source>[];
-    context.shouldErrorsBeAnalyzedMap[source2] = true;
-    manager.resultsComputed(source2, {SOURCE_KIND: SourceKind.LIBRARY});
-    expect_librarySourceQueue([source2]);
-    expect_unknownSourceQueue([source1, source3]);
-  }
-
-  void test_resultsComputed_sourceKind_isLibrary_isPriority_computeErrors() {
-    manager.unknownSourceQueue.addAll([source1, source2, source3]);
-    context.prioritySources = <Source>[source2];
-    context.shouldErrorsBeAnalyzedMap[source2] = true;
-    manager.resultsComputed(source2, {SOURCE_KIND: SourceKind.LIBRARY});
-    expect_unknownSourceQueue([source1, source3]);
-    expect(manager.priorityResultQueue,
-        unorderedEquals([new TargetedResult(source2, LIBRARY_ERRORS_READY)]));
-  }
-
-  void test_resultsComputed_sourceKind_isLibrary_isPriority_computeUnit() {
-    manager.unknownSourceQueue.addAll([source1, source2, source3]);
-    context.prioritySources = <Source>[source2];
-    context.shouldErrorsBeAnalyzedMap[source2] = false;
-    manager.resultsComputed(source2, {SOURCE_KIND: SourceKind.LIBRARY});
-    expect_unknownSourceQueue([source1, source3]);
-    expect(
-        manager.priorityResultQueue,
-        unorderedEquals([
-          new TargetedResult(
-              new LibrarySpecificUnit(source2, source2), RESOLVED_UNIT)
-        ]));
-  }
-
-  void test_resultsComputed_sourceKind_isPart() {
-    manager.unknownSourceQueue.addAll([source1, source2, source3]);
-    manager.resultsComputed(source2, {SOURCE_KIND: SourceKind.PART});
-    expect_librarySourceQueue([]);
-    expect_unknownSourceQueue([source1, source3]);
-  }
-
-  void test_resultsComputed_updatePartsLibraries_partParsed() {
-    Source part = new TestSource('part.dart');
-    expect(manager.libraryPartsMap, isEmpty);
-    // part.dart parsed, no changes is the map of libraries
-    manager.resultsComputed(part, <ResultDescriptor, dynamic>{
-      SOURCE_KIND: SourceKind.PART,
-      INCLUDED_PARTS: <Source>[]
-    });
-    expect(manager.libraryPartsMap, isEmpty);
-  }
-
-  void test_unitIncrementallyResolved() {
-    manager.unitIncrementallyResolved(source1, source2);
-    expect_librarySourceQueue([source1]);
-  }
-
-  CacheEntry _getOrCreateEntry(Source source, [bool explicit = true]) {
-    CacheEntry entry = cache.get(source);
-    if (entry == null) {
-      entry = new CacheEntry(source);
-      entry.explicitlyAdded = explicit;
-      cache.put(entry);
-    }
-    return entry;
-  }
-}
-
-class _DartSdkMock implements DartSdk {
-  AnalysisContext context;
-
-  @override
-  noSuchMethod(Invocation invocation) {
-    throw new StateError('Unexpected invocation of ${invocation.memberName}');
-  }
-}
-
-class _DartWorkManagerMock implements DartWorkManager {
-  Map<Source, List<Source>> librariesContainingPartMap =
-      <Source, List<Source>>{};
-
-  Map<Source, Map<Map<ResultDescriptor, dynamic>, int>> resultsComputedCounts =
-      <Source, Map<Map<ResultDescriptor, dynamic>, int>>{};
-
-  @override
-  List<Source> getLibrariesContainingPart(Source part) {
-    return librariesContainingPartMap[part] ?? <Source>[];
-  }
-
-  @override
-  noSuchMethod(Invocation invocation) {
-    throw new StateError('Unexpected invocation of ${invocation.memberName}');
-  }
-
-  @override
-  void resultsComputed(
-      AnalysisTarget target, Map<ResultDescriptor, dynamic> outputs) {
-    Map<Map<ResultDescriptor, dynamic>, int> bySourceMap =
-        resultsComputedCounts.putIfAbsent(target, () => {});
-    bySourceMap[outputs] = (bySourceMap[outputs] ?? 0) + 1;
-  }
-}
-
-class _InternalAnalysisContextMock implements InternalAnalysisContext {
-  @override
-  CachePartition privateAnalysisCachePartition;
-
-  @override
-  AnalysisCache analysisCache;
-
-  @override
-  SourceFactory sourceFactory;
-
-  bool analyzeAllErrors;
-
-  bool everythingExists = false;
-
-  bool aboutToComputeEverything;
-
-  @override
-  List<Source> prioritySources = <Source>[];
-
-  @override
-  List<WorkManager> workManagers = <WorkManager>[];
-
-  Map<Source, List<Source>> getLibrariesContainingMap =
-      <Source, List<Source>>{};
-
-  Map<Source, bool> shouldErrorsBeAnalyzedMap = <Source, bool>{};
-
-  Map<ResultDescriptor, bool Function(CacheEntry entry, ResultDescriptor)>
-      aboutToComputeResultMap =
-      <ResultDescriptor, bool Function(CacheEntry entry, ResultDescriptor)>{};
-
-  Map<Source, AnalysisErrorInfo> errorsMap = <Source, AnalysisErrorInfo>{};
-
-  Map<Source, ChangeNoticeImpl> _pendingNotices = <Source, ChangeNoticeImpl>{};
-
-  @override
-  final AnalysisOptions analysisOptions = new AnalysisOptionsImpl();
-
-  @override
-  final ReentrantSynchronousStream<InvalidatedResult> onResultInvalidated =
-      new ReentrantSynchronousStream<InvalidatedResult>();
-
-  _InternalAnalysisContextMock() {
-    privateAnalysisCachePartition = new UniversalCachePartition(this);
-    analysisCache = new AnalysisCache([privateAnalysisCachePartition]);
-    analysisCache.onResultInvalidated.listen((InvalidatedResult event) {
-      onResultInvalidated.add(event);
-    });
-  }
-
-  @override
-  bool aboutToComputeResult(CacheEntry entry, ResultDescriptor result) {
-    if (aboutToComputeEverything != null) {
-      return aboutToComputeEverything;
-    }
-    bool Function(CacheEntry entry, ResultDescriptor) function =
-        aboutToComputeResultMap[result];
-    if (function == null) {
-      return false;
-    }
-    return function(entry, result);
-  }
-
-  @override
-  bool exists(Source source) {
-    return everythingExists;
-  }
-
-  @override
-  CacheEntry getCacheEntry(AnalysisTarget target) {
-    CacheEntry entry = analysisCache.get(target);
-    if (entry == null) {
-      entry = new CacheEntry(target);
-      analysisCache.put(entry);
-    }
-    return entry;
-  }
-
-  @override
-  AnalysisErrorInfo getErrors(Source source) => errorsMap[source];
-
-  List<Source> getLibrariesContaining(Source source) {
-    return getLibrariesContainingMap[source];
-  }
-
-  @override
-  ChangeNoticeImpl getNotice(Source source) {
-    return _pendingNotices.putIfAbsent(
-        source, () => new ChangeNoticeImpl(source));
-  }
-
-  @override
-  noSuchMethod(Invocation invocation) {
-    throw new StateError('Unexpected invocation of ${invocation.memberName}');
-  }
-
-  void setShouldErrorsBeAnalyzed(Source source, bool value) {
-    shouldErrorsBeAnalyzedMap[source] = value;
-  }
-
-  @override
-  bool shouldErrorsBeAnalyzed(Source source) {
-    if (analyzeAllErrors != null) {
-      return analyzeAllErrors;
-    }
-    return shouldErrorsBeAnalyzedMap[source];
-  }
-}
-
-class _SourceFactoryMock implements SourceFactory {
-  DartSdk dartSdk;
-
-  @override
-  noSuchMethod(Invocation invocation) {
-    throw new StateError('Unexpected invocation of ${invocation.memberName}');
-  }
-}
-
-class _SourceMock implements Source {
-  @override
-  final String shortName;
-
-  @override
-  bool isInSystemLibrary = false;
-
-  @override
-  Source source;
-
-  _SourceMock(this.shortName);
-
-  @override
-  String get fullName => '/' + shortName;
-
-  @override
-  noSuchMethod(Invocation invocation) {
-    throw new StateError('Unexpected invocation of ${invocation.memberName}');
-  }
-
-  @override
-  String toString() => fullName;
-}
diff --git a/pkg/analyzer/test/src/task/general_test.dart b/pkg/analyzer/test/src/task/general_test.dart
deleted file mode 100644
index e5e3b2b..0000000
--- a/pkg/analyzer/test/src/task/general_test.dart
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (c) 2015, 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 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/task/api/general.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/general.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../../generated/test_support.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(GetContentTaskTest);
-  });
-}
-
-@reflectiveTest
-class GetContentTaskTest extends EngineTestCase {
-  test_buildInputs() {
-    AnalysisTarget target = new TestSource();
-    Map<String, TaskInput> inputs = GetContentTask.buildInputs(target);
-    expect(inputs, isEmpty);
-  }
-
-  test_constructor() {
-    AnalysisContext context = new _MockContext();
-    AnalysisTarget target = new TestSource();
-    GetContentTask task = new GetContentTask(context, target);
-    expect(task, isNotNull);
-    expect(task.context, context);
-    expect(task.target, target);
-  }
-
-  test_createTask() {
-    AnalysisContext context = new _MockContext();
-    AnalysisTarget target = new TestSource();
-    GetContentTask task = GetContentTask.createTask(context, target);
-    expect(task, isNotNull);
-    expect(task.context, context);
-    expect(task.target, target);
-  }
-
-  test_descriptor() {
-    AnalysisContext context = new _MockContext();
-    AnalysisTarget target = new TestSource();
-    GetContentTask task = new GetContentTask(context, target);
-    expect(task.descriptor, GetContentTask.DESCRIPTOR);
-  }
-
-  test_perform() {
-    _MockContext context = new _MockContext();
-    Source target = new TestSource();
-    GetContentTask task = new GetContentTask(context, target);
-    context.getContentsResponse[target] =
-        () => new TimestampedData<String>(42, 'foo');
-    task.perform();
-    expect(task.caughtException, isNull);
-    expect(task.outputs, hasLength(2));
-    expect(task.outputs[CONTENT], 'foo');
-    expect(task.outputs[MODIFICATION_TIME], 42);
-  }
-
-  void test_perform_exception() {
-    _MockContext context = new _MockContext();
-    Source target = new TestSource();
-    GetContentTask task = new GetContentTask(context, target);
-    context.getContentsResponse[target] = () => throw 'My exception!';
-    task.perform();
-    expect(task.caughtException, isNull);
-    expect(task.outputs, hasLength(2));
-    expect(task.outputs[CONTENT], '');
-    expect(task.outputs[MODIFICATION_TIME], -1);
-  }
-}
-
-class _MockContext implements AnalysisContext {
-  Map<Source, TimestampedData<String> Function()> getContentsResponse =
-      <Source, TimestampedData<String> Function()>{};
-
-  String get name => 'mock';
-
-  @override
-  TimestampedData<String> getContents(Source source) {
-    TimestampedData<String> Function() response = getContentsResponse[source];
-    if (response == null) {
-      fail('Unexpected invocation of getContents');
-    }
-    return response();
-  }
-
-  @override
-  noSuchMethod(Invocation invocation) {
-    fail('Unexpected invocation of ${invocation.memberName}');
-  }
-}
diff --git a/pkg/analyzer/test/src/task/inputs_test.dart b/pkg/analyzer/test/src/task/inputs_test.dart
deleted file mode 100644
index c8963d3..0000000
--- a/pkg/analyzer/test/src/task/inputs_test.dart
+++ /dev/null
@@ -1,1073 +0,0 @@
-// Copyright (c) 2015, 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 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/inputs.dart';
-import 'package:analyzer/src/task/model.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../../generated/test_support.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(ConstantTaskInputBuilderTest);
-    defineReflectiveTests(ConstantTaskInputTest);
-    defineReflectiveTests(ListTaskInputImplTest);
-    defineReflectiveTests(ListToListTaskInputTest);
-    defineReflectiveTests(ListToListTaskInputBuilderTest);
-    defineReflectiveTests(ListToMapTaskInputBuilderTest);
-    defineReflectiveTests(ListToMapTaskInputTest);
-    defineReflectiveTests(ObjectToListTaskInputBuilderTest);
-    defineReflectiveTests(ObjectToListTaskInputTest);
-    defineReflectiveTests(SimpleTaskInputTest);
-    defineReflectiveTests(SimpleTaskInputBuilderTest);
-    defineReflectiveTests(TopLevelTaskInputBuilderTest);
-  });
-}
-
-@reflectiveTest
-class ConstantTaskInputBuilderTest extends EngineTestCase {
-  static final int value = 7;
-  static final ConstantTaskInput<int> input = new ConstantTaskInput<int>(value);
-
-  ConstantTaskInputBuilder builder;
-
-  void setUp() {
-    super.setUp();
-    builder = new ConstantTaskInputBuilder(input);
-  }
-
-  test_create() {
-    expect(builder, isNotNull);
-    expect(builder.input, input);
-  }
-
-  test_currentResult_afterOneMoveNext() {
-    builder.moveNext();
-    expect(builder.currentResult, null);
-  }
-
-  test_currentResult_beforeMoveNext() {
-    expect(builder.currentResult, null);
-  }
-
-  test_currentTarget_afterOneMoveNext() {
-    builder.moveNext();
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentTarget_beforeMoveNext() {
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentValue_afterOneMoveNext() {
-    builder.moveNext();
-    expect(() {
-      builder.currentValue = 'value';
-    }, throwsStateError);
-  }
-
-  test_currentValue_beforeMoveNext() {
-    expect(() {
-      builder.currentValue = 'value';
-    }, throwsStateError);
-  }
-
-  test_currentValueNotAvailable_afterOneMoveNext() {
-    builder.moveNext();
-    expect(() {
-      builder.currentValueNotAvailable();
-    }, throwsStateError);
-  }
-
-  test_currentValueNotAvailable_beforeMoveNext() {
-    expect(() {
-      builder.currentValueNotAvailable();
-    }, throwsStateError);
-  }
-
-  test_inputValue_afterOneMoveNext() {
-    builder.moveNext();
-    expect(builder.inputValue, value);
-  }
-
-  test_inputValue_beforeMoveNext() {
-    expect(builder.inputValue, value);
-  }
-
-  test_moveNext() {
-    expect(builder.moveNext(), false);
-    expect(builder.moveNext(), false);
-  }
-}
-
-@reflectiveTest
-class ConstantTaskInputTest extends EngineTestCase {
-  test_create() {
-    int value = 3;
-    ConstantTaskInput<int> input = new ConstantTaskInput<int>(value);
-    expect(input, isNotNull);
-    expect(input.value, value);
-  }
-
-  test_createBuilder() {
-    ConstantTaskInput<int> input = new ConstantTaskInput<int>(5);
-    expect(input.createBuilder(), new TypeMatcher<ConstantTaskInputBuilder>());
-  }
-}
-
-@reflectiveTest
-class ListTaskInputImplTest extends EngineTestCase {
-  static final AnalysisTarget target = new TestSource();
-  static final ResultDescriptor<List<AnalysisTarget>> result1 =
-      new ResultDescriptorImpl<List<AnalysisTarget>>('result1', null);
-  static final result2 = new ResultDescriptorImpl<int>('result2', null);
-
-  test_create() {
-    var input = new ListTaskInputImpl<AnalysisTarget>(target, result1);
-    expect(input, isNotNull);
-    expect(input.target, target);
-    expect(input.result, result1);
-  }
-
-  test_createBuilder() {
-    var input = new ListTaskInputImpl<AnalysisTarget>(target, result1);
-    expect(input.createBuilder(), new TypeMatcher<SimpleTaskInputBuilder>());
-  }
-
-  test_toList() {
-    var input = new ListTaskInputImpl<AnalysisTarget>(target, result1);
-    ListTaskInput<String> input2 =
-        input.toList((target) => new SimpleTaskInput<String>(target, null));
-    expect(
-        input2, new TypeMatcher<ListToListTaskInput<AnalysisTarget, String>>());
-  }
-
-  test_toListOf() {
-    var input = new ListTaskInputImpl<AnalysisTarget>(target, result1);
-    ListTaskInput<int> input2 = input.toListOf(result2);
-    expect(input2, new TypeMatcher<ListToListTaskInput<AnalysisTarget, int>>());
-  }
-
-  test_toMap() {
-    var input = new ListTaskInputImpl<AnalysisTarget>(target, result1);
-    MapTaskInput<AnalysisTarget, String> input2 =
-        input.toMap((target) => new SimpleTaskInput<String>(target, null));
-    expect(
-        input2, new TypeMatcher<ListToMapTaskInput<AnalysisTarget, String>>());
-  }
-
-  test_toMapOf() {
-    var input = new ListTaskInputImpl<AnalysisTarget>(target, result1);
-    MapTaskInput<AnalysisTarget, int> input2 = input.toMapOf(result2);
-    expect(input2, new TypeMatcher<ListToMapTaskInput<AnalysisTarget, int>>());
-  }
-}
-
-@reflectiveTest
-class ListToListTaskInputBuilderTest extends EngineTestCase {
-  static final AnalysisTarget target1 = new TestSource();
-  static final ResultDescriptorImpl<List> result1 =
-      new ResultDescriptorImpl<List>('result1', null);
-  static final ResultDescriptorImpl result2 =
-      new ResultDescriptorImpl('result2', null);
-  static final ListToListTaskInput input = new ListToListTaskInput(
-      result1.of(target1), (element) => result2.of(element));
-
-  test_create() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    expect(builder, isNotNull);
-    expect(builder.input, input);
-  }
-
-  test_currentResult_afterComplete() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    builder.moveNext();
-    builder.currentValue = [];
-    builder.moveNext();
-    expect(builder.currentResult, null);
-  }
-
-  test_currentResult_afterCurrentValueNotAvailable() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-    builder.moveNext();
-    expect(builder.currentResult, null);
-  }
-
-  test_currentResult_afterOneMoveNext() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    builder.moveNext();
-    expect(builder.currentResult, result1);
-  }
-
-  test_currentResult_beforeMoveNext() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    expect(builder.currentResult, null);
-  }
-
-  test_currentTarget_afterComplete() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    builder.moveNext();
-    builder.currentValue = [];
-    builder.moveNext();
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentTarget_afterCurrentValueNotAvailable() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-    builder.moveNext();
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentTarget_afterOneMoveNext() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    builder.moveNext();
-    expect(builder.currentTarget, target1);
-  }
-
-  test_currentTarget_beforeMoveNext() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentValue_afterOneMoveNext() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    builder.moveNext();
-    builder.currentValue = [];
-  }
-
-  test_currentValue_beforeMoveNext() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    expect(() {
-      builder.currentValue = [];
-    }, throwsStateError);
-  }
-
-  test_currentValueNotAvailable_afterOneMoveNext() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-  }
-
-  test_currentValueNotAvailable_beforeMoveNext() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    expect(() {
-      builder.currentValueNotAvailable();
-    }, throwsStateError);
-  }
-
-  test_inputValue_afterComplete() {
-    AnalysisTarget target2 = new TestSource();
-    AnalysisTarget target3 = new TestSource();
-    String value2 = 'value2';
-    String value3 = 'value3';
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    builder.moveNext(); // Advance to requesting the list
-    builder.currentValue = [target2, target3];
-    builder.moveNext(); // Advance to requesting result2 for target2
-    builder.currentValue = value2;
-    builder.moveNext(); // Advance to requesting result2 for target3
-    builder.currentValue = value3;
-    builder.moveNext(); // Advance to the end
-    var inputValue = builder.inputValue;
-    expect(inputValue, new TypeMatcher<List>());
-    List list = inputValue;
-    expect(list.length, 2);
-    expect(list[0], value2);
-    expect(list[1], value3);
-  }
-
-  test_inputValue_afterFirstValueNotAvailable() {
-    AnalysisTarget target2 = new TestSource();
-    AnalysisTarget target3 = new TestSource();
-    String value3 = 'value3';
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    builder.moveNext(); // Advance to requesting the list
-    builder.currentValue = [target2, target3];
-    builder.moveNext(); // Advance to requesting result2 for target2
-    builder.currentValueNotAvailable();
-    builder.moveNext(); // Advance to requesting result2 for target3
-    builder.currentValue = value3;
-    builder.moveNext(); // Advance to the end
-    var inputValue = builder.inputValue;
-    expect(inputValue, new TypeMatcher<List>());
-    List list = inputValue;
-    expect(list, orderedEquals([value3]));
-  }
-
-  test_inputValue_afterListNotAvailable() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    builder.moveNext(); // Advance to requesting the list
-    builder.currentValueNotAvailable();
-    builder.moveNext(); // Advance to the end
-    var inputValue = builder.inputValue;
-    expect(inputValue, new TypeMatcher<List>());
-    List list = inputValue;
-    expect(list, isEmpty);
-  }
-
-  test_inputValue_afterOneMoveNext() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    builder.moveNext();
-    expect(() => builder.inputValue, throwsStateError);
-  }
-
-  test_inputValue_beforeMoveNext() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    expect(() => builder.inputValue, throwsStateError);
-  }
-
-  test_moveNext_withoutSet() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    expect(builder.moveNext(), true);
-    expect(() => builder.moveNext(), throwsStateError);
-  }
-
-  test_moveNext_withSet() {
-    ListToListTaskInputBuilder builder = new ListToListTaskInputBuilder(input);
-    expect(builder.moveNext(), true);
-    builder.currentValue = [];
-    expect(builder.moveNext(), false);
-    expect(builder.moveNext(), false);
-  }
-}
-
-@reflectiveTest
-class ListToListTaskInputTest extends EngineTestCase {
-  static final AnalysisTarget target = new TestSource();
-  static final ResultDescriptorImpl<List> result =
-      new ResultDescriptorImpl<List>('result', null);
-
-  test_create() {
-    SimpleTaskInput<List> baseAccessor = result.of(target);
-    GenerateTaskInputs generate = (object) => null;
-    ListToListTaskInput input = new ListToListTaskInput(baseAccessor, generate);
-    expect(input, isNotNull);
-    expect(input.baseAccessor, baseAccessor);
-    expect(input.generateTaskInputs, equals(generate));
-  }
-
-  test_createBuilder() {
-    SimpleTaskInput<List> baseAccessor = result.of(target);
-    GenerateTaskInputs generate = (object) => null;
-    ListToListTaskInput input = new ListToListTaskInput(baseAccessor, generate);
-    expect(input.createBuilder(), isNotNull);
-  }
-}
-
-@reflectiveTest
-class ListToMapTaskInputBuilderTest extends EngineTestCase {
-  static final AnalysisTarget target1 = new TestSource('target1');
-  static final ResultDescriptorImpl<List> result1 =
-      new ResultDescriptorImpl<List>('result1', null);
-  static final ResultDescriptorImpl result2 =
-      new ResultDescriptorImpl('result2', null);
-  static final ListToMapTaskInput input = new ListToMapTaskInput(
-      result1.of(target1), (element) => result2.of(element));
-
-  test_create() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    expect(builder, isNotNull);
-    expect(builder.input, input);
-  }
-
-  test_currentResult_afterComplete() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    builder.moveNext();
-    builder.currentValue = [];
-    builder.moveNext();
-    expect(builder.currentResult, null);
-  }
-
-  test_currentResult_afterCurrentValueNotAvailable() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-    builder.moveNext();
-    expect(builder.currentResult, null);
-  }
-
-  test_currentResult_afterOneMoveNext() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    builder.moveNext();
-    expect(builder.currentResult, result1);
-  }
-
-  test_currentResult_beforeMoveNext() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    expect(builder.currentResult, null);
-  }
-
-  test_currentTarget_afterComplete() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    builder.moveNext();
-    builder.currentValue = [];
-    builder.moveNext();
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentTarget_afterCurrentValueNotAvailable() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-    builder.moveNext();
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentTarget_afterOneMoveNext() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    builder.moveNext();
-    expect(builder.currentTarget, target1);
-  }
-
-  test_currentTarget_beforeMoveNext() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentValue_afterOneMoveNext() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    builder.moveNext();
-    builder.currentValue = [];
-  }
-
-  test_currentValue_beforeMoveNext() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    expect(() {
-      builder.currentValue = [];
-    }, throwsStateError);
-  }
-
-  test_currentValueNotAvailable_afterOneMoveNext() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-  }
-
-  test_currentValueNotAvailable_beforeMoveNext() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    expect(() {
-      builder.currentValueNotAvailable();
-    }, throwsStateError);
-  }
-
-  test_inputValue_afterComplete() {
-    AnalysisTarget target2 = new TestSource('target2');
-    AnalysisTarget target3 = new TestSource('target3');
-    String value2 = 'value2';
-    String value3 = 'value3';
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    builder.moveNext(); // Advance to requesting the list
-    builder.currentValue = [target2, target3];
-    builder.moveNext(); // Advance to requesting result2 for target2
-    builder.currentValue = value2;
-    builder.moveNext(); // Advance to requesting result2 for target3
-    builder.currentValue = value3;
-    builder.moveNext(); // Advance to the end
-    var inputValue = builder.inputValue;
-    expect(inputValue, new TypeMatcher<Map>());
-    expect(inputValue.length, 2);
-    expect(inputValue, containsPair(target2, value2));
-    expect(inputValue, containsPair(target3, value3));
-  }
-
-  test_inputValue_afterFirstValueNotAvailable() {
-    AnalysisTarget target2 = new TestSource('target2');
-    AnalysisTarget target3 = new TestSource('target3');
-    String value3 = 'value3';
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    builder.moveNext(); // Advance to requesting the list
-    builder.currentValue = [target2, target3];
-    builder.moveNext(); // Advance to requesting result2 for target2
-    builder.currentValueNotAvailable();
-    builder.moveNext(); // Advance to requesting result2 for target3
-    builder.currentValue = value3;
-    builder.moveNext(); // Advance to the end
-    var inputValue = builder.inputValue;
-    expect(inputValue, new TypeMatcher<Map>());
-    expect(inputValue, hasLength(1));
-    expect(inputValue, containsPair(target3, value3));
-  }
-
-  test_inputValue_afterListNotAvailable() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    builder.moveNext(); // Advance to requesting the list
-    builder.currentValueNotAvailable();
-    builder.moveNext(); // Advance to the end
-    var inputValue = builder.inputValue;
-    expect(inputValue, new TypeMatcher<Map>());
-    expect(inputValue, isEmpty);
-  }
-
-  test_inputValue_afterOneMoveNext() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    builder.moveNext();
-    expect(() => builder.inputValue, throwsStateError);
-  }
-
-  test_inputValue_beforeMoveNext() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    expect(() => builder.inputValue, throwsStateError);
-  }
-
-  test_moveNext_withoutSet() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    expect(builder.moveNext(), true);
-    expect(() => builder.moveNext(), throwsStateError);
-  }
-
-  test_moveNext_withSet() {
-    ListToMapTaskInputBuilder builder = new ListToMapTaskInputBuilder(input);
-    expect(builder.moveNext(), true);
-    builder.currentValue = [];
-    expect(builder.moveNext(), false);
-    expect(builder.moveNext(), false);
-  }
-}
-
-@reflectiveTest
-class ListToMapTaskInputTest extends EngineTestCase {
-  static final AnalysisTarget target = new TestSource();
-  static final ResultDescriptorImpl<List> result =
-      new ResultDescriptorImpl<List>('result', null);
-
-  test_create() {
-    SimpleTaskInput<List> baseAccessor = result.of(target);
-    GenerateTaskInputs generate = (object) => null;
-    ListToMapTaskInput input = new ListToMapTaskInput(baseAccessor, generate);
-    expect(input, isNotNull);
-    expect(input.baseAccessor, baseAccessor);
-    expect(input.generateTaskInputs, equals(generate));
-  }
-
-  test_createBuilder() {
-    SimpleTaskInput<List> baseAccessor = result.of(target);
-    GenerateTaskInputs generate = (object) => null;
-    ListToMapTaskInput input = new ListToMapTaskInput(baseAccessor, generate);
-    expect(input.createBuilder(), isNotNull);
-  }
-}
-
-@reflectiveTest
-class ObjectToListTaskInputBuilderTest {
-  static final AnalysisTarget target = new TestSource();
-  static final ResultDescriptorImpl result =
-      new ResultDescriptorImpl('result', null);
-  static final SimpleTaskInput baseInput = new SimpleTaskInput(target, result);
-  static final mapper = (Object x) => [x];
-  static final ObjectToListTaskInput input =
-      new ObjectToListTaskInput(baseInput, mapper);
-
-  ObjectToListTaskInputBuilder builder;
-
-  void setUp() {
-    builder = new ObjectToListTaskInputBuilder(input);
-  }
-
-  test_create() {
-    expect(builder, isNotNull);
-    expect(builder.input, input);
-  }
-
-  test_currentResult_afterComplete() {
-    builder.moveNext();
-    builder.currentValue = 'value';
-    builder.moveNext();
-    expect(builder.currentResult, null);
-  }
-
-  test_currentResult_afterCurrentValueNotAvailable() {
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-    builder.moveNext();
-    expect(builder.currentResult, null);
-  }
-
-  test_currentResult_afterOneMoveNext() {
-    builder.moveNext();
-    expect(builder.currentResult, result);
-  }
-
-  test_currentResult_beforeMoveNext() {
-    expect(builder.currentResult, null);
-  }
-
-  test_currentTarget_afterComplete() {
-    builder.moveNext();
-    builder.currentValue = 'value';
-    builder.moveNext();
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentTarget_afterCurrentValueNotAvailable() {
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-    builder.moveNext();
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentTarget_afterOneMoveNext() {
-    builder.moveNext();
-    expect(builder.currentTarget, target);
-  }
-
-  test_currentTarget_beforeMoveNext() {
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentValue_afterOneMoveNext() {
-    builder.moveNext();
-    builder.currentValue = 'value';
-  }
-
-  test_currentValue_beforeMoveNext() {
-    expect(() {
-      builder.currentValue = 'value';
-    }, throwsStateError);
-  }
-
-  test_currentValueNotAvailable_afterOneMoveNext() {
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-  }
-
-  test_currentValueNotAvailable_beforeMoveNext() {
-    expect(() {
-      builder.currentValueNotAvailable();
-    }, throwsStateError);
-  }
-
-  test_inputValue_afterComplete() {
-    builder.moveNext();
-    String value = 'value';
-    builder.currentValue = value;
-    builder.moveNext();
-    expect(builder.inputValue, [value]);
-  }
-
-  test_inputValue_afterCurrentValueNotAvailable() {
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-    builder.moveNext();
-    expect(builder.inputValue, [null]);
-  }
-
-  test_inputValue_afterOneMoveNext() {
-    builder.moveNext();
-    expect(() => builder.inputValue, throwsStateError);
-  }
-
-  test_inputValue_beforeMoveNext() {
-    expect(() => builder.inputValue, throwsStateError);
-  }
-
-  test_moveNext_withoutSet() {
-    expect(builder.moveNext(), true);
-    expect(() => builder.moveNext(), throwsStateError);
-  }
-
-  test_moveNext_withSet() {
-    expect(builder.moveNext(), true);
-    builder.currentValue = 'value';
-    expect(builder.moveNext(), false);
-    expect(builder.moveNext(), false);
-  }
-}
-
-@reflectiveTest
-class ObjectToListTaskInputTest extends EngineTestCase {
-  static final AnalysisTarget target = new TestSource();
-  static final ResultDescriptorImpl result =
-      new ResultDescriptorImpl('result', null);
-
-  test_create() {
-    SimpleTaskInput baseInput = new SimpleTaskInput(target, result);
-    var mapper = (Object x) => [x];
-    ObjectToListTaskInput input = new ObjectToListTaskInput(baseInput, mapper);
-    expect(input, isNotNull);
-    expect(input.baseInput, baseInput);
-    expect(input.mapper, equals(mapper));
-  }
-
-  test_createBuilder() {
-    SimpleTaskInput baseInput = new SimpleTaskInput(target, result);
-    var mapper = (Object x) => [x];
-    ObjectToListTaskInput input = new ObjectToListTaskInput(baseInput, mapper);
-    expect(
-        input.createBuilder(), new TypeMatcher<ObjectToListTaskInputBuilder>());
-  }
-}
-
-@reflectiveTest
-class SimpleTaskInputBuilderTest {
-  static final AnalysisTarget target = new TestSource();
-  static final ResultDescriptorImpl result =
-      new ResultDescriptorImpl('result', null);
-  static final SimpleTaskInput input = new SimpleTaskInput(target, result);
-
-  SimpleTaskInputBuilder builder;
-
-  void setUp() {
-    builder = new SimpleTaskInputBuilder(input);
-  }
-
-  test_create() {
-    expect(builder, isNotNull);
-    expect(builder.input, input);
-  }
-
-  test_currentResult_afterComplete() {
-    builder.moveNext();
-    builder.currentValue = 'value';
-    builder.moveNext();
-    expect(builder.currentResult, null);
-  }
-
-  test_currentResult_afterCurrentValueNotAvailable() {
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-    builder.moveNext();
-    expect(builder.currentResult, null);
-  }
-
-  test_currentResult_afterOneMoveNext() {
-    builder.moveNext();
-    expect(builder.currentResult, result);
-  }
-
-  test_currentResult_beforeMoveNext() {
-    expect(builder.currentResult, null);
-  }
-
-  test_currentTarget_afterComplete() {
-    builder.moveNext();
-    builder.currentValue = 'value';
-    builder.moveNext();
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentTarget_afterCurrentValueNotAvailable() {
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-    builder.moveNext();
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentTarget_afterOneMoveNext() {
-    builder.moveNext();
-    expect(builder.currentTarget, target);
-  }
-
-  test_currentTarget_beforeMoveNext() {
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentValue_afterOneMoveNext() {
-    builder.moveNext();
-    builder.currentValue = 'value';
-  }
-
-  test_currentValue_beforeMoveNext() {
-    expect(() {
-      builder.currentValue = 'value';
-    }, throwsStateError);
-  }
-
-  test_currentValueNotAvailable_afterOneMoveNext() {
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-  }
-
-  test_currentValueNotAvailable_beforeMoveNext() {
-    expect(() {
-      builder.currentValueNotAvailable();
-    }, throwsStateError);
-  }
-
-  test_inputValue_afterComplete() {
-    builder.moveNext();
-    String value = 'value';
-    builder.currentValue = value;
-    builder.moveNext();
-    expect(builder.inputValue, value);
-  }
-
-  test_inputValue_afterCurrentValueNotAvailable() {
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-    builder.moveNext();
-    expect(builder.inputValue, isNull);
-  }
-
-  test_inputValue_afterOneMoveNext() {
-    builder.moveNext();
-    expect(() => builder.inputValue, throwsStateError);
-  }
-
-  test_inputValue_beforeMoveNext() {
-    expect(() => builder.inputValue, throwsStateError);
-  }
-
-  test_moveNext_withoutSet() {
-    expect(builder.moveNext(), true);
-    expect(() => builder.moveNext(), throwsStateError);
-  }
-
-  test_moveNext_withSet() {
-    expect(builder.moveNext(), true);
-    builder.currentValue = 'value';
-    expect(builder.moveNext(), false);
-    expect(builder.moveNext(), false);
-  }
-}
-
-@reflectiveTest
-class SimpleTaskInputTest extends EngineTestCase {
-  static final AnalysisTarget target = new TestSource();
-  static final ResultDescriptorImpl result =
-      new ResultDescriptorImpl('result', null);
-
-  test_create() {
-    SimpleTaskInput input = new SimpleTaskInput(target, result);
-    expect(input, isNotNull);
-    expect(input.target, target);
-    expect(input.result, result);
-  }
-
-  test_createBuilder() {
-    SimpleTaskInput input = new SimpleTaskInput(target, result);
-    expect(input.createBuilder(), new TypeMatcher<SimpleTaskInputBuilder>());
-  }
-}
-
-@reflectiveTest
-class TopLevelTaskInputBuilderTest extends EngineTestCase {
-  static final AnalysisTarget target = new TestSource();
-  static final ResultDescriptorImpl result1 =
-      new ResultDescriptorImpl('result1', null);
-  static final ResultDescriptorImpl result2 =
-      new ResultDescriptorImpl('result2', null);
-  static final SimpleTaskInput input1 = new SimpleTaskInput(target, result1);
-  static final SimpleTaskInput input2 = new SimpleTaskInput(target, result2);
-
-  test_create() {
-    Map<String, TaskInput> inputDescriptors = {};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    expect(builder, isNotNull);
-    expect(builder.inputDescriptors, inputDescriptors);
-  }
-
-  test_currentResult_afterComplete() {
-    Map<String, TaskInput> inputDescriptors = {'one': input1};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    builder.moveNext();
-    builder.currentValue = 'value1';
-    builder.moveNext();
-    expect(builder.currentResult, null);
-  }
-
-  test_currentResult_afterCurrentValueNotAvailable() {
-    Map<String, TaskInput> inputDescriptors = {'one': input1};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-    builder.moveNext();
-    expect(builder.currentResult, null);
-  }
-
-  test_currentResult_afterOneMoveNext() {
-    Map<String, TaskInput> inputDescriptors = {'one': input1, 'two': input2};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    builder.moveNext();
-    expect(builder.currentResult, result1);
-  }
-
-  test_currentResult_afterTwoMoveNext_withConstantInput() {
-    ConstantTaskInput<int> constantInput = new ConstantTaskInput<int>(11);
-    Map<String, TaskInput> inputDescriptors = <String, TaskInput>{
-      'one': input1,
-      'constant': constantInput,
-      'two': input2
-    };
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    builder.moveNext();
-    builder.currentValue = 'value1';
-    builder.moveNext();
-    expect(builder.currentResult, result2);
-  }
-
-  test_currentResult_beforeMoveNext() {
-    Map<String, TaskInput> inputDescriptors = {};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    expect(builder.currentResult, null);
-  }
-
-  test_currentTarget_afterComplete() {
-    Map<String, TaskInput> inputDescriptors = {'one': input1};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    builder.moveNext();
-    builder.currentValue = 'value1';
-    builder.moveNext();
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentTarget_afterCurrentValueNotAvailable() {
-    Map<String, TaskInput> inputDescriptors = {'one': input1};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-    builder.moveNext();
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentTarget_afterOneMoveNext() {
-    Map<String, TaskInput> inputDescriptors = {'one': input1};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    builder.moveNext();
-    expect(builder.currentTarget, target);
-  }
-
-  test_currentTarget_afterTwoMoveNext_withConstantInput() {
-    ConstantTaskInput<int> constantInput = new ConstantTaskInput<int>(11);
-    Map<String, TaskInput> inputDescriptors = <String, TaskInput>{
-      'one': input1,
-      'constant': constantInput,
-      'two': input2
-    };
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    builder.moveNext();
-    builder.currentValue = 'value1';
-    builder.moveNext();
-    expect(builder.currentTarget, target);
-  }
-
-  test_currentTarget_beforeMoveNext() {
-    Map<String, TaskInput> inputDescriptors = {};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    expect(builder.currentTarget, null);
-  }
-
-  test_currentValue_afterOneMoveNext() {
-    Map<String, TaskInput> inputDescriptors = {'one': input1};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    builder.moveNext();
-    builder.currentValue = 'value1';
-  }
-
-  test_currentValue_beforeMoveNext() {
-    Map<String, TaskInput> inputDescriptors = {'one': input1};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    expect(() {
-      builder.currentValue = 'value1';
-    }, throwsStateError);
-  }
-
-  test_currentValueNotAvailable_afterOneMoveNext() {
-    Map<String, TaskInput> inputDescriptors = {'one': input1};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    builder.moveNext();
-    builder.currentValueNotAvailable();
-  }
-
-  test_currentValueNotAvailable_beforeMoveNext() {
-    Map<String, TaskInput> inputDescriptors = {'one': input1};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    expect(() {
-      builder.currentValueNotAvailable();
-    }, throwsStateError);
-  }
-
-  test_inputValue_afterComplete() {
-    String key1 = 'one';
-    String key2 = 'two';
-    String value1 = 'value1';
-    String value2 = 'value2';
-    Map<String, TaskInput> inputDescriptors = {key1: input1, key2: input2};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    builder.moveNext(); // Advance to requesting result1 for target
-    builder.currentValue = value1;
-    builder.moveNext(); // Advance to requesting result2 for target
-    builder.currentValue = value2;
-    builder.moveNext(); // Advance to the end
-    var inputValue = builder.inputValue;
-    expect(inputValue, new TypeMatcher<Map>());
-    Map inputs = inputValue;
-    expect(inputs.length, 2);
-    expect(inputs, containsPair(key1, value1));
-    expect(inputs, containsPair(key2, value2));
-  }
-
-  test_inputValue_afterOneMoveNext() {
-    Map<String, TaskInput> inputDescriptors = {'one': input1};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    builder.moveNext();
-    expect(() => builder.inputValue, throwsStateError);
-  }
-
-  test_inputValue_afterOneValueNotAvailable() {
-    String key1 = 'one';
-    String key2 = 'two';
-    String value2 = 'value2';
-    Map<String, TaskInput> inputDescriptors = {key1: input1, key2: input2};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    builder.moveNext(); // Advance to requesting result1 for target
-    builder.currentValueNotAvailable();
-    builder.moveNext(); // Advance to requesting result2 for target
-    builder.currentValue = value2;
-    builder.moveNext(); // Advance to the end
-    var inputValue = builder.inputValue;
-    expect(inputValue, new TypeMatcher<Map>());
-    Map inputs = inputValue;
-    expect(inputs, hasLength(1));
-    expect(inputs, containsPair(key2, value2));
-  }
-
-  test_inputValue_beforeMoveNext() {
-    Map<String, TaskInput> inputDescriptors = {};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    expect(() => builder.inputValue, throwsStateError);
-  }
-
-  test_moveNext_withoutSet() {
-    Map<String, TaskInput> inputDescriptors = {'one': input1};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    expect(builder.moveNext(), true);
-    expect(() => builder.moveNext(), throwsStateError);
-  }
-
-  test_moveNext_withSet() {
-    Map<String, TaskInput> inputDescriptors = {'one': input1};
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    expect(builder.moveNext(), true);
-    builder.currentValue = 'value1';
-    expect(builder.moveNext(), false);
-    expect(builder.moveNext(), false);
-  }
-}
diff --git a/pkg/analyzer/test/src/task/manager_test.dart b/pkg/analyzer/test/src/task/manager_test.dart
deleted file mode 100644
index b91e829..0000000
--- a/pkg/analyzer/test/src/task/manager_test.dart
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright (c) 2015, 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 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/manager.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../../generated/test_support.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(TaskManagerTest);
-  });
-}
-
-@reflectiveTest
-class TaskManagerTest extends EngineTestCase {
-  static final ResultDescriptor result1 = new ResultDescriptor('result1', null);
-  static final ResultDescriptor result2 = new ResultDescriptor('result2', null);
-
-  test_addGeneralResult() {
-    TaskManager manager = new TaskManager();
-    manager.addGeneralResult(result1);
-    Set<ResultDescriptor> results = manager.generalResults;
-    expect(results, unorderedEquals([result1]));
-  }
-
-  test_addPriorityResult() {
-    TaskManager manager = new TaskManager();
-    manager.addPriorityResult(result1);
-    Set<ResultDescriptor> results = manager.priorityResults;
-    expect(results, unorderedEquals([result1]));
-  }
-
-  test_addTaskDescriptor() {
-    TaskManager manager = new TaskManager();
-    TaskDescriptor descriptor =
-        new TaskDescriptor('task', null, null, [result1]);
-    manager.addTaskDescriptor(descriptor);
-    expect(manager.taskMap.length, 1);
-  }
-
-  test_constructor() {
-    TaskManager manager = new TaskManager();
-    expect(manager, isNotNull);
-    expect(manager.generalResults, isEmpty);
-    expect(manager.priorityResults, isEmpty);
-  }
-
-  test_findTask_defined() {
-    TaskManager manager = new TaskManager();
-    TaskDescriptor descriptor =
-        new TaskDescriptor('task', null, null, [result1]);
-    manager.addTaskDescriptor(descriptor);
-    AnalysisTarget target = new TestSource();
-    expect(manager.findTask(target, result1), descriptor);
-  }
-
-  test_findTask_empty() {
-    TaskManager manager = new TaskManager();
-    AnalysisTarget target = new TestSource();
-    expect(() => manager.findTask(target, result1),
-        throwsA(new TypeMatcher<AnalysisException>()));
-  }
-
-  test_findTask_multiple() {
-    TaskManager manager = new TaskManager();
-    TaskDescriptor descriptor1 =
-        new TaskDescriptor('task1', null, null, [result1]);
-    manager.addTaskDescriptor(descriptor1);
-    TaskDescriptor descriptor2 =
-        new TaskDescriptor('task2', null, null, [result1]);
-    manager.addTaskDescriptor(descriptor2);
-    TaskDescriptor descriptor3 =
-        new TaskDescriptor('task3', null, null, [result2]);
-    manager.addTaskDescriptor(descriptor3);
-
-    AnalysisTarget target = new TestSource();
-    TaskDescriptor task = manager.findTask(target, result1);
-    expect(task == descriptor1 || task == descriptor2, true);
-  }
-
-  test_findTask_undefined() {
-    TaskManager manager = new TaskManager();
-    TaskDescriptor descriptor =
-        new TaskDescriptor('task', null, null, [result1]);
-    manager.addTaskDescriptor(descriptor);
-    AnalysisTarget target = new TestSource();
-    expect(() => manager.findTask(target, result2),
-        throwsA(new TypeMatcher<AnalysisException>()));
-  }
-
-  test_removeGeneralResult_absent() {
-    TaskManager manager = new TaskManager();
-    manager.addGeneralResult(result1);
-    Set<ResultDescriptor> results = manager.generalResults;
-    expect(results, unorderedEquals([result1]));
-  }
-
-  test_removeGeneralResult_present() {
-    TaskManager manager = new TaskManager();
-    manager.addGeneralResult(result1);
-    manager.addGeneralResult(result2);
-    Set<ResultDescriptor> results = manager.generalResults;
-    expect(results, unorderedEquals([result1, result2]));
-    manager.removeGeneralResult(result1);
-    expect(results, unorderedEquals([result2]));
-  }
-
-  test_removePriorityResult_absent() {
-    TaskManager manager = new TaskManager();
-    manager.addPriorityResult(result1);
-    manager.removePriorityResult(result2);
-    Set<ResultDescriptor> results = manager.priorityResults;
-    expect(results, unorderedEquals([result1]));
-  }
-
-  test_removePriorityResult_present() {
-    TaskManager manager = new TaskManager();
-    manager.addPriorityResult(result1);
-    manager.addPriorityResult(result2);
-    Set<ResultDescriptor> results = manager.priorityResults;
-    expect(results, unorderedEquals([result1, result2]));
-    manager.removePriorityResult(result1);
-    expect(results, unorderedEquals([result2]));
-  }
-}
diff --git a/pkg/analyzer/test/src/task/model_test.dart b/pkg/analyzer/test/src/task/model_test.dart
deleted file mode 100644
index 65b78ca..0000000
--- a/pkg/analyzer/test/src/task/model_test.dart
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright (c) 2015, 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 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/model.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../../generated/test_support.dart';
-import 'test_support.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(AnalysisTaskTest);
-    defineReflectiveTests(ResultDescriptorImplTest);
-    defineReflectiveTests(SimpleResultCachingPolicyTest);
-    defineReflectiveTests(TaskDescriptorImplTest);
-  });
-}
-
-@reflectiveTest
-class AnalysisTaskTest extends EngineTestCase {
-  test_getRequiredInput_missingKey() {
-    AnalysisTarget target = new TestSource();
-    AnalysisTask task = new TestAnalysisTask(null, target);
-    task.inputs = {'a': 'b'};
-    expect(() => task.getRequiredInput('c'),
-        throwsA(new TypeMatcher<AnalysisException>()));
-  }
-
-  test_getRequiredInput_noInputs() {
-    AnalysisTarget target = new TestSource();
-    AnalysisTask task = new TestAnalysisTask(null, target);
-    expect(() => task.getRequiredInput('x'),
-        throwsA(new TypeMatcher<AnalysisException>()));
-  }
-
-  test_getRequiredInput_valid() {
-    AnalysisTarget target = new TestSource();
-    AnalysisTask task = new TestAnalysisTask(null, target);
-    String key = 'a';
-    String value = 'b';
-    task.inputs = {key: value};
-    expect(task.getRequiredInput(key), value);
-  }
-
-  test_getRequiredSource() {
-    AnalysisTarget target = new TestSource();
-    AnalysisTask task = new TestAnalysisTask(null, target);
-    expect(task.getRequiredSource(), target);
-  }
-}
-
-@reflectiveTest
-class ResultDescriptorImplTest extends EngineTestCase {
-  test_create_withCachingPolicy() {
-    ResultCachingPolicy policy = new SimpleResultCachingPolicy(128, 16);
-    ResultDescriptorImpl result =
-        new ResultDescriptorImpl('result', null, cachingPolicy: policy);
-    expect(result.cachingPolicy, same(policy));
-  }
-
-  test_create_withoutCachingPolicy() {
-    ResultDescriptorImpl result = new ResultDescriptorImpl('result', null);
-    ResultCachingPolicy cachingPolicy = result.cachingPolicy;
-    expect(cachingPolicy, isNotNull);
-    expect(cachingPolicy.maxActiveSize, -1);
-    expect(cachingPolicy.maxIdleSize, -1);
-  }
-
-  test_create_withoutContribution() {
-    expect(new ResultDescriptorImpl('name', null), isNotNull);
-  }
-
-  test_inputFor() {
-    AnalysisTarget target = new TestSource();
-    ResultDescriptorImpl result = new ResultDescriptorImpl('result', null);
-    TaskInput input = result.of(target);
-    expect(input, isNotNull);
-  }
-
-  test_name() {
-    String name = 'result';
-    ResultDescriptorImpl result = new ResultDescriptorImpl(name, null);
-    expect(result.name, name);
-  }
-}
-
-@reflectiveTest
-class SimpleResultCachingPolicyTest extends EngineTestCase {
-  test_create() {
-    ResultCachingPolicy policy = new SimpleResultCachingPolicy(256, 32);
-    expect(policy.maxActiveSize, 256);
-    expect(policy.maxIdleSize, 32);
-    expect(policy.measure(null), 1);
-  }
-}
-
-@reflectiveTest
-class TaskDescriptorImplTest extends EngineTestCase {
-  test_create_noOptionalArgs() {
-    String name = 'name';
-    BuildTask buildTask = (context, target) => null;
-    CreateTaskInputs createTaskInputs = (target) => null;
-    List<ResultDescriptor> results = <ResultDescriptor>[];
-    TaskDescriptorImpl descriptor =
-        new TaskDescriptorImpl(name, buildTask, createTaskInputs, results);
-    expect(descriptor, isNotNull);
-    expect(descriptor.name, name);
-    expect(descriptor.buildTask, equals(buildTask));
-    expect(descriptor.createTaskInputs, equals(createTaskInputs));
-    expect(descriptor.suitabilityFor(null), TaskSuitability.LOWEST);
-    expect(descriptor.results, results);
-  }
-
-  test_create_withIsAppropriateFor() {
-    String name = 'name';
-    BuildTask buildTask = (context, target) => null;
-    CreateTaskInputs createTaskInputs = (target) => null;
-    List<ResultDescriptor> results = <ResultDescriptor>[];
-    SuitabilityFor suitabilityFor = (target) => TaskSuitability.NONE;
-    TaskDescriptorImpl descriptor = new TaskDescriptorImpl(
-        name, buildTask, createTaskInputs, results,
-        suitabilityFor: suitabilityFor);
-    expect(descriptor, isNotNull);
-    expect(descriptor.name, name);
-    expect(descriptor.buildTask, equals(buildTask));
-    expect(descriptor.createTaskInputs, equals(createTaskInputs));
-    expect(descriptor.suitabilityFor(null), TaskSuitability.NONE);
-    expect(descriptor.results, results);
-  }
-
-  test_createTask() {
-    BuildTask buildTask =
-        (context, target) => new TestAnalysisTask(context, target);
-    CreateTaskInputs createTaskInputs = (target) => null;
-    List<ResultDescriptor> results = <ResultDescriptor>[];
-    TaskDescriptorImpl descriptor =
-        new TaskDescriptorImpl('name', buildTask, createTaskInputs, results);
-    AnalysisContext context = null;
-    AnalysisTarget target = new TestSource();
-    Map<String, dynamic> inputs = {};
-    AnalysisTask createTask = descriptor.createTask(context, target, inputs);
-    expect(createTask, isNotNull);
-    expect(createTask.context, context);
-    expect(createTask.inputs, inputs);
-    expect(createTask.target, target);
-  }
-}
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index ee00e8e6..8032e06 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -18,13 +18,13 @@
 import 'package:analyzer/src/lint/linter.dart';
 import 'package:analyzer/src/lint/registry.dart';
 import 'package:analyzer/src/task/options.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 import 'package:yaml/yaml.dart';
 
 import '../../generated/test_support.dart';
 import '../../resource_utils.dart';
-import '../context/abstract_context.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -40,10 +40,10 @@
     new TypeMatcher<GenerateOptionsErrorsTask>();
 
 @reflectiveTest
-class ContextConfigurationTest extends AbstractContextTest {
-  final AnalysisOptionsProvider optionsProvider = new AnalysisOptionsProvider();
+class ContextConfigurationTest {
+  final AnalysisOptions analysisOptions = AnalysisOptionsImpl();
 
-  AnalysisOptions get analysisOptions => context.analysisOptions;
+  final AnalysisOptionsProvider optionsProvider = AnalysisOptionsProvider();
 
   void configureContext(String optionsSource) =>
       applyToAnalysisOptions(analysisOptions, parseOptions(optionsSource));
@@ -262,7 +262,7 @@
 }
 
 @reflectiveTest
-class GenerateOldOptionsErrorsTaskTest extends AbstractContextTest {
+class GenerateOldOptionsErrorsTaskTest with ResourceProviderMixin {
   final AnalysisOptionsProvider optionsProvider = new AnalysisOptionsProvider();
 
   String get optionsFilePath => '/${AnalysisEngine.ANALYSIS_OPTIONS_FILE}';
@@ -288,7 +288,7 @@
   }
 
   void validate(String content, List<ErrorCode> expected) {
-    final Source source = newSource(optionsFilePath, content);
+    final source = newFile(optionsFilePath, content: content).createSource();
     var options = optionsProvider.getOptionsFromSource(source);
     final OptionsFileValidator validator = new OptionsFileValidator(source);
     var errors = validator.validate(options);
@@ -376,14 +376,6 @@
 ''', [AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUES]);
   }
 
-  test_analyzer_strong_mode_unsupported_value() {
-    validate('''
-analyzer:
-  strong-mode:
-    implicit-dynamic: foo
-''', [AnalysisOptionsWarningCode.UNSUPPORTED_VALUE]);
-  }
-
   test_analyzer_lint_codes_recognized() {
     Registry.ruleRegistry.register(new TestRule());
     validate('''
@@ -431,6 +423,14 @@
 ''', [AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUES]);
   }
 
+  test_analyzer_strong_mode_unsupported_value() {
+    validate('''
+analyzer:
+  strong-mode:
+    implicit-dynamic: foo
+''', [AnalysisOptionsWarningCode.UNSUPPORTED_VALUE]);
+  }
+
   test_analyzer_supported_exclude() {
     validate('''
 analyzer:
diff --git a/pkg/analyzer/test/src/task/options_work_manager_test.dart b/pkg/analyzer/test/src/task/options_work_manager_test.dart
deleted file mode 100644
index 8845781..0000000
--- a/pkg/analyzer/test/src/task/options_work_manager_test.dart
+++ /dev/null
@@ -1,311 +0,0 @@
-// Copyright (c) 2015, 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 'package:analyzer/error/error.dart' show AnalysisError;
-import 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/error/codes.dart' show AnalysisOptionsErrorCode;
-import 'package:analyzer/src/generated/engine.dart'
-    show
-        AnalysisEngine,
-        AnalysisErrorInfo,
-        AnalysisErrorInfoImpl,
-        CacheState,
-        ChangeNoticeImpl,
-        InternalAnalysisContext;
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/api/general.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/options.dart';
-import 'package:analyzer/src/task/options_work_manager.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../../generated/test_support.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(OptionsWorkManagerNewFileTest);
-    defineReflectiveTests(OptionsWorkManagerOldFileTest);
-  });
-}
-
-@reflectiveTest
-class OptionsWorkManagerNewFileTest extends OptionsWorkManagerTest {
-  String get optionsFile => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE;
-}
-
-@reflectiveTest
-class OptionsWorkManagerOldFileTest extends OptionsWorkManagerTest {
-  String get optionsFile => AnalysisEngine.ANALYSIS_OPTIONS_FILE;
-}
-
-abstract class OptionsWorkManagerTest {
-  _InternalAnalysisContextMock context = new _InternalAnalysisContextMock();
-  AnalysisCache cache;
-  OptionsWorkManager manager;
-
-  CaughtException caughtException = new CaughtException(null, null);
-
-  Source source1;
-
-  Source source2;
-  Source source3;
-  Source source4;
-  CacheEntry entry1;
-  CacheEntry entry2;
-  CacheEntry entry3;
-  CacheEntry entry4;
-  String get optionsFile;
-
-  void expect_sourceQueue(List<Source> sources) {
-    expect(manager.sourceQueue, unorderedEquals(sources));
-  }
-
-  void setUp() {
-    cache = context.analysisCache;
-    manager = new OptionsWorkManager(context);
-    source1 = new TestSource('test1/$optionsFile');
-    source2 = new TestSource('test2/$optionsFile');
-    source3 = new TestSource('test3/$optionsFile');
-    source4 = new TestSource('test4/$optionsFile');
-    entry1 = context.getCacheEntry(source1);
-    entry2 = context.getCacheEntry(source2);
-    entry3 = context.getCacheEntry(source3);
-    entry4 = context.getCacheEntry(source4);
-  }
-
-  void test_applyChange_add() {
-    // add source1
-    manager.applyChange([source1], [], []);
-    expect_sourceQueue([source1]);
-    // add source2
-    manager.applyChange([source2], [], []);
-    expect_sourceQueue([source1, source2]);
-  }
-
-  void test_applyChange_add_duplicate() {
-    // add source1
-    manager.applyChange([source1], [], []);
-    expect_sourceQueue([source1]);
-    // add source1 again
-    manager.applyChange([source1], [], []);
-    expect_sourceQueue([source1]);
-  }
-
-  void test_applyChange_change() {
-    // change source1
-    manager.applyChange([], [source1], []);
-    expect_sourceQueue([source1]);
-  }
-
-  void test_applyChange_change_afterAdd() {
-    manager.applyChange([source1, source2], [], []);
-    // change source1
-    manager.applyChange([], [source1], []);
-    expect_sourceQueue([source1, source2]);
-  }
-
-  void test_applyChange_remove() {
-    manager.applyChange([source1, source2], [], []);
-    // remove source1
-    manager.applyChange([], [], [source1]);
-    expect_sourceQueue([source2]);
-    // remove source2
-    manager.applyChange([], [], [source2]);
-    expect_sourceQueue([]);
-    // remove source3
-    manager.applyChange([], [], [source3]);
-    expect_sourceQueue([]);
-  }
-
-  void test_applyPriorityTargets() {
-    context.setShouldErrorsBeAnalyzed(source2, true);
-    context.setShouldErrorsBeAnalyzed(source3, true);
-    manager.priorityResultQueue
-        .add(new TargetedResult(source1, ANALYSIS_OPTIONS_ERRORS));
-    manager.priorityResultQueue
-        .add(new TargetedResult(source2, ANALYSIS_OPTIONS_ERRORS));
-    // -source1 +source3
-    manager.applyPriorityTargets([source2, source3]);
-    expect(
-        manager.priorityResultQueue,
-        unorderedEquals([
-          new TargetedResult(source2, ANALYSIS_OPTIONS_ERRORS),
-          new TargetedResult(source3, ANALYSIS_OPTIONS_ERRORS)
-        ]));
-    // get next request
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source2);
-    expect(request.result, ANALYSIS_OPTIONS_ERRORS);
-  }
-
-  void test_getErrors() {
-    AnalysisError error1 = new AnalysisError(
-        source1, 1, 0, AnalysisOptionsErrorCode.PARSE_ERROR, ['']);
-    AnalysisError error2 = new AnalysisError(
-        source1, 2, 0, AnalysisOptionsErrorCode.PARSE_ERROR, ['']);
-    entry1
-        .setValue(ANALYSIS_OPTIONS_ERRORS, <AnalysisError>[error1, error2], []);
-
-    List<AnalysisError> errors = manager.getErrors(source1);
-    expect(errors, unorderedEquals([error1, error2]));
-  }
-
-  void test_getNextResult_hasNormal_firstIsError() {
-    entry1.setErrorState(caughtException, [ANALYSIS_OPTIONS_ERRORS]);
-    manager.sourceQueue.addAll([source1, source2]);
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source2);
-    expect(request.result, ANALYSIS_OPTIONS_ERRORS);
-    // source1 is out, source2 is waiting
-    expect_sourceQueue([source2]);
-  }
-
-  void test_getNextResult_hasNormal_firstIsInvalid() {
-    entry1.setState(ANALYSIS_OPTIONS_ERRORS, CacheState.INVALID);
-    manager.sourceQueue.addAll([source1, source2]);
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source1);
-    expect(request.result, ANALYSIS_OPTIONS_ERRORS);
-    // no changes until computed
-    expect_sourceQueue([source1, source2]);
-  }
-
-  void test_getNextResult_hasNormal_firstIsValid() {
-    entry1.setValue(ANALYSIS_OPTIONS_ERRORS, [], []);
-    manager.sourceQueue.addAll([source1, source2]);
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source2);
-    expect(request.result, ANALYSIS_OPTIONS_ERRORS);
-    // source1 is out, source2 is waiting
-    expect_sourceQueue([source2]);
-  }
-
-  void test_getNextResult_hasNormalAndPriority() {
-    entry1.setState(ANALYSIS_OPTIONS_ERRORS, CacheState.INVALID);
-    manager.sourceQueue.addAll([source1, source2]);
-    manager.addPriorityResult(source3, ANALYSIS_OPTIONS_ERRORS);
-
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source3);
-    expect(request.result, ANALYSIS_OPTIONS_ERRORS);
-    // no changes until computed
-    expect_sourceQueue([source1, source2]);
-  }
-
-  void test_getNextResult_hasPriority() {
-    manager.addPriorityResult(source1, ANALYSIS_OPTIONS_ERRORS);
-    manager.addPriorityResult(source2, ANALYSIS_OPTIONS_ERRORS);
-    expect(
-        manager.priorityResultQueue,
-        unorderedEquals([
-          new TargetedResult(source1, ANALYSIS_OPTIONS_ERRORS),
-          new TargetedResult(source2, ANALYSIS_OPTIONS_ERRORS)
-        ]));
-
-    TargetedResult request = manager.getNextResult();
-    expect(request.target, source1);
-    expect(request.result, ANALYSIS_OPTIONS_ERRORS);
-    // no changes until computed
-    expect(
-        manager.priorityResultQueue,
-        unorderedEquals([
-          new TargetedResult(source1, ANALYSIS_OPTIONS_ERRORS),
-          new TargetedResult(source2, ANALYSIS_OPTIONS_ERRORS)
-        ]));
-  }
-
-  void test_getNextResult_nothingToDo() {
-    TargetedResult request = manager.getNextResult();
-    expect(request, isNull);
-  }
-
-  void test_getNextResultPriority_hasPriority() {
-    manager.addPriorityResult(source1, SOURCE_KIND);
-    expect(manager.getNextResultPriority(), WorkOrderPriority.PRIORITY);
-  }
-
-  void test_getNextResultPriority_hasSource() {
-    manager.sourceQueue.addAll([source1]);
-    expect(manager.getNextResultPriority(), WorkOrderPriority.NORMAL);
-  }
-
-  void test_getNextResultPriority_nothingToDo() {
-    expect(manager.getNextResultPriority(), WorkOrderPriority.NONE);
-  }
-
-  void test_resultsComputed_errors() {
-    AnalysisError error1 = new AnalysisError(
-        source1, 1, 0, AnalysisOptionsErrorCode.PARSE_ERROR, ['']);
-    AnalysisError error2 = new AnalysisError(
-        source1, 2, 0, AnalysisOptionsErrorCode.PARSE_ERROR, ['']);
-    LineInfo lineInfo = new LineInfo([0]);
-    entry1.setValue(LINE_INFO, lineInfo, []);
-    entry1
-        .setValue(ANALYSIS_OPTIONS_ERRORS, <AnalysisError>[error1, error2], []);
-    // RESOLVED_UNIT is ready, set errors
-    manager.resultsComputed(source1, {ANALYSIS_OPTIONS_ERRORS: null});
-    // all of the errors are included
-    ChangeNoticeImpl notice = context.getNotice(source1);
-    expect(notice.errors, unorderedEquals([error1, error2]));
-    expect(notice.lineInfo, lineInfo);
-  }
-}
-
-class _InternalAnalysisContextMock implements InternalAnalysisContext {
-  @override
-  CachePartition privateAnalysisCachePartition;
-
-  @override
-  AnalysisCache analysisCache;
-
-  Map<Source, bool> shouldErrorsBeAnalyzedMap = <Source, bool>{};
-
-  Map<Source, ChangeNoticeImpl> _pendingNotices = <Source, ChangeNoticeImpl>{};
-
-  _InternalAnalysisContextMock() {
-    privateAnalysisCachePartition = new UniversalCachePartition(this);
-    analysisCache = new AnalysisCache([privateAnalysisCachePartition]);
-  }
-
-  @override
-  CacheEntry getCacheEntry(AnalysisTarget target) {
-    CacheEntry entry = analysisCache.get(target);
-    if (entry == null) {
-      entry = new CacheEntry(target);
-      analysisCache.put(entry);
-    }
-    return entry;
-  }
-
-  @override
-  AnalysisErrorInfo getErrors(Source source) {
-    List<AnalysisError> errors = AnalysisError.NO_ERRORS;
-    if (AnalysisEngine.isAnalysisOptionsFileName(source.shortName)) {
-      errors = getCacheEntry(source).getValue(ANALYSIS_OPTIONS_ERRORS);
-    }
-    return new AnalysisErrorInfoImpl(
-        errors, getCacheEntry(source).getValue(LINE_INFO));
-  }
-
-  @override
-  ChangeNoticeImpl getNotice(Source source) =>
-      _pendingNotices.putIfAbsent(source, () => new ChangeNoticeImpl(source));
-
-  @override
-  noSuchMethod(Invocation invocation) {
-    throw new StateError('Unexpected invocation of ${invocation.memberName}');
-  }
-
-  void setShouldErrorsBeAnalyzed(Source source, bool value) {
-    shouldErrorsBeAnalyzedMap[source] = value;
-  }
-
-  @override
-  bool shouldErrorsBeAnalyzed(Source source) {
-    return shouldErrorsBeAnalyzedMap[source];
-  }
-}
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 0d931a6..d56773e 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -8,11 +8,15 @@
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(CheckerTest_Driver);
+    defineReflectiveTests(CheckerTest);
   });
 }
 
-abstract class CheckerTest extends AbstractStrongTest {
+@reflectiveTest
+class CheckerTest extends AbstractStrongTest {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   test_awaitForInCastsStreamElementToVariable() async {
     await checkFile('''
 import 'dart:async';
@@ -2305,11 +2309,11 @@
 
   test_implicitDynamic_mapLiteral() async {
     addFile(r'''
-var m0 = /*error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{};
-Map m1 = /*error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{};
-Map<dynamic, dynamic> m2 = /*error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{};
+var m0 = /*info:INFERRED_TYPE_LITERAL,error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{};
+Map m1 = /*info:INFERRED_TYPE_LITERAL,error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{};
+Map<dynamic, dynamic> m2 = /*info:INFERRED_TYPE_LITERAL,error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{};
 dynamic d = 42;
-var m3 = /*error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{d: d};
+var m3 = /*info:INFERRED_TYPE_LITERAL,error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{d: d};
 var m4 = /*info:INFERRED_TYPE_LITERAL,error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{'x': d, 'y': d};
 var m5 = /*info:INFERRED_TYPE_LITERAL,error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{d: 'x'};
 
@@ -2535,7 +2539,6 @@
     ''');
   }
 
-  @failingTest // Does not work with old task model
   test_interfacesFromMixinsUsedTwiceAreChecked() {
     // Regression test for https://github.com/dart-lang/sdk/issues/29782
     return checkFile(r'''
@@ -3744,7 +3747,6 @@
     var upwardsInferNonDynamicIsOK = {4: 2};
     var explicitDynamicIsOK = <dynamic, dynamic>{4: 2};
 
-    var rawMap = /*info:STRICT_RAW_TYPE*/{};
     var rawMapOfMaps = </*info:STRICT_RAW_TYPE*/Map>{};
     /*info:STRICT_RAW_TYPE*/Map rawMapFromType = {};
 
@@ -3818,6 +3820,15 @@
     await check(strictRawTypes: true);
   }
 
+  test_strictRawTypes_emptyMap() async {
+    addFile('''
+main() {
+  var rawMap = /*info:STRICT_RAW_TYPE*/{};
+}
+''');
+    await check(strictRawTypes: true);
+  }
+
   test_strictRawTypes_typedefs() async {
     addFile(r'''
 typedef T F1<T>(T _);
@@ -4153,13 +4164,13 @@
  // TODO(leafp): We can't currently test for key errors since the
  // error marker binds to the entire entry.
   {
-     Map m = {s: i};
-     m = {s: s};
-     m = {s: n};
-     m = {s: i,
+     Map m = /*info:INFERRED_TYPE_LITERAL*/{s: i};
+     m = /*info:INFERRED_TYPE_LITERAL*/{s: s};
+     m = /*info:INFERRED_TYPE_LITERAL*/{s: n};
+     m = /*info:INFERRED_TYPE_LITERAL*/{s: i,
           s: n,
           s: s};
-     m = {i: s,
+     m = /*info:INFERRED_TYPE_LITERAL*/{i: s,
           n: s,
           s: s};
   }
@@ -4500,13 +4511,3 @@
     ''', name: '/meta.dart');
   }
 }
-
-@reflectiveTest
-class CheckerTest_Driver extends CheckerTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-
-  @override // Passes with driver
-  test_interfacesFromMixinsUsedTwiceAreChecked() =>
-      super.test_interfacesFromMixinsUsedTwiceAreChecked();
-}
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index 777c51f..a6da936 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2015, 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.
 
@@ -15,7 +15,7 @@
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(InferredTypeTest_Driver);
+    defineReflectiveTests(InferredTypeTest);
     defineReflectiveTests(InferredTypeTest_SetLiterals);
   });
 }
@@ -1410,7 +1410,7 @@
 void foo([Map<int, String> m1 = /*info:INFERRED_TYPE_LITERAL*/const {1: "hello"},
     Map<int, String> m2 = /*info:INFERRED_TYPE_LITERAL*/const {
       // One error is from type checking and the other is from const evaluation.
-      /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE,error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/"hello":
+      /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/"hello":
           "world"
     }]) {
 }
@@ -1431,11 +1431,11 @@
     };
   }
   {
-    Map<dynamic, dynamic> l0 = {};
-    Map<dynamic, dynamic> l1 = {3: "hello"};
-    Map<dynamic, dynamic> l2 = {"hello": "hello"};
-    Map<dynamic, dynamic> l3 = {3: 3};
-    Map<dynamic, dynamic> l4 = {3:"hello", "hello": 3};
+    Map<dynamic, dynamic> l0 = /*info:INFERRED_TYPE_LITERAL*/{};
+    Map<dynamic, dynamic> l1 = /*info:INFERRED_TYPE_LITERAL*/{3: "hello"};
+    Map<dynamic, dynamic> l2 = /*info:INFERRED_TYPE_LITERAL*/{"hello": "hello"};
+    Map<dynamic, dynamic> l3 = /*info:INFERRED_TYPE_LITERAL*/{3: 3};
+    Map<dynamic, dynamic> l4 = /*info:INFERRED_TYPE_LITERAL*/{3:"hello", "hello": 3};
   }
   {
     Map<dynamic, String> l0 = /*info:INFERRED_TYPE_LITERAL*/{};
@@ -1470,16 +1470,16 @@
     const Map<int, String> l0 = /*info:INFERRED_TYPE_LITERAL*/const {};
     const Map<int, String> l1 = /*info:INFERRED_TYPE_LITERAL*/const {3: "hello"};
     const Map<int, String> l2 = /*info:INFERRED_TYPE_LITERAL*/const {
-      /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE,error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/"hello":
+      /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/"hello":
           "hello"
     };
     const Map<int, String> l3 = /*info:INFERRED_TYPE_LITERAL*/const {
-      3: /*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE,error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/3
+      3: /*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/3
     };
     const Map<int, String> l4 = /*info:INFERRED_TYPE_LITERAL*/const {
       3:"hello",
-      /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE,error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/"hello":
-          /*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE,error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/3
+      /*error:MAP_KEY_TYPE_NOT_ASSIGNABLE*/"hello":
+          /*error:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/3
     };
   }
 }
@@ -1504,7 +1504,7 @@
 Iterable<Map<int, int>> bar() sync* {
   yield /*info:INFERRED_TYPE_LITERAL*/{};
   yield /*error:YIELD_OF_INVALID_TYPE*/new List();
-  yield* {};
+  yield* /*info:INFERRED_TYPE_LITERAL*/{};
   yield* /*info:INFERRED_TYPE_ALLOCATION*/new List();
 }
 ''');
@@ -2546,13 +2546,13 @@
   b = /*error:INVALID_ASSIGNMENT*/"hi";
   b = new B(3);
   c1 = [];
-  c1 = /*error:INVALID_ASSIGNMENT*/{};
+  c1 = /*error:INVALID_ASSIGNMENT,info:INFERRED_TYPE_LITERAL*/{};
   c2 = [];
-  c2 = /*error:INVALID_ASSIGNMENT*/{};
-  d = {};
+  c2 = /*error:INVALID_ASSIGNMENT,info:INFERRED_TYPE_LITERAL*/{};
+  d = /*info:INFERRED_TYPE_LITERAL*/{};
   d = /*error:INVALID_ASSIGNMENT*/3;
   e = new A();
-  e = /*error:INVALID_ASSIGNMENT*/{};
+  e = /*error:INVALID_ASSIGNMENT,info:INFERRED_TYPE_LITERAL*/{};
   f = 3;
   f = /*error:INVALID_ASSIGNMENT*/false;
   g = 1;
@@ -4393,72 +4393,6 @@
 @reflectiveTest
 class InferredTypeTest extends AbstractStrongTest with InferredTypeMixin {
   @override
-  bool get mayCheckTypesOfLocals => true;
-
-  @override
-  Future<CompilationUnitElement> checkFileElement(String content) async {
-    CompilationUnit unit = await checkFile(content);
-    return unit.declaredElement;
-  }
-
-  @override
-  @failingTest
-  test_circularReference_viaClosures() {
-    return super.test_circularReference_viaClosures();
-  }
-
-  @override
-  @failingTest
-  test_circularReference_viaClosures_initializerTypes() {
-    return super.test_circularReference_viaClosures_initializerTypes();
-  }
-
-  @override
-  @failingTest
-  test_instantiateToBounds_typeName_error1() {
-    // Test doesn't work with the old task model
-    return super.test_instantiateToBounds_typeName_error1();
-  }
-
-  @override
-  @failingTest
-  test_instantiateToBounds_typeName_error2() {
-    // Test doesn't work with the old task model
-    return super.test_instantiateToBounds_typeName_error2();
-  }
-
-  @override
-  @failingTest
-  test_instantiateToBounds_typeName_error3() {
-    // Test doesn't work with the old task model
-    return super.test_instantiateToBounds_typeName_error3();
-  }
-
-  @override
-  @failingTest
-  test_instantiateToBounds_typeName_OK_hasBound_definedAfter() {
-    return super.test_instantiateToBounds_typeName_OK_hasBound_definedAfter();
-  }
-
-  @override
-  @failingTest
-  test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1() {
-    return super
-        .test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1();
-  }
-
-  @failingTest
-  @override
-  test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1() {
-    return super
-        .test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1();
-  }
-}
-
-@reflectiveTest
-class InferredTypeTest_Driver extends AbstractStrongTest
-    with InferredTypeMixin {
-  @override
   bool get enableNewAnalysisDriver => true;
 
   @override
@@ -4527,7 +4461,7 @@
 Iterable<Map<int, int>> bar() sync* {
   yield /*info:INFERRED_TYPE_LITERAL*/{};
   yield /*error:YIELD_OF_INVALID_TYPE*/new List();
-  yield* {};
+  yield* /*info:INFERRED_TYPE_LITERAL*/{};
   yield* /*info:INFERRED_TYPE_ALLOCATION*/new List();
 }
 ''');
diff --git a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
index 38d5a42..fadd403 100644
--- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
+++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -243,10 +243,10 @@
   AnalysisContext _context = null;
   AnalysisDriver _driver = null;
 
-  bool get enableNewAnalysisDriver => false;
-
   List<String> get enabledExperiments => [];
 
+  bool get enableNewAnalysisDriver => false;
+
   /// Adds a file to check. The file should contain:
   ///
   ///   * all expected failures are listed in the source code using comments
@@ -382,9 +382,7 @@
     );
   }
 
-  void setUp() {
-    AnalysisEngine.instance.processRequiredPlugins();
-  }
+  void setUp() {}
 
   void tearDown() {
     // This is a sanity check, in case only addFile is called.
diff --git a/pkg/analyzer/test/src/task/test_all.dart b/pkg/analyzer/test/src/task/test_all.dart
index f66959e..d6f96c1f 100644
--- a/pkg/analyzer/test/src/task/test_all.dart
+++ b/pkg/analyzer/test/src/task/test_all.dart
@@ -4,25 +4,12 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'dart_work_manager_test.dart' as dart_work_manager_test;
-import 'general_test.dart' as general_test;
-import 'inputs_test.dart' as inputs_test;
-import 'manager_test.dart' as manager_test;
-import 'model_test.dart' as model_test;
 import 'options_test.dart' as options_test;
-import 'options_work_manager_test.dart' as options_work_manager_test;
 import 'strong/test_all.dart' as strong_mode_test_all;
 
-/// Utility for manually running all tests.
 main() {
   defineReflectiveSuite(() {
-    dart_work_manager_test.main();
-    general_test.main();
-    inputs_test.main();
-    manager_test.main();
-    model_test.main();
     options_test.main();
-    options_work_manager_test.main();
     strong_mode_test_all.main();
   }, name: 'task');
 }
diff --git a/pkg/analyzer/test/src/task/test_support.dart b/pkg/analyzer/test/src/task/test_support.dart
deleted file mode 100644
index 7415324..0000000
--- a/pkg/analyzer/test/src/task/test_support.dart
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2015, 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 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/task/api/model.dart';
-
-/**
- * A configurable analysis task that can be used by tests.
- */
-class TestAnalysisTask extends AnalysisTask {
-  /**
-   * The descriptor describing this task.
-   */
-  TaskDescriptor descriptor;
-
-  /**
-   * The exception that is to be "thrown" by this task.
-   */
-  CaughtException exception;
-
-  /**
-   * The results whose values are to be provided as outputs from this task.
-   */
-  List<ResultDescriptor> results;
-
-  /**
-   * The next value that is to be used for a result.
-   */
-  int value;
-
-  @override
-  final bool handlesDependencyCycles;
-
-  TestAnalysisTask(AnalysisContext context, AnalysisTarget target,
-      {this.descriptor,
-      this.exception,
-      this.handlesDependencyCycles: false,
-      this.results,
-      this.value: 1})
-      : super(context, target);
-
-  @override
-  String get description => 'Test task';
-
-  @override
-  internalPerform() {
-    if (exception != null) {
-      caughtException = exception;
-    } else if (results != null) {
-      for (ResultDescriptor result in results) {
-        outputs[result] = value++;
-      }
-    } else if (descriptor != null) {
-      for (ResultDescriptor result in descriptor.results) {
-        outputs[result] = value++;
-      }
-    }
-  }
-}
diff --git a/pkg/analyzer/test/src/test_all.dart b/pkg/analyzer/test/src/test_all.dart
index 011e198..32548b3 100644
--- a/pkg/analyzer/test/src/test_all.dart
+++ b/pkg/analyzer/test/src/test_all.dart
@@ -9,15 +9,18 @@
 import 'dart/test_all.dart' as dart;
 import 'diagnostics/test_all.dart' as diagnostics;
 import 'fasta/test_all.dart' as fasta;
+import 'hint/test_all.dart' as hint;
 import 'lint/test_all.dart' as lint;
 import 'options/test_all.dart' as options;
 import 'pubspec/test_all.dart' as pubspec;
+import 'services/test_all.dart' as services;
 import 'source/test_all.dart' as source;
 import 'summary/test_all.dart' as summary;
+import 'summary2/test_all.dart' as summary2;
 import 'task/test_all.dart' as task;
 import 'util/test_all.dart' as util;
+import 'workspace/test_all.dart' as workspace;
 
-/// Utility for manually running all tests.
 main() {
   defineReflectiveSuite(() {
     command_line.main();
@@ -25,12 +28,16 @@
     dart.main();
     diagnostics.main();
     fasta.main();
+    hint.main();
     lint.main();
     options.main();
     pubspec.main();
+    services.main();
     source.main();
     summary.main();
+    summary2.main();
     task.main();
     util.main();
+    workspace.main();
   }, name: 'src');
 }
diff --git a/pkg/analyzer/test/src/workspace/test_all.dart b/pkg/analyzer/test/src/workspace/test_all.dart
index c2e0512..edf5bd0 100644
--- a/pkg/analyzer/test/src/workspace/test_all.dart
+++ b/pkg/analyzer/test/src/workspace/test_all.dart
@@ -1,19 +1,21 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2014, 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 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'basic_test.dart' as basic_test;
-import 'bazel_test.dart' as bazel_test;
-import 'gn_test.dart' as gn_test;
-import 'package_build_test.dart' as package_build_test;
+import 'basic_test.dart' as basic;
+import 'bazel_test.dart' as bazel;
+import 'gn_test.dart' as gn;
+import 'package_build_test.dart' as package_build;
+import 'pub_test.dart' as pub;
 
 main() {
   defineReflectiveSuite(() {
-    basic_test.main();
-    bazel_test.main();
-    gn_test.main();
-    package_build_test.main();
+    basic.main();
+    bazel.main();
+    gn.main();
+    package_build.main();
+    pub.main();
   }, name: 'workspace');
 }
diff --git a/pkg/analyzer/test/test_all.dart b/pkg/analyzer/test/test_all.dart
index d0c8dfd..a27c273 100644
--- a/pkg/analyzer/test/test_all.dart
+++ b/pkg/analyzer/test/test_all.dart
@@ -1,10 +1,10 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2014, 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 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'cancelable_future_test.dart' as cancelable_future_test;
+import 'cancelable_future_test.dart' as cancelable_future;
 import 'dart/test_all.dart' as dart;
 import 'error/test_all.dart' as error;
 import 'file_system/test_all.dart' as file_system;
@@ -13,11 +13,11 @@
 import 'parse_compilation_unit_test.dart' as parse_compilation_unit;
 import 'source/test_all.dart' as source;
 import 'src/test_all.dart' as src;
+import 'verify_tests_test.dart' as verify_tests;
 
-/// Utility for manually running all tests.
 main() {
   defineReflectiveSuite(() {
-    cancelable_future_test.main();
+    cancelable_future.main();
     dart.main();
     error.main();
     file_system.main();
@@ -26,5 +26,6 @@
     parse_compilation_unit.main();
     source.main();
     src.main();
+    verify_tests.main();
   }, name: 'analyzer');
 }
diff --git a/pkg/analyzer/test/verify_tests_test.dart b/pkg/analyzer/test/verify_tests_test.dart
new file mode 100644
index 0000000..d22aa57
--- /dev/null
+++ b/pkg/analyzer/test/verify_tests_test.dart
@@ -0,0 +1,82 @@
+// Copyright (c) 2019, 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 'package:analyzer/dart/analysis/analysis_context.dart';
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:front_end/src/testing/package_root.dart' as package_root;
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+
+main() {
+  PhysicalResourceProvider provider = PhysicalResourceProvider.INSTANCE;
+  String packageRoot = provider.pathContext.normalize(package_root.packageRoot);
+  String analyzerPath = provider.pathContext.join(packageRoot, 'analyzer');
+  String testDirPath = provider.pathContext.join(analyzerPath, 'test');
+
+  AnalysisContextCollection collection = new AnalysisContextCollection(
+      includedPaths: <String>[testDirPath], resourceProvider: provider);
+  List<AnalysisContext> contexts = collection.contexts;
+  if (contexts.length != 1) {
+    fail('The test directory contains multiple analysis contexts.');
+  }
+
+  buildTestsIn(
+      contexts[0].currentSession, testDirPath, provider.getFolder(testDirPath));
+}
+
+void buildTestsIn(
+    AnalysisSession session, String testDirPath, Folder directory) {
+  List<String> testFileNames = [];
+  File testAllFile;
+  List<Resource> children = directory.getChildren();
+  children.sort((first, second) => first.shortName.compareTo(second.shortName));
+  for (Resource child in children) {
+    if (child is Folder) {
+      if (child.getChildAssumingFile('test_all.dart').exists) {
+        testFileNames.add('${child.shortName}/test_all.dart');
+      }
+      buildTestsIn(session, testDirPath, child);
+    } else if (child is File) {
+      String name = child.shortName;
+      if (name == 'test_all.dart') {
+        testAllFile = child;
+      } else if (name.endsWith('_test.dart')) {
+        testFileNames.add(name);
+      }
+    }
+  }
+  String relativePath = path.relative(directory.path, from: testDirPath);
+  test(relativePath, () {
+    if (testFileNames.isEmpty) {
+      return;
+    }
+    if (testAllFile == null) {
+      fail('Missing "test_all.dart" in $relativePath');
+    }
+    ParsedUnitResult result = session.getParsedUnit(testAllFile.path);
+    if (result.state != ResultState.VALID) {
+      fail('Could not parse ${testAllFile.path}');
+    }
+    List<String> importedFiles = [];
+    for (var directive in result.unit.directives) {
+      if (directive is ImportDirective) {
+        importedFiles.add(directive.uri.stringValue);
+      }
+    }
+    List<String> missingFiles = [];
+    for (String testFileName in testFileNames) {
+      if (!importedFiles.contains(testFileName)) {
+        missingFiles.add(testFileName);
+      }
+    }
+    if (missingFiles.isNotEmpty) {
+      fail('Tests missing from "test_all.dart": ${missingFiles.join(', ')}');
+    }
+  });
+}
diff --git a/pkg/analyzer/tool/summary/dump_inferred_types.dart b/pkg/analyzer/tool/summary/dump_inferred_types.dart
index a5167b0..ffc71af 100644
--- a/pkg/analyzer/tool/summary/dump_inferred_types.dart
+++ b/pkg/analyzer/tool/summary/dump_inferred_types.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/base.dart';
 import 'package:analyzer/src/summary/idl.dart';
@@ -40,7 +41,8 @@
 
   InferredTypeCollector(
       GetDependencyCallback getDependency, GetUnitCallback getUnit)
-      : _linker = new Linker({}, getDependency, getUnit, null);
+      : _linker =
+            new Linker({}, getDependency, getUnit, null, AnalysisOptionsImpl());
 
   /**
    * If an inferred type exists matching the given [slot], record that it is the
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index ee2a239..ca4002a 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -354,8 +354,12 @@
             uriToUnit[absoluteUri];
       }
 
-      Map<String, LinkedLibraryBuilder> linkResult = link(libraryUris,
-          getDependency, getUnit, analysisDriver.declaredVariables.get);
+      Map<String, LinkedLibraryBuilder> linkResult = link(
+          libraryUris,
+          getDependency,
+          getUnit,
+          analysisDriver.declaredVariables,
+          analysisOptions);
       linkResult.forEach(assembler.addLinkedLibrary);
     });
   }
@@ -557,6 +561,22 @@
 }
 
 /**
+ * Tracks paths to dependencies, really just a thin api around a Set<String>.
+ */
+class DependencyTracker {
+  final _dependencies = Set<String>();
+
+  /// The path to the file to create once tracking is done.
+  final String outputPath;
+
+  DependencyTracker(this.outputPath);
+
+  Iterable<String> get dependencies => _dependencies;
+
+  void record(String path) => _dependencies.add(path);
+}
+
+/**
  * [PackageBundleProvider] that always reads from the [ResourceProvider].
  */
 class DirectPackageBundleProvider implements PackageBundleProvider {
@@ -719,19 +739,3 @@
     return cache.get(inputs, path);
   }
 }
-
-/**
- * Tracks paths to dependencies, really just a thin api around a Set<String>.
- */
-class DependencyTracker {
-  final _dependencies = Set<String>();
-
-  Iterable<String> get dependencies => _dependencies;
-
-  /// The path to the file to create once tracking is done.
-  final String outputPath;
-
-  DependencyTracker(this.outputPath);
-
-  void record(String path) => _dependencies.add(path);
-}
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 8b2b808..dea039b 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -52,8 +52,6 @@
 import 'package:package_config/packages_file.dart' as pkgfile show parse;
 import 'package:package_config/src/packages_impl.dart' show MapPackages;
 import 'package:path/path.dart' as path;
-import 'package:plugin/manager.dart';
-import 'package:plugin/plugin.dart';
 import 'package:telemetry/crash_reporting.dart';
 import 'package:telemetry/telemetry.dart' as telemetry;
 import 'package:yaml/yaml.dart';
@@ -100,9 +98,6 @@
 
   ContextCache contextCache;
 
-  /// The plugins that are defined outside the `analyzer_cli` package.
-  List<Plugin> _userDefinedPlugins = <Plugin>[];
-
   /// The driver that was most recently created by a call to [_analyzeAll], or
   /// `null` if [_analyzeAll] hasn't been called yet.
   @visibleForTesting
@@ -149,11 +144,6 @@
   CrashReportSender get crashReportSender => (_crashReportSender ??=
       new CrashReportSender('Dart_analyzer_cli', analytics));
 
-  @override
-  void set userDefinedPlugins(List<Plugin> plugins) {
-    _userDefinedPlugins = plugins ?? <Plugin>[];
-  }
-
   /**
    * Converts the given [filePath] into absolute and normalized.
    */
@@ -173,7 +163,7 @@
 
     StringUtilities.INTERNER = new MappedInterner();
 
-    _processPlugins();
+    linter.registerLintRules();
 
     // Parse commandline options.
     CommandLineOptions options = CommandLineOptions.parse(args);
@@ -735,17 +725,6 @@
   bool _isInHiddenDir(String relative) =>
       path.split(relative).any((part) => part.startsWith("."));
 
-  void _processPlugins() {
-    List<Plugin> plugins = <Plugin>[];
-    plugins.addAll(AnalysisEngine.instance.requiredPlugins);
-    plugins.addAll(_userDefinedPlugins);
-
-    ExtensionManager manager = new ExtensionManager();
-    manager.processPlugins(plugins);
-
-    linter.registerLintRules();
-  }
-
   /// Analyze a single source.
   Future<ErrorSeverity> _runAnalyzer(
       FileState file, CommandLineOptions options, ErrorFormatter formatter) {
diff --git a/pkg/analyzer_cli/lib/starter.dart b/pkg/analyzer_cli/lib/starter.dart
index 09db5bf..88a232c 100644
--- a/pkg/analyzer_cli/lib/starter.dart
+++ b/pkg/analyzer_cli/lib/starter.dart
@@ -7,7 +7,6 @@
 
 import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:analyzer_cli/src/driver.dart';
-import 'package:plugin/plugin.dart';
 
 /**
  * An object that can be used to start a command-line analysis. This class
@@ -30,11 +29,6 @@
   void set packageResolverProvider(ResolverProvider provider);
 
   /**
-   * Set the [plugins] that are defined outside the analyzer_cli package.
-   */
-  void set userDefinedPlugins(List<Plugin> plugins);
-
-  /**
    * Use the given command-line [arguments] to start this analyzer.
    *
    * If [sendPort] is provided it is used for bazel worker communication
diff --git a/pkg/analyzer_cli/pubspec.yaml b/pkg/analyzer_cli/pubspec.yaml
index bfa2b84..cac47aa 100644
--- a/pkg/analyzer_cli/pubspec.yaml
+++ b/pkg/analyzer_cli/pubspec.yaml
@@ -8,7 +8,6 @@
   collection: ^1.14.1
   linter: ^0.1.16
   package_config: '>=0.1.5 <2.0.0'
-  plugin: '>=0.1.0 <0.3.0'
   protobuf: ^0.9.0
   telemetry: ^0.0.1
   yaml: ^2.1.2
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index e504aac..785a0f3 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -1266,11 +1266,14 @@
     // Prepare information about existing imports.
     LibraryDirective libraryDirective;
     List<ImportDirective> importDirectives = <ImportDirective>[];
+    PartDirective partDirective;
     for (Directive directive in unit.directives) {
       if (directive is LibraryDirective) {
         libraryDirective = directive;
       } else if (directive is ImportDirective) {
         importDirectives.add(directive);
+      } else if (directive is PartDirective) {
+        partDirective = directive;
       }
     }
 
@@ -1396,15 +1399,28 @@
     // Insert imports: after the library directive.
     if (libraryDirective != null) {
       addInsertion(libraryDirective.end, (EditBuilder builder) {
+        builder.writeln();
+        builder.writeln();
         for (int i = 0; i < importList.length; i++) {
           var import = importList[i];
-          if (i == 0) {
+          writeImport(builder, import);
+          if (i != importList.length - 1) {
             builder.writeln();
           }
-          builder.writeln();
+        }
+      });
+      return;
+    }
+
+    // Insert imports: before a part directive.
+    if (partDirective != null) {
+      addInsertion(partDirective.offset, (EditBuilder builder) {
+        for (int i = 0; i < importList.length; i++) {
+          var import = importList[i];
           writeImport(builder, import);
           builder.writeln();
         }
+        builder.writeln();
       });
       return;
     }
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
index a3be8b8..5aae60f 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
@@ -1604,25 +1604,6 @@
 @reflectiveTest
 class ImportLibraryTest extends AbstractContextTest
     with DartChangeBuilderMixin {
-  test_afterLibraryDirective_dart() async {
-    await _assertImportLibrary(
-      initialCode: '''
-library test;
-
-class A {}
-''',
-      uriList: ['dart:async'],
-      expectedCode: '''
-library test;
-
-import 'dart:async';
-
-
-class A {}
-''',
-    );
-  }
-
   test_dart_beforeDart() async {
     await _assertImportLibrary(
       initialCode: '''
@@ -1765,6 +1746,58 @@
     );
   }
 
+  test_noImports_afterLibrary_hasDeclaration() async {
+    await _assertImportLibrary(
+      initialCode: '''
+library test;
+
+class A {}
+''',
+      uriList: ['dart:async'],
+      expectedCode: '''
+library test;
+
+import 'dart:async';
+
+class A {}
+''',
+    );
+  }
+
+  test_noImports_afterLibrary_hasPart() async {
+    await _assertImportLibrary(
+      initialCode: '''
+library test;
+
+part 'a.dart';
+''',
+      uriList: ['dart:aaa', 'dart:bbb'],
+      expectedCode: '''
+library test;
+
+import 'dart:aaa';
+import 'dart:bbb';
+
+part 'a.dart';
+''',
+    );
+  }
+
+  test_noImports_beforePart() async {
+    await _assertImportLibrary(
+      initialCode: '''
+part 'a.dart';
+''',
+      uriList: ['dart:aaa', 'dart:bbb'],
+      expectedCode: '''
+import 'dart:aaa';
+import 'dart:bbb';
+
+part 'a.dart';
+''',
+    );
+  }
+
   test_package_afterDart() async {
     await _assertImportLibrary(
       initialCode: '''
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
index 02e19d1..51cc21e 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
@@ -468,11 +468,9 @@
     );
   }
 
-  @failingTest
   test_shadowed_class_inPart() async {
     newFile('/home/test/lib/a.dart', content: 'class C {}');
     newFile('/home/test/lib/p.dart', content: 'class C {}');
-    // TODO(scheglov) "import" must be before "part"
     await _assertImportLibraryElement(
       initialCode: r'''
 part 'p.dart';
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
index 37958bb..8f42f89 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
@@ -6,6 +6,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/engine.dart' as analyzer;
 import 'package:analyzer/src/generated/parser.dart' as analyzer;
 import 'package:analyzer/src/test_utilities/find_element.dart';
 import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
@@ -663,20 +664,33 @@
     assertTarget('new C();', '{var f; {var x;} new C();}');
   }
 
-  test_MapLiteralEntry() async {
-    // MapLiteralEntry  MapLiteral  VariableDeclaration
+  test_MapLiteral_expression() async {
+    super.setUp();
+    final experimentStatus =
+        (this.driver.analysisOptions as analyzer.AnalysisOptionsImpl)
+            .experimentStatus;
+    if (experimentStatus.control_flow_collections ||
+        experimentStatus.spread_collections) {
+      // SimpleIdentifier  MapLiteral  VariableDeclaration
+      await createTarget('foo = {1: 2, T^');
+      assertTarget('T', '{1 : 2, T}');
+    } else {
+      // TODO(b/35569): remove this branch of test behavior
+
+      // SimpleIdentifier  MapLiteralEntry  MapLiteral  VariableDeclaration
+      await createTarget('foo = {1: 2, T^');
+      assertTarget('T : ', '{1 : 2, T : }');
+    }
+  }
+
+  test_MapLiteral_empty() async {
+    // MapLiteral  VariableDeclaration
     await createTarget('foo = {^');
     // fasta scanner inserts synthetic closing '}'
     assertTarget('}', '{}');
   }
 
-  test_MapLiteralEntry1() async {
-    // MapLiteralEntry  MapLiteral  VariableDeclaration
-    await createTarget('foo = {1: 2, T^');
-    assertTarget('T : ', '{1 : 2, T : }');
-  }
-
-  test_MapLiteralEntry2() async {
+  test_MapLiteralEntry() async {
     // SimpleIdentifier  MapLiteralEntry  MapLiteral  VariableDeclaration
     await createTarget('foo = {7:T^};');
     assertTarget('T', '7 : T');
diff --git a/pkg/compiler/analysis_options.yaml b/pkg/compiler/analysis_options.yaml
index af22f6b..deba0e5 100644
--- a/pkg/compiler/analysis_options.yaml
+++ b/pkg/compiler/analysis_options.yaml
@@ -10,3 +10,7 @@
     deprecated_member_use: ignore
     # Allow deprecated calls from within the same package
     deprecated_member_use_from_same_package: ignore
+
+linter:
+  rules:
+    - annotate_overrides
diff --git a/pkg/compiler/lib/compiler.dart b/pkg/compiler/lib/compiler.dart
index 11816ed..3da6d59 100644
--- a/pkg/compiler/lib/compiler.dart
+++ b/pkg/compiler/lib/compiler.dart
@@ -170,5 +170,6 @@
   /// diagnostic kinds.
   const Diagnostic(this.ordinal, this.name);
 
+  @override
   String toString() => name;
 }
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index f54520a..17c84a4 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -22,7 +22,9 @@
 /// Implements the [Compiler] using a [api.CompilerInput] for supplying the
 /// sources.
 class CompilerImpl extends Compiler {
+  @override
   final Measurer measurer;
+  @override
   api.CompilerInput provider;
   api.CompilerDiagnostics handler;
 
@@ -81,6 +83,7 @@
     return future;
   }
 
+  @override
   Future<bool> run(Uri uri) {
     Duration setupDuration = measurer.elapsedWallClock;
     return selfTask.measureSubtask("impl.run", () {
@@ -146,6 +149,7 @@
         ' (${percent.toStringAsFixed(2)}%)');
   }
 
+  @override
   void reportDiagnostic(DiagnosticMessage message,
       List<DiagnosticMessage> infos, api.Diagnostic kind) {
     _reportDiagnosticMessage(message, kind);
@@ -197,6 +201,7 @@
 
   _Environment(this.definitions);
 
+  @override
   String valueOf(String name) {
     var result = definitions[name];
     if (result != null || definitions.containsKey(name)) return result;
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index 467dfe1c3..343d58b 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -307,14 +307,18 @@
 
   BoxLocal(this.container);
 
+  @override
   String get name => container.name;
 
+  @override
   bool operator ==(other) {
     return other is BoxLocal && other.container == container;
   }
 
+  @override
   int get hashCode => container.hashCode;
 
+  @override
   String toString() => 'BoxLocal($name)';
 }
 
@@ -324,12 +328,15 @@
 
   ThisLocal(this.enclosingClass);
 
+  @override
   String get name => 'this';
 
+  @override
   bool operator ==(other) {
     return other is ThisLocal && other.enclosingClass == enclosingClass;
   }
 
+  @override
   int get hashCode => enclosingClass.hashCode;
 }
 
@@ -339,15 +346,19 @@
 
   TypeVariableLocal(this.typeVariable);
 
+  @override
   String get name => typeVariable.element.name;
 
+  @override
   int get hashCode => typeVariable.hashCode;
 
+  @override
   bool operator ==(other) {
     if (other is! TypeVariableLocal) return false;
     return typeVariable == other.typeVariable;
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('type_variable_local(');
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index a0c99af..ec92751 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -46,6 +46,7 @@
 
   _CodegenImpact();
 
+  @override
   void apply(WorldImpactVisitor visitor) {
     staticUses.forEach(visitor.visitStaticUse);
     dynamicUses.forEach(visitor.visitDynamicUse);
@@ -59,6 +60,7 @@
         .add(new Pair<DartType, DartType>(subtype, supertype));
   }
 
+  @override
   Iterable<Pair<DartType, DartType>> get typeVariableBoundsSubtypeChecks {
     return _typeVariableBoundsSubtypeChecks != null
         ? _typeVariableBoundsSubtypeChecks
@@ -70,6 +72,7 @@
     _constSymbols.add(name);
   }
 
+  @override
   Iterable<String> get constSymbols {
     return _constSymbols != null ? _constSymbols : const <String>[];
   }
@@ -79,6 +82,7 @@
     _specializedGetInterceptors.add(classes);
   }
 
+  @override
   Iterable<Set<ClassEntity>> get specializedGetInterceptors {
     return _specializedGetInterceptors != null
         ? _specializedGetInterceptors
@@ -89,6 +93,7 @@
     _usesInterceptor = true;
   }
 
+  @override
   bool get usesInterceptor => _usesInterceptor;
 
   void registerAsyncMarker(AsyncMarker asyncMarker) {
@@ -96,6 +101,7 @@
     _asyncMarkers.add(asyncMarker);
   }
 
+  @override
   Iterable<AsyncMarker> get asyncMarkers {
     return _asyncMarkers != null
         ? _asyncMarkers.iterable(AsyncMarker.values)
@@ -125,6 +131,7 @@
 
   bool get isForResolution => false;
 
+  @override
   String toString() => 'CodegenRegistry for $currentElement';
 
   @deprecated
diff --git a/pkg/compiler/lib/src/common/names.dart b/pkg/compiler/lib/src/common/names.dart
index 5d1116c..ec947a4 100644
--- a/pkg/compiler/lib/src/common/names.dart
+++ b/pkg/compiler/lib/src/common/names.dart
@@ -231,4 +231,8 @@
 
   /// The URI for 'package:js'.
   static final Uri package_js = new Uri(scheme: 'package', path: 'js/js.dart');
+
+  /// The URI for 'package:meta/dart2js.dart'.
+  static final Uri package_meta_dart2js =
+      new Uri(scheme: 'package', path: 'meta/dart2js.dart');
 }
diff --git a/pkg/compiler/lib/src/common/tasks.dart b/pkg/compiler/lib/src/common/tasks.dart
index 83a1e0d..ebf692e 100644
--- a/pkg/compiler/lib/src/common/tasks.dart
+++ b/pkg/compiler/lib/src/common/tasks.dart
@@ -208,6 +208,7 @@
 }
 
 class GenericTask extends CompilerTask {
+  @override
   final String name;
   GenericTask(this.name, Measurer measurer) : super(measurer);
 }
@@ -230,6 +231,7 @@
   final bool enableTaskMeasurements;
 
   static int _hashCodeGenerator = 197;
+  @override
   final int hashCode = _hashCodeGenerator++;
 
   Measurer({this.enableTaskMeasurements: false});
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 11c0efa..4ca6b63 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -136,9 +136,6 @@
   /// The `double` type defined in 'dart:core'.
   InterfaceType get doubleType;
 
-  /// The `Resource` type defined in 'dart:core'.
-  InterfaceType get resourceType;
-
   /// The `String` type defined in 'dart:core'.
   InterfaceType get stringType;
 
@@ -598,136 +595,165 @@
 
   /// The `Object` class defined in 'dart:core'.
   ClassEntity _objectClass;
+  @override
   ClassEntity get objectClass =>
       _objectClass ??= _findClass(coreLibrary, 'Object');
 
   /// The `bool` class defined in 'dart:core'.
   ClassEntity _boolClass;
+  @override
   ClassEntity get boolClass => _boolClass ??= _findClass(coreLibrary, 'bool');
 
   /// The `num` class defined in 'dart:core'.
   ClassEntity _numClass;
+  @override
   ClassEntity get numClass => _numClass ??= _findClass(coreLibrary, 'num');
 
   /// The `int` class defined in 'dart:core'.
   ClassEntity _intClass;
+  @override
   ClassEntity get intClass => _intClass ??= _findClass(coreLibrary, 'int');
 
   /// The `double` class defined in 'dart:core'.
   ClassEntity _doubleClass;
+  @override
   ClassEntity get doubleClass =>
       _doubleClass ??= _findClass(coreLibrary, 'double');
 
   /// The `String` class defined in 'dart:core'.
   ClassEntity _stringClass;
+  @override
   ClassEntity get stringClass =>
       _stringClass ??= _findClass(coreLibrary, 'String');
 
   /// The `Function` class defined in 'dart:core'.
   ClassEntity _functionClass;
+  @override
   ClassEntity get functionClass =>
       _functionClass ??= _findClass(coreLibrary, 'Function');
 
   /// The `Resource` class defined in 'dart:core'.
   ClassEntity _resourceClass;
+  @override
   ClassEntity get resourceClass =>
       _resourceClass ??= _findClass(coreLibrary, 'Resource');
 
   /// The `Symbol` class defined in 'dart:core'.
   ClassEntity _symbolClass;
+  @override
   ClassEntity get symbolClass =>
       _symbolClass ??= _findClass(coreLibrary, 'Symbol');
 
   /// The `Null` class defined in 'dart:core'.
   ClassEntity _nullClass;
+  @override
   ClassEntity get nullClass => _nullClass ??= _findClass(coreLibrary, 'Null');
 
   /// The `Type` class defined in 'dart:core'.
   ClassEntity _typeClass;
+  @override
   ClassEntity get typeClass => _typeClass ??= _findClass(coreLibrary, 'Type');
 
   /// The `StackTrace` class defined in 'dart:core';
   ClassEntity _stackTraceClass;
+  @override
   ClassEntity get stackTraceClass =>
       _stackTraceClass ??= _findClass(coreLibrary, 'StackTrace');
 
   /// The `List` class defined in 'dart:core';
   ClassEntity _listClass;
+  @override
   ClassEntity get listClass => _listClass ??= _findClass(coreLibrary, 'List');
 
   /// The `Set` class defined in 'dart:core'.
   ClassEntity _setClass;
+  @override
   ClassEntity get setClass => _setClass ??= _findClass(coreLibrary, 'Set');
 
   /// The `Map` class defined in 'dart:core';
   ClassEntity _mapClass;
+  @override
   ClassEntity get mapClass => _mapClass ??= _findClass(coreLibrary, 'Map');
 
   /// The `_UnmodifiableSet` class defined in 'dart:collection';
   ClassEntity _unmodifiableSetClass;
+  @override
   ClassEntity get unmodifiableSetClass => _unmodifiableSetClass ??=
       _findClass(_env.lookupLibrary(Uris.dart_collection), '_UnmodifiableSet');
 
   /// The `Iterable` class defined in 'dart:core';
   ClassEntity _iterableClass;
+  @override
   ClassEntity get iterableClass =>
       _iterableClass ??= _findClass(coreLibrary, 'Iterable');
 
   /// The `Future` class defined in 'async';.
   ClassEntity _futureClass;
+  @override
   ClassEntity get futureClass =>
       _futureClass ??= _findClass(asyncLibrary, 'Future');
 
   /// The `Stream` class defined in 'async';
   ClassEntity _streamClass;
+  @override
   ClassEntity get streamClass =>
       _streamClass ??= _findClass(asyncLibrary, 'Stream');
 
   /// The dart:core library.
   LibraryEntity _coreLibrary;
+  @override
   LibraryEntity get coreLibrary =>
       _coreLibrary ??= _env.lookupLibrary(Uris.dart_core, required: true);
 
   /// The dart:async library.
   LibraryEntity _asyncLibrary;
+  @override
   LibraryEntity get asyncLibrary =>
       _asyncLibrary ??= _env.lookupLibrary(Uris.dart_async);
 
   /// The dart:mirrors library. Null if the program doesn't access dart:mirrors.
   LibraryEntity _mirrorsLibrary;
+  @override
   LibraryEntity get mirrorsLibrary =>
       _mirrorsLibrary ??= _env.lookupLibrary(Uris.dart_mirrors);
 
   /// The dart:typed_data library.
   LibraryEntity _typedDataLibrary;
+  @override
   LibraryEntity get typedDataLibrary =>
       _typedDataLibrary ??= _env.lookupLibrary(Uris.dart__native_typed_data);
 
   LibraryEntity _jsHelperLibrary;
+  @override
   LibraryEntity get jsHelperLibrary =>
       _jsHelperLibrary ??= _env.lookupLibrary(Uris.dart__js_helper);
 
   LibraryEntity _interceptorsLibrary;
+  @override
   LibraryEntity get interceptorsLibrary =>
       _interceptorsLibrary ??= _env.lookupLibrary(Uris.dart__interceptors);
 
   LibraryEntity _foreignLibrary;
+  @override
   LibraryEntity get foreignLibrary =>
       _foreignLibrary ??= _env.lookupLibrary(Uris.dart__foreign_helper);
 
   /// Reference to the internal library to lookup functions to always inline.
   LibraryEntity _internalLibrary;
+  @override
   LibraryEntity get internalLibrary => _internalLibrary ??=
       _env.lookupLibrary(Uris.dart__internal, required: true);
 
   /// The `NativeTypedData` class from dart:typed_data.
   ClassEntity _typedDataClass;
+  @override
   ClassEntity get typedDataClass =>
       _typedDataClass ??= _findClass(typedDataLibrary, 'NativeTypedData');
 
   /// Constructor of the `Symbol` class in dart:internal. This getter will
   /// ensure that `Symbol` is resolved and lookup the constructor on demand.
   ConstructorEntity _symbolConstructorTarget;
+  @override
   ConstructorEntity get symbolConstructorTarget {
     // TODO(johnniwinther): Kernel does not include redirecting factories
     // so this cannot be found in kernel. Find a consistent way to handle
@@ -764,6 +790,7 @@
 
   /// Whether [element] is the same as [symbolConstructor]. Used to check
   /// for the constructor without computing it until it is likely to be seen.
+  @override
   bool isSymbolConstructor(ConstructorEntity element) {
     assert(element != null);
     _ensureSymbolConstructorDependencies();
@@ -773,17 +800,20 @@
 
   /// The function `identical` in dart:core.
   FunctionEntity _identicalFunction;
+  @override
   FunctionEntity get identicalFunction =>
       _identicalFunction ??= _findLibraryMember(coreLibrary, 'identical');
 
   /// Whether [element] is the `Function.apply` method. This will not
   /// resolve the apply method if it hasn't been seen yet during compilation.
+  @override
   bool isFunctionApplyMethod(MemberEntity element) =>
       element.name == 'apply' && element.enclosingClass == functionClass;
 
   /// Returns `true` if [element] is the unnamed constructor of `List`. This
   /// will not resolve the constructor if it hasn't been seen yet during
   /// compilation.
+  @override
   bool isUnnamedListConstructor(ConstructorEntity element) =>
       (element.name == '' && element.enclosingClass == listClass) ||
       (element.name == 'list' && element.enclosingClass == jsArrayClass);
@@ -791,54 +821,66 @@
   /// Returns `true` if [element] is the 'filled' constructor of `List`. This
   /// will not resolve the constructor if it hasn't been seen yet during
   /// compilation.
+  @override
   bool isFilledListConstructor(ConstructorEntity element) =>
       element.name == 'filled' && element.enclosingClass == listClass;
 
   /// The `dynamic` type.
+  @override
   DynamicType get dynamicType => _env.dynamicType;
 
   /// The `Object` type defined in 'dart:core'.
+  @override
   InterfaceType get objectType => _getRawType(objectClass);
 
   /// The `bool` type defined in 'dart:core'.
+  @override
   InterfaceType get boolType => _getRawType(boolClass);
 
   /// The `num` type defined in 'dart:core'.
+  @override
   InterfaceType get numType => _getRawType(numClass);
 
   /// The `int` type defined in 'dart:core'.
+  @override
   InterfaceType get intType => _getRawType(intClass);
 
   /// The `double` type defined in 'dart:core'.
+  @override
   InterfaceType get doubleType => _getRawType(doubleClass);
 
-  /// The `Resource` type defined in 'dart:core'.
-  InterfaceType get resourceType => _getRawType(resourceClass);
-
   /// The `String` type defined in 'dart:core'.
+  @override
   InterfaceType get stringType => _getRawType(stringClass);
 
   /// The `Symbol` type defined in 'dart:core'.
+  @override
   InterfaceType get symbolType => _getRawType(symbolClass);
 
   /// The `Function` type defined in 'dart:core'.
+  @override
   InterfaceType get functionType => _getRawType(functionClass);
 
   /// The `Null` type defined in 'dart:core'.
+  @override
   InterfaceType get nullType => _getRawType(nullClass);
 
   /// The `Type` type defined in 'dart:core'.
+  @override
   InterfaceType get typeType => _getRawType(typeClass);
 
+  @override
   InterfaceType get typeLiteralType => _getRawType(typeLiteralClass);
 
   /// The `StackTrace` type defined in 'dart:core';
+  @override
   InterfaceType get stackTraceType => _getRawType(stackTraceClass);
 
   /// Returns an instance of the `List` type defined in 'dart:core' with
   /// [elementType] as its type argument.
   ///
   /// If no type argument is provided, the canonical raw type is returned.
+  @override
   InterfaceType listType([DartType elementType]) {
     if (elementType == null) {
       return _getRawType(listClass);
@@ -850,6 +892,7 @@
   /// [elementType] as its type argument.
   ///
   /// If no type argument is provided, the canonical raw type is returned.
+  @override
   InterfaceType setType([DartType elementType]) {
     if (elementType == null) {
       return _getRawType(setClass);
@@ -861,6 +904,7 @@
   /// [keyType] and [valueType] as its type arguments.
   ///
   /// If no type arguments are provided, the canonical raw type is returned.
+  @override
   InterfaceType mapType([DartType keyType, DartType valueType]) {
     if (keyType == null && valueType == null) {
       return _getRawType(mapClass);
@@ -876,6 +920,7 @@
   /// [elementType] as its type argument.
   ///
   /// If no type argument is provided, the canonical raw type is returned.
+  @override
   InterfaceType iterableType([DartType elementType]) {
     if (elementType == null) {
       return _getRawType(iterableClass);
@@ -887,6 +932,7 @@
   /// [elementType] as its type argument.
   ///
   /// If no type argument is provided, the canonical raw type is returned.
+  @override
   InterfaceType futureType([DartType elementType]) {
     if (elementType == null) {
       return _getRawType(futureClass);
@@ -898,6 +944,7 @@
   /// [elementType] as its type argument.
   ///
   /// If no type argument is provided, the canonical raw type is returned.
+  @override
   InterfaceType streamType([DartType elementType]) {
     if (elementType == null) {
       return _getRawType(streamClass);
@@ -906,16 +953,19 @@
   }
 
   /// Returns `true` if [element] is a superclass of `String` or `num`.
+  @override
   bool isNumberOrStringSupertype(ClassEntity element) {
     return element == _findClass(coreLibrary, 'Comparable', required: false);
   }
 
   /// Returns `true` if [element] is a superclass of `String`.
+  @override
   bool isStringOnlySupertype(ClassEntity element) {
     return element == _findClass(coreLibrary, 'Pattern', required: false);
   }
 
   /// Returns `true` if [element] is a superclass of `List`.
+  @override
   bool isListSupertype(ClassEntity element) => element == iterableClass;
 
   ClassEntity _findClass(LibraryEntity library, String name,
@@ -953,6 +1003,7 @@
     return _env.createInterfaceType(cls, typeArguments);
   }
 
+  @override
   InterfaceType getConstantMapTypeFor(InterfaceType sourceType,
       {bool hasProtoKey: false, bool onlyStringKeys: false}) {
     ClassEntity classElement = onlyStringKeys
@@ -966,17 +1017,21 @@
     }
   }
 
+  @override
   InterfaceType getConstantSetTypeFor(InterfaceType sourceType) =>
       sourceType.treatAsRaw
           ? _env.getRawType(constSetLiteralClass)
           : _env.createInterfaceType(
               constSetLiteralClass, sourceType.typeArguments);
 
+  @override
   FieldEntity get symbolField => symbolImplementationField;
 
+  @override
   InterfaceType get symbolImplementationType =>
       _env.getRawType(symbolImplementationClass);
 
+  @override
   bool isDefaultEqualityImplementation(MemberEntity element) {
     assert(element.name == '==');
     ClassEntity classElement = element.enclosingClass;
@@ -988,6 +1043,7 @@
   // From dart:core
 
   ClassEntity _mapLiteralClass;
+  @override
   ClassEntity get mapLiteralClass {
     if (_mapLiteralClass == null) {
       _mapLiteralClass = _env.lookupClass(coreLibrary, 'LinkedHashMap');
@@ -1016,27 +1072,32 @@
         _env.lookupLocalClassMember(mapLiteralClass, '_makeEmpty');
   }
 
+  @override
   ConstructorEntity get mapLiteralConstructor {
     _ensureMapLiteralHelpers();
     return _mapLiteralConstructor;
   }
 
+  @override
   ConstructorEntity get mapLiteralConstructorEmpty {
     _ensureMapLiteralHelpers();
     return _mapLiteralConstructorEmpty;
   }
 
+  @override
   FunctionEntity get mapLiteralUntypedMaker {
     _ensureMapLiteralHelpers();
     return _mapLiteralUntypedMaker;
   }
 
+  @override
   FunctionEntity get mapLiteralUntypedEmptyMaker {
     _ensureMapLiteralHelpers();
     return _mapLiteralUntypedEmptyMaker;
   }
 
   ClassEntity _setLiteralClass;
+  @override
   ClassEntity get setLiteralClass => _setLiteralClass ??=
       _findClass(_env.lookupLibrary(Uris.dart_collection), 'LinkedHashSet');
 
@@ -1058,32 +1119,38 @@
         _env.lookupLocalClassMember(setLiteralClass, '_makeEmpty');
   }
 
+  @override
   ConstructorEntity get setLiteralConstructor {
     _ensureSetLiteralHelpers();
     return _setLiteralConstructor;
   }
 
+  @override
   ConstructorEntity get setLiteralConstructorEmpty {
     _ensureSetLiteralHelpers();
     return _setLiteralConstructorEmpty;
   }
 
+  @override
   FunctionEntity get setLiteralUntypedMaker {
     _ensureSetLiteralHelpers();
     return _setLiteralUntypedMaker;
   }
 
+  @override
   FunctionEntity get setLiteralUntypedEmptyMaker {
     _ensureSetLiteralHelpers();
     return _setLiteralUntypedEmptyMaker;
   }
 
   FunctionEntity _objectNoSuchMethod;
+  @override
   FunctionEntity get objectNoSuchMethod {
     return _objectNoSuchMethod ??=
         _env.lookupLocalClassMember(objectClass, Identifiers.noSuchMethod_);
   }
 
+  @override
   bool isDefaultNoSuchMethodImplementation(FunctionEntity element) {
     ClassEntity classElement = element.enclosingClass;
     return classElement == objectClass ||
@@ -1098,59 +1165,78 @@
   FunctionEntity _findAsyncHelperFunction(String name) =>
       _findLibraryMember(asyncLibrary, name);
 
+  @override
   FunctionEntity get asyncHelperStartSync =>
       _findAsyncHelperFunction("_asyncStartSync");
+  @override
   FunctionEntity get asyncHelperAwait =>
       _findAsyncHelperFunction("_asyncAwait");
+  @override
   FunctionEntity get asyncHelperReturn =>
       _findAsyncHelperFunction("_asyncReturn");
+  @override
   FunctionEntity get asyncHelperRethrow =>
       _findAsyncHelperFunction("_asyncRethrow");
 
+  @override
   FunctionEntity get wrapBody =>
       _findAsyncHelperFunction("_wrapJsFunctionForAsync");
 
+  @override
   FunctionEntity get yieldStar => _env.lookupLocalClassMember(
       _findAsyncHelperClass("_IterationMarker"), "yieldStar");
 
+  @override
   FunctionEntity get yieldSingle => _env.lookupLocalClassMember(
       _findAsyncHelperClass("_IterationMarker"), "yieldSingle");
 
+  @override
   FunctionEntity get syncStarUncaughtError => _env.lookupLocalClassMember(
       _findAsyncHelperClass("_IterationMarker"), "uncaughtError");
 
+  @override
   FunctionEntity get asyncStarHelper =>
       _findAsyncHelperFunction("_asyncStarHelper");
 
+  @override
   FunctionEntity get streamOfController =>
       _findAsyncHelperFunction("_streamOfController");
 
+  @override
   FunctionEntity get endOfIteration => _env.lookupLocalClassMember(
       _findAsyncHelperClass("_IterationMarker"), "endOfIteration");
 
+  @override
   ClassEntity get syncStarIterable =>
       _findAsyncHelperClass("_SyncStarIterable");
 
+  @override
   ClassEntity get futureImplementation => _findAsyncHelperClass('_Future');
 
+  @override
   ClassEntity get controllerStream =>
       _findAsyncHelperClass("_ControllerStream");
 
+  @override
   ClassEntity get streamIterator => _findAsyncHelperClass("StreamIterator");
 
+  @override
   ConstructorEntity get streamIteratorConstructor =>
       _env.lookupConstructor(streamIterator, "");
 
   FunctionEntity _syncStarIterableFactory;
+  @override
   FunctionEntity get syncStarIterableFactory => _syncStarIterableFactory ??=
       _findAsyncHelperFunction('_makeSyncStarIterable');
 
   FunctionEntity _asyncAwaitCompleterFactory;
+  @override
   FunctionEntity get asyncAwaitCompleterFactory =>
       _asyncAwaitCompleterFactory ??=
           _findAsyncHelperFunction('_makeAsyncAwaitCompleter');
 
   FunctionEntity _asyncStarStreamControllerFactory;
+  @override
   FunctionEntity get asyncStarStreamControllerFactory =>
       _asyncStarStreamControllerFactory ??=
           _findAsyncHelperFunction('_makeAsyncStarStreamController');
@@ -1163,92 +1249,114 @@
       _findLibraryMember(interceptorsLibrary, name);
 
   ClassEntity _jsInterceptorClass;
+  @override
   ClassEntity get jsInterceptorClass =>
       _jsInterceptorClass ??= _findInterceptorsClass('Interceptor');
 
   ClassEntity _jsStringClass;
+  @override
   ClassEntity get jsStringClass =>
       _jsStringClass ??= _findInterceptorsClass('JSString');
 
   ClassEntity _jsArrayClass;
+  @override
   ClassEntity get jsArrayClass =>
       _jsArrayClass ??= _findInterceptorsClass('JSArray');
 
   ClassEntity _jsNumberClass;
+  @override
   ClassEntity get jsNumberClass =>
       _jsNumberClass ??= _findInterceptorsClass('JSNumber');
 
   ClassEntity _jsIntClass;
+  @override
   ClassEntity get jsIntClass => _jsIntClass ??= _findInterceptorsClass('JSInt');
 
   ClassEntity _jsDoubleClass;
+  @override
   ClassEntity get jsDoubleClass =>
       _jsDoubleClass ??= _findInterceptorsClass('JSDouble');
 
   ClassEntity _jsNullClass;
+  @override
   ClassEntity get jsNullClass =>
       _jsNullClass ??= _findInterceptorsClass('JSNull');
 
   ClassEntity _jsBoolClass;
+  @override
   ClassEntity get jsBoolClass =>
       _jsBoolClass ??= _findInterceptorsClass('JSBool');
 
   ClassEntity _jsPlainJavaScriptObjectClass;
+  @override
   ClassEntity get jsPlainJavaScriptObjectClass =>
       _jsPlainJavaScriptObjectClass ??=
           _findInterceptorsClass('PlainJavaScriptObject');
 
   ClassEntity _jsUnknownJavaScriptObjectClass;
+  @override
   ClassEntity get jsUnknownJavaScriptObjectClass =>
       _jsUnknownJavaScriptObjectClass ??=
           _findInterceptorsClass('UnknownJavaScriptObject');
 
   ClassEntity _jsJavaScriptFunctionClass;
+  @override
   ClassEntity get jsJavaScriptFunctionClass => _jsJavaScriptFunctionClass ??=
       _findInterceptorsClass('JavaScriptFunction');
 
   ClassEntity _jsJavaScriptObjectClass;
+  @override
   ClassEntity get jsJavaScriptObjectClass =>
       _jsJavaScriptObjectClass ??= _findInterceptorsClass('JavaScriptObject');
 
   ClassEntity _jsIndexableClass;
+  @override
   ClassEntity get jsIndexableClass =>
       _jsIndexableClass ??= _findInterceptorsClass('JSIndexable');
 
   ClassEntity _jsMutableIndexableClass;
+  @override
   ClassEntity get jsMutableIndexableClass =>
       _jsMutableIndexableClass ??= _findInterceptorsClass('JSMutableIndexable');
 
   ClassEntity _jsMutableArrayClass;
+  @override
   ClassEntity get jsMutableArrayClass =>
       _jsMutableArrayClass ??= _findInterceptorsClass('JSMutableArray');
 
   ClassEntity _jsFixedArrayClass;
+  @override
   ClassEntity get jsFixedArrayClass =>
       _jsFixedArrayClass ??= _findInterceptorsClass('JSFixedArray');
 
   ClassEntity _jsExtendableArrayClass;
+  @override
   ClassEntity get jsExtendableArrayClass =>
       _jsExtendableArrayClass ??= _findInterceptorsClass('JSExtendableArray');
 
   ClassEntity _jsUnmodifiableArrayClass;
+  @override
   ClassEntity get jsUnmodifiableArrayClass => _jsUnmodifiableArrayClass ??=
       _findInterceptorsClass('JSUnmodifiableArray');
 
   ClassEntity _jsPositiveIntClass;
+  @override
   ClassEntity get jsPositiveIntClass =>
       _jsPositiveIntClass ??= _findInterceptorsClass('JSPositiveInt');
 
   ClassEntity _jsUInt32Class;
+  @override
   ClassEntity get jsUInt32Class =>
       _jsUInt32Class ??= _findInterceptorsClass('JSUInt32');
 
   ClassEntity _jsUInt31Class;
+  @override
   ClassEntity get jsUInt31Class =>
       _jsUInt31Class ??= _findInterceptorsClass('JSUInt31');
 
   /// Returns `true` member is the 'findIndexForNativeSubclassType' method
   /// declared in `dart:_interceptors`.
+  @override
   bool isFindIndexForNativeSubclassType(MemberEntity member) {
     return member.name == 'findIndexForNativeSubclassType' &&
         member.isTopLevel &&
@@ -1256,24 +1364,29 @@
   }
 
   FunctionEntity _getNativeInterceptorMethod;
+  @override
   FunctionEntity get getNativeInterceptorMethod =>
       _getNativeInterceptorMethod ??=
           _findInterceptorsFunction('getNativeInterceptor');
 
   /// Returns `true` if [selector] applies to `JSIndexable.length`.
+  @override
   bool appliesToJsIndexableLength(Selector selector) {
     return selector.name == 'length' && (selector.isGetter || selector.isCall);
   }
 
   ConstructorEntity _jsArrayTypedConstructor;
+  @override
   ConstructorEntity get jsArrayTypedConstructor =>
       _jsArrayTypedConstructor ??= _findConstructor(jsArrayClass, 'typed');
 
   FunctionEntity _jsArrayRemoveLast;
+  @override
   FunctionEntity get jsArrayRemoveLast =>
       _jsArrayRemoveLast ??= _findClassMember(jsArrayClass, 'removeLast');
 
   FunctionEntity _jsArrayAdd;
+  @override
   FunctionEntity get jsArrayAdd =>
       _jsArrayAdd ??= _findClassMember(jsArrayClass, 'add');
 
@@ -1281,6 +1394,7 @@
     return cls.name == 'JSString' && cls.library == interceptorsLibrary;
   }
 
+  @override
   bool isJsStringSplit(MemberEntity member) {
     return member.name == 'split' &&
         member.isInstanceMember &&
@@ -1291,6 +1405,7 @@
   /// in the given [world].
   ///
   /// Returns `false` if `JSString.split` is not available.
+  @override
   bool appliesToJsStringSplit(Selector selector, AbstractValue receiver,
       AbstractValueDomain abstractValueDomain) {
     if (_jsStringSplit == null) {
@@ -1308,23 +1423,28 @@
   }
 
   FunctionEntity _jsStringSplit;
+  @override
   FunctionEntity get jsStringSplit =>
       _jsStringSplit ??= _findClassMember(jsStringClass, 'split');
 
   FunctionEntity _jsStringToString;
+  @override
   FunctionEntity get jsStringToString =>
       _jsStringToString ??= _findClassMember(jsStringClass, 'toString');
 
   FunctionEntity _jsStringOperatorAdd;
+  @override
   FunctionEntity get jsStringOperatorAdd =>
       _jsStringOperatorAdd ??= _findClassMember(jsStringClass, '+');
 
   ClassEntity _jsConstClass;
+  @override
   ClassEntity get jsConstClass =>
       _jsConstClass ??= _findClass(foreignLibrary, 'JS_CONST');
 
   // From package:js
   ClassEntity _jsAnnotationClass;
+  @override
   ClassEntity get jsAnnotationClass {
     if (_jsAnnotationClass == null) {
       LibraryEntity library = _env.lookupLibrary(Uris.package_js);
@@ -1335,6 +1455,7 @@
   }
 
   ClassEntity _jsAnonymousClass;
+  @override
   ClassEntity get jsAnonymousClass {
     if (_jsAnonymousClass == null) {
       LibraryEntity library = _env.lookupLibrary(Uris.package_js);
@@ -1346,6 +1467,7 @@
 
   // From dart:_js_helper
   // TODO(johnniwinther): Avoid the need for this (from [CheckedModeHelper]).
+  @override
   FunctionEntity findHelperFunction(String name) => _findHelperFunction(name);
 
   FunctionEntity _findHelperFunction(String name) =>
@@ -1355,47 +1477,58 @@
       _findClass(jsHelperLibrary, name);
 
   ClassEntity _closureClass;
+  @override
   ClassEntity get closureClass => _closureClass ??= _findHelperClass('Closure');
 
   ClassEntity _boundClosureClass;
+  @override
   ClassEntity get boundClosureClass =>
       _boundClosureClass ??= _findHelperClass('BoundClosure');
 
   ClassEntity _typeLiteralClass;
+  @override
   ClassEntity get typeLiteralClass =>
       _typeLiteralClass ??= _findHelperClass('TypeImpl');
 
   ClassEntity _constMapLiteralClass;
+  @override
   ClassEntity get constMapLiteralClass =>
       _constMapLiteralClass ??= _findHelperClass('ConstantMap');
 
   // TODO(fishythefish): Implement a `ConstantSet` class and update the backend
   // impacts + constant emitter accordingly.
   ClassEntity _constSetLiteralClass;
+  @override
   ClassEntity get constSetLiteralClass =>
       _constSetLiteralClass ??= unmodifiableSetClass;
 
   ClassEntity _typeVariableClass;
+  @override
   ClassEntity get typeVariableClass =>
       _typeVariableClass ??= _findHelperClass('TypeVariable');
 
   ClassEntity _pragmaClass;
+  @override
   ClassEntity get pragmaClass =>
       _pragmaClass ??= _findClass(coreLibrary, 'pragma');
 
   FieldEntity _pragmaClassNameField;
+  @override
   FieldEntity get pragmaClassNameField =>
       _pragmaClassNameField ??= _findClassMember(pragmaClass, 'name');
 
   FieldEntity _pragmaClassOptionsField;
+  @override
   FieldEntity get pragmaClassOptionsField =>
       _pragmaClassOptionsField ??= _findClassMember(pragmaClass, 'options');
 
   ClassEntity _jsInvocationMirrorClass;
+  @override
   ClassEntity get jsInvocationMirrorClass =>
       _jsInvocationMirrorClass ??= _findHelperClass('JSInvocationMirror');
 
   MemberEntity _invocationTypeArgumentGetter;
+  @override
   MemberEntity get invocationTypeArgumentGetter =>
       _invocationTypeArgumentGetter ??=
           _findClassMember(jsInvocationMirrorClass, 'typeArguments');
@@ -1403,110 +1536,143 @@
   /// Interface used to determine if an object has the JavaScript
   /// indexing behavior. The interface is only visible to specific libraries.
   ClassEntity _jsIndexingBehaviorInterface;
+  @override
   ClassEntity get jsIndexingBehaviorInterface =>
       _jsIndexingBehaviorInterface ??=
           _findHelperClass('JavaScriptIndexingBehavior');
 
+  @override
   ClassEntity get stackTraceHelperClass => _findHelperClass('_StackTrace');
 
+  @override
   ClassEntity get constantMapClass =>
       _findHelperClass(constant_system.JavaScriptMapConstant.DART_CLASS);
+  @override
   ClassEntity get constantStringMapClass =>
       _findHelperClass(constant_system.JavaScriptMapConstant.DART_STRING_CLASS);
+  @override
   ClassEntity get constantProtoMapClass =>
       _findHelperClass(constant_system.JavaScriptMapConstant.DART_PROTO_CLASS);
+  @override
   ClassEntity get generalConstantMapClass => _findHelperClass(
       constant_system.JavaScriptMapConstant.DART_GENERAL_CLASS);
 
+  @override
   ClassEntity get annotationCreatesClass => _findHelperClass('Creates');
 
+  @override
   ClassEntity get annotationReturnsClass => _findHelperClass('Returns');
 
+  @override
   ClassEntity get annotationJSNameClass => _findHelperClass('JSName');
 
   /// The class for native annotations defined in dart:_js_helper.
   ClassEntity _nativeAnnotationClass;
+  @override
   ClassEntity get nativeAnnotationClass =>
       _nativeAnnotationClass ??= _findHelperClass('Native');
 
   ConstructorEntity _typeVariableConstructor;
+  @override
   ConstructorEntity get typeVariableConstructor => _typeVariableConstructor ??=
       _env.lookupConstructor(typeVariableClass, '');
 
   FunctionEntity _assertTest;
+  @override
   FunctionEntity get assertTest =>
       _assertTest ??= _findHelperFunction('assertTest');
 
   FunctionEntity _assertThrow;
+  @override
   FunctionEntity get assertThrow =>
       _assertThrow ??= _findHelperFunction('assertThrow');
 
   FunctionEntity _assertHelper;
+  @override
   FunctionEntity get assertHelper =>
       _assertHelper ??= _findHelperFunction('assertHelper');
 
   FunctionEntity _assertUnreachableMethod;
+  @override
   FunctionEntity get assertUnreachableMethod =>
       _assertUnreachableMethod ??= _findHelperFunction('assertUnreachable');
 
   /// Holds the method "getIsolateAffinityTag" when dart:_js_helper has been
   /// loaded.
   FunctionEntity _getIsolateAffinityTagMarker;
+  @override
   FunctionEntity get getIsolateAffinityTagMarker =>
       _getIsolateAffinityTagMarker ??=
           _findHelperFunction('getIsolateAffinityTag');
 
   /// Holds the method "requiresPreamble" in _js_helper.
   FunctionEntity _requiresPreambleMarker;
+  @override
   FunctionEntity get requiresPreambleMarker =>
       _requiresPreambleMarker ??= _findHelperFunction('requiresPreamble');
 
+  @override
   FunctionEntity get loadLibraryWrapper =>
       _findHelperFunction("_loadLibraryWrapper");
 
+  @override
   FunctionEntity get loadDeferredLibrary =>
       _findHelperFunction("loadDeferredLibrary");
 
+  @override
   FunctionEntity get boolConversionCheck =>
       _findHelperFunction('boolConversionCheck');
 
+  @override
   FunctionEntity get traceHelper => _findHelperFunction('traceHelper');
 
+  @override
   FunctionEntity get closureFromTearOff =>
       _findHelperFunction('closureFromTearOff');
 
+  @override
   FunctionEntity get isJsIndexable => _findHelperFunction('isJsIndexable');
 
+  @override
   FunctionEntity get throwIllegalArgumentException =>
       _findHelperFunction('iae');
 
+  @override
   FunctionEntity get throwIndexOutOfRangeException =>
       _findHelperFunction('ioore');
 
+  @override
   FunctionEntity get exceptionUnwrapper =>
       _findHelperFunction('unwrapException');
 
+  @override
   FunctionEntity get throwRuntimeError =>
       _findHelperFunction('throwRuntimeError');
 
+  @override
   FunctionEntity get throwUnsupportedError =>
       _findHelperFunction('throwUnsupportedError');
 
+  @override
   FunctionEntity get throwTypeError => _findHelperFunction('throwTypeError');
 
+  @override
   FunctionEntity get throwAbstractClassInstantiationError =>
       _findHelperFunction('throwAbstractClassInstantiationError');
 
   FunctionEntity _cachedCheckConcurrentModificationError;
+  @override
   FunctionEntity get checkConcurrentModificationError =>
       _cachedCheckConcurrentModificationError ??=
           _findHelperFunction('checkConcurrentModificationError');
 
+  @override
   FunctionEntity get throwConcurrentModificationError =>
       _findHelperFunction('throwConcurrentModificationError');
 
   /// Return `true` if [member] is the 'checkInt' function defined in
   /// dart:_js_helpers.
+  @override
   bool isCheckInt(MemberEntity member) {
     return member.isFunction &&
         member.isTopLevel &&
@@ -1516,6 +1682,7 @@
 
   /// Return `true` if [member] is the 'checkNum' function defined in
   /// dart:_js_helpers.
+  @override
   bool isCheckNum(MemberEntity member) {
     return member.isFunction &&
         member.isTopLevel &&
@@ -1525,6 +1692,7 @@
 
   /// Return `true` if [member] is the 'checkString' function defined in
   /// dart:_js_helpers.
+  @override
   bool isCheckString(MemberEntity member) {
     return member.isFunction &&
         member.isTopLevel &&
@@ -1532,92 +1700,123 @@
         member.name == 'checkString';
   }
 
+  @override
   FunctionEntity get stringInterpolationHelper => _findHelperFunction('S');
 
+  @override
   FunctionEntity get wrapExceptionHelper =>
       _findHelperFunction('wrapException');
 
+  @override
   FunctionEntity get throwExpressionHelper =>
       _findHelperFunction('throwExpression');
 
+  @override
   FunctionEntity get closureConverter =>
       _findHelperFunction('convertDartClosureToJS');
 
+  @override
   FunctionEntity get traceFromException =>
       _findHelperFunction('getTraceFromException');
 
+  @override
   FunctionEntity get setRuntimeTypeInfo =>
       _findHelperFunction('setRuntimeTypeInfo');
 
+  @override
   FunctionEntity get getRuntimeTypeInfo =>
       _findHelperFunction('getRuntimeTypeInfo');
 
+  @override
   FunctionEntity get getTypeArgumentByIndex =>
       _findHelperFunction('getTypeArgumentByIndex');
 
+  @override
   FunctionEntity get computeSignature =>
       _findHelperFunction('computeSignature');
 
+  @override
   FunctionEntity get getRuntimeTypeArguments =>
       _findHelperFunction('getRuntimeTypeArguments');
 
+  @override
   FunctionEntity get getRuntimeTypeArgument =>
       _findHelperFunction('getRuntimeTypeArgument');
 
+  @override
   FunctionEntity get getRuntimeTypeArgumentIntercepted =>
       _findHelperFunction('getRuntimeTypeArgumentIntercepted');
 
+  @override
   FunctionEntity get assertIsSubtype => _findHelperFunction('assertIsSubtype');
 
+  @override
   FunctionEntity get checkSubtype => _findHelperFunction('checkSubtype');
 
+  @override
   FunctionEntity get assertSubtype => _findHelperFunction('assertSubtype');
 
+  @override
   FunctionEntity get subtypeCast => _findHelperFunction('subtypeCast');
 
+  @override
   FunctionEntity get functionTypeTest =>
       _findHelperFunction('functionTypeTest');
 
+  @override
   FunctionEntity get futureOrTest => _findHelperFunction('futureOrTest');
 
+  @override
   FunctionEntity get checkSubtypeOfRuntimeType =>
       _findHelperFunction('checkSubtypeOfRuntimeType');
 
+  @override
   FunctionEntity get assertSubtypeOfRuntimeType =>
       _findHelperFunction('assertSubtypeOfRuntimeType');
 
+  @override
   FunctionEntity get subtypeOfRuntimeTypeCast =>
       _findHelperFunction('subtypeOfRuntimeTypeCast');
 
+  @override
   FunctionEntity get checkDeferredIsLoaded =>
       _findHelperFunction('checkDeferredIsLoaded');
 
+  @override
   FunctionEntity get throwNoSuchMethod =>
       _findHelperFunction('throwNoSuchMethod');
 
+  @override
   FunctionEntity get createRuntimeType =>
       _findHelperFunction('createRuntimeType');
 
+  @override
   FunctionEntity get fallThroughError =>
       _findHelperFunction("getFallThroughError");
 
+  @override
   FunctionEntity get createInvocationMirror =>
       _findHelperFunction('createInvocationMirror');
 
+  @override
   bool isCreateInvocationMirrorHelper(MemberEntity member) {
     return member.isTopLevel &&
         member.name == '_createInvocationMirror' &&
         member.library == coreLibrary;
   }
 
+  @override
   FunctionEntity get createUnmangledInvocationMirror =>
       _findHelperFunction('createUnmangledInvocationMirror');
 
+  @override
   FunctionEntity get cyclicThrowHelper =>
       _findHelperFunction("throwCyclicInit");
 
+  @override
   FunctionEntity get defineProperty => _findHelperFunction('defineProperty');
 
+  @override
   bool isExtractTypeArguments(FunctionEntity member) {
     return member.name == 'extractTypeArguments' &&
         member.library == internalLibrary;
@@ -1634,22 +1833,27 @@
     }
   }
 
+  @override
   ClassEntity getInstantiationClass(int typeArgumentCount) {
     _checkTypeArgumentCount(typeArgumentCount);
     return _findHelperClass('Instantiation$typeArgumentCount');
   }
 
+  @override
   FunctionEntity getInstantiateFunction(int typeArgumentCount) {
     _checkTypeArgumentCount(typeArgumentCount);
     return _findHelperFunction('instantiate$typeArgumentCount');
   }
 
+  @override
   FunctionEntity get instantiatedGenericFunctionType =>
       _findHelperFunction('instantiatedGenericFunctionType');
 
+  @override
   FunctionEntity get extractFunctionTypeObjectFromInternal =>
       _findHelperFunction('extractFunctionTypeObjectFromInternal');
 
+  @override
   bool isInstantiationClass(ClassEntity cls) {
     return cls.library == _jsHelperLibrary &&
         cls.name != 'Instantiation' &&
@@ -1659,15 +1863,19 @@
   // From dart:_internal
 
   ClassEntity _symbolImplementationClass;
+  @override
   ClassEntity get symbolImplementationClass =>
       _symbolImplementationClass ??= _findClass(internalLibrary, 'Symbol');
 
   /// Used to annotate items that have the keyword "native".
   ClassEntity _externalNameClass;
+  @override
   ClassEntity get externalNameClass =>
       _externalNameClass ??= _findClass(internalLibrary, 'ExternalName');
+  @override
   InterfaceType get externalNameType => _getRawType(externalNameClass);
 
+  @override
   ConstructorEntity get symbolValidatedConstructor =>
       _symbolValidatedConstructor ??=
           _findConstructor(symbolImplementationClass, 'validated');
@@ -1680,6 +1888,7 @@
           required: true);
 
   ConstructorEntity _symbolValidatedConstructor;
+  @override
   bool isSymbolValidatedConstructor(ConstructorEntity element) {
     if (_symbolValidatedConstructor != null) {
       return element == _symbolValidatedConstructor;
@@ -1690,11 +1899,13 @@
   // From dart:_native_typed_data
 
   ClassEntity _typedArrayOfIntClass;
+  @override
   ClassEntity get typedArrayOfIntClass => _typedArrayOfIntClass ??= _findClass(
       _env.lookupLibrary(Uris.dart__native_typed_data, required: true),
       'NativeTypedArrayOfInt');
 
   ClassEntity _typedArrayOfDoubleClass;
+  @override
   ClassEntity get typedArrayOfDoubleClass =>
       _typedArrayOfDoubleClass ??= _findClass(
           _env.lookupLibrary(Uris.dart__native_typed_data, required: true),
@@ -1704,19 +1915,18 @@
 
   /// Holds the class for the [JsGetName] enum.
   ClassEntity _jsGetNameEnum;
+  @override
   ClassEntity get jsGetNameEnum => _jsGetNameEnum ??= _findClass(
       _env.lookupLibrary(Uris.dart__js_embedded_names, required: true),
       'JsGetName');
 
   /// Holds the class for the [JsBuiltins] enum.
   ClassEntity _jsBuiltinEnum;
+  @override
   ClassEntity get jsBuiltinEnum => _jsBuiltinEnum ??= _findClass(
       _env.lookupLibrary(Uris.dart__js_embedded_names, required: true),
       'JsBuiltin');
 
-  static final Uri PACKAGE_META_DART2JS =
-      new Uri(scheme: 'package', path: 'meta/dart2js.dart');
-
   bool _metaAnnotationChecked = false;
   ClassEntity _metaNoInlineClass;
   ClassEntity _metaTryInlineClass;
@@ -1724,7 +1934,7 @@
   void _ensureMetaAnnotations() {
     if (!_metaAnnotationChecked) {
       _metaAnnotationChecked = true;
-      LibraryEntity library = _env.lookupLibrary(PACKAGE_META_DART2JS);
+      LibraryEntity library = _env.lookupLibrary(Uris.package_meta_dart2js);
       if (library != null) {
         _metaNoInlineClass = _env.lookupClass(library, '_NoInline');
         _metaTryInlineClass = _env.lookupClass(library, '_TryInline');
@@ -1737,22 +1947,26 @@
     }
   }
 
+  @override
   ClassEntity get metaNoInlineClass {
     _ensureMetaAnnotations();
     return _metaNoInlineClass;
   }
 
+  @override
   ClassEntity get metaTryInlineClass {
     _ensureMetaAnnotations();
     return _metaTryInlineClass;
   }
 
+  @override
   bool isForeign(MemberEntity element) => element.library == foreignLibrary;
 
   /// Returns `true` if [member] is a "foreign helper", that is, a member whose
   /// semantics is defined synthetically and not through Dart code.
   ///
   /// Most foreign helpers are located in the `dart:_foreign_helper` library.
+  @override
   bool isForeignHelper(MemberEntity member) {
     return member.library == foreignLibrary ||
         isCreateInvocationMirrorHelper(member);
@@ -1765,6 +1979,7 @@
   ///
   /// This returns `false` for JS interop members which therefore must be
   /// allowed to be external through the JS interop annotation handling.
+  @override
   bool isExternalAllowed(FunctionEntity function) {
     return isForeignHelper(function) ||
         (function is ConstructorEntity &&
@@ -1777,6 +1992,7 @@
 
   /// Returns `true` if the implementation of the 'operator ==' [function] is
   /// known to handle `null` as argument.
+  @override
   bool operatorEqHandlesNullArgument(FunctionEntity function) {
     assert(function.name == '==',
         failedAt(function, "Unexpected function $function."));
@@ -1786,6 +2002,7 @@
         cls == jsNullClass;
   }
 
+  @override
   ClassEntity getDefaultSuperclass(
       ClassEntity cls, NativeBasicData nativeBasicData) {
     if (nativeBasicData.isJsInteropClass(cls)) {
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index baffff3..2eb6455 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -673,6 +673,7 @@
 
 class CompilerDiagnosticReporter extends DiagnosticReporter {
   final Compiler compiler;
+  @override
   final DiagnosticOptions options;
 
   Entity _currentElement;
@@ -690,6 +691,7 @@
 
   Entity get currentElement => _currentElement;
 
+  @override
   DiagnosticMessage createMessage(Spannable spannable, MessageKind messageKind,
       [Map arguments = const {}]) {
     SourceSpan span = spanFromSpannable(spannable);
@@ -698,22 +700,26 @@
     return new DiagnosticMessage(span, spannable, message);
   }
 
+  @override
   void reportError(DiagnosticMessage message,
       [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
     reportDiagnosticInternal(message, infos, api.Diagnostic.ERROR);
   }
 
+  @override
   void reportWarning(DiagnosticMessage message,
       [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
     reportDiagnosticInternal(message, infos, api.Diagnostic.WARNING);
   }
 
+  @override
   void reportHint(DiagnosticMessage message,
       [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
     reportDiagnosticInternal(message, infos, api.Diagnostic.HINT);
   }
 
   @deprecated
+  @override
   void reportInfo(Spannable node, MessageKind messageKind,
       [Map arguments = const {}]) {
     reportDiagnosticInternal(createMessage(node, messageKind, arguments),
@@ -779,6 +785,7 @@
   /// Perform an operation, [f], returning the return value from [f].  If an
   /// error occurs then report it as having occurred during compilation of
   /// [element].  Can be nested.
+  @override
   withCurrentElement(Entity element, f()) {
     Entity old = currentElement;
     _currentElement = element;
@@ -832,6 +839,7 @@
     throw 'No error location.';
   }
 
+  @override
   SourceSpan spanFromSpannable(Spannable spannable) {
     if (spannable == CURRENT_ELEMENT_SPANNABLE) {
       spannable = currentElement;
@@ -852,6 +860,7 @@
     }
   }
 
+  @override
   internalError(Spannable spannable, reason) {
     String message = tryToString(reason);
     reportDiagnosticInternal(
@@ -886,6 +895,7 @@
     return element != null ? element : currentElement;
   }
 
+  @override
   void log(message) {
     Message msg = MessageTemplate.TEMPLATES[MessageKind.GENERIC]
         .message({'text': '$message'});
@@ -953,11 +963,13 @@
   final Map<Entity, WorldImpact> _impactCache;
   _MapImpactCacheDeleter(this._impactCache);
 
+  @override
   void uncacheWorldImpact(Entity element) {
     if (retainDataForTesting) return;
     _impactCache.remove(element);
   }
 
+  @override
   void emptyCache() {
     if (retainDataForTesting) return;
     _impactCache.clear();
@@ -967,6 +979,7 @@
 class _EmptyEnvironment implements Environment {
   const _EmptyEnvironment();
 
+  @override
   String valueOf(String key) => null;
 }
 
@@ -990,6 +1003,7 @@
 
   ProgressImpl(this._reporter);
 
+  @override
   void showProgress(String prefix, int count, String suffix) {
     if (_stopwatch.elapsedMilliseconds > 500) {
       _reporter.log('$prefix$count$suffix');
@@ -997,6 +1011,7 @@
     }
   }
 
+  @override
   void startPhase() {
     _stopwatch.reset();
   }
@@ -1008,12 +1023,14 @@
 class InteractiveProgress implements Progress {
   final Stopwatch _stopwatchPhase = new Stopwatch()..start();
   final Stopwatch _stopwatchInterval = new Stopwatch()..start();
+  @override
   void startPhase() {
     print('');
     _stopwatchPhase.reset();
     _stopwatchInterval.reset();
   }
 
+  @override
   void showProgress(String prefix, int count, String suffix) {
     if (_stopwatchInterval.elapsedMilliseconds > 500) {
       var time = _stopwatchPhase.elapsedMilliseconds / 1000;
diff --git a/pkg/compiler/lib/src/constants/constant_system.dart b/pkg/compiler/lib/src/constants/constant_system.dart
index 701fc39..40ef21c 100644
--- a/pkg/compiler/lib/src/constants/constant_system.dart
+++ b/pkg/compiler/lib/src/constants/constant_system.dart
@@ -1001,8 +1001,10 @@
       List<ConstantValue> values, this.protoValue, this.onlyStringKeys)
       : this.keyList = keyList,
         super(type, keyList.entries, values);
+  @override
   bool get isMap => true;
 
+  @override
   List<ConstantValue> getDependencies() {
     List<ConstantValue> result = <ConstantValue>[];
     if (onlyStringKeys) {
diff --git a/pkg/compiler/lib/src/constants/constructors.dart b/pkg/compiler/lib/src/constants/constructors.dart
index e575b5a..3b9fb60 100644
--- a/pkg/compiler/lib/src/constants/constructors.dart
+++ b/pkg/compiler/lib/src/constants/constructors.dart
@@ -74,13 +74,16 @@
   GenerativeConstantConstructor(this.type, this.defaultValues, this.fieldMap,
       this.assertions, this.superConstructorInvocation);
 
+  @override
   ConstantConstructorKind get kind => ConstantConstructorKind.GENERATIVE;
 
+  @override
   InterfaceType computeInstanceType(
       EvaluationEnvironment environment, InterfaceType newType) {
     return environment.substByContext(type, newType);
   }
 
+  @override
   InstanceData computeInstanceData(EvaluationEnvironment environment,
       List<ConstantExpression> arguments, CallStructure callStructure) {
     NormalizedArguments args =
@@ -96,10 +99,12 @@
     return appliedInstanceData;
   }
 
+  @override
   accept(ConstantConstructorVisitor visitor, arg) {
     return visitor.visitGenerative(this, arg);
   }
 
+  @override
   int get hashCode {
     int hash = Hashing.objectHash(type);
     hash = Hashing.mapHash(defaultValues, hash);
@@ -107,6 +112,7 @@
     return Hashing.objectHash(superConstructorInvocation, hash);
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! GenerativeConstantConstructor) return false;
@@ -116,6 +122,7 @@
         mapEquals(fieldMap, other.fieldMap);
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write("{'type': $type");
@@ -181,16 +188,19 @@
   RedirectingGenerativeConstantConstructor(
       this.defaultValues, this.thisConstructorInvocation);
 
+  @override
   ConstantConstructorKind get kind {
     return ConstantConstructorKind.REDIRECTING_GENERATIVE;
   }
 
+  @override
   InterfaceType computeInstanceType(
       EvaluationEnvironment environment, InterfaceType newType) {
     return environment.substByContext(
         thisConstructorInvocation.computeInstanceType(environment), newType);
   }
 
+  @override
   InstanceData computeInstanceData(EvaluationEnvironment environment,
       List<ConstantExpression> arguments, CallStructure callStructure) {
     NormalizedArguments args =
@@ -201,15 +211,18 @@
     return appliedInstanceData;
   }
 
+  @override
   accept(ConstantConstructorVisitor visitor, arg) {
     return visitor.visitRedirectingGenerative(this, arg);
   }
 
+  @override
   int get hashCode {
     int hash = Hashing.objectHash(thisConstructorInvocation);
     return Hashing.mapHash(defaultValues, hash);
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! RedirectingGenerativeConstantConstructor) return false;
@@ -218,6 +231,7 @@
             defaultValues, other.defaultValues);
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write("{'type': ${thisConstructorInvocation.type}");
@@ -236,16 +250,19 @@
 
   RedirectingFactoryConstantConstructor(this.targetConstructorInvocation);
 
+  @override
   ConstantConstructorKind get kind {
     return ConstantConstructorKind.REDIRECTING_FACTORY;
   }
 
+  @override
   InterfaceType computeInstanceType(
       EvaluationEnvironment environment, InterfaceType newType) {
     return environment.substByContext(
         targetConstructorInvocation.computeInstanceType(environment), newType);
   }
 
+  @override
   InstanceData computeInstanceData(EvaluationEnvironment environment,
       List<ConstantExpression> arguments, CallStructure callStructure) {
     ConstantConstructor constantConstructor =
@@ -254,20 +271,24 @@
         environment, arguments, callStructure);
   }
 
+  @override
   accept(ConstantConstructorVisitor visitor, arg) {
     return visitor.visitRedirectingFactory(this, arg);
   }
 
+  @override
   int get hashCode {
     return Hashing.objectHash(targetConstructorInvocation);
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! RedirectingFactoryConstantConstructor) return false;
     return targetConstructorInvocation == other.targetConstructorInvocation;
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write("{");
diff --git a/pkg/compiler/lib/src/constants/evaluation.dart b/pkg/compiler/lib/src/constants/evaluation.dart
index e9ac77a..f360735 100644
--- a/pkg/compiler/lib/src/constants/evaluation.dart
+++ b/pkg/compiler/lib/src/constants/evaluation.dart
@@ -71,6 +71,7 @@
 
 abstract class EvaluationEnvironmentBase implements EvaluationEnvironment {
   Link<Spannable> _spannableStack = const Link<Spannable>();
+  @override
   InterfaceType enclosingConstructedType;
   final Set<FieldEntity> _currentlyEvaluatedFields = new Set<FieldEntity>();
   final bool constantRequired;
@@ -79,6 +80,7 @@
     _spannableStack = _spannableStack.prepend(spannable);
   }
 
+  @override
   bool get checkCasts => true;
 
   DiagnosticReporter get reporter;
@@ -239,6 +241,7 @@
     return value;
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('NormalizedArguments[');
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index d0abc41..bb24531 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -99,10 +99,12 @@
 
   int _computeHashCode();
 
+  @override
   int get hashCode => _hashCode ??= _computeHashCode();
 
   bool _equals(covariant ConstantExpression other);
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! ConstantExpression) return false;
@@ -111,6 +113,7 @@
     return _equals(other);
   }
 
+  @override
   String toString() {
     assertDebugMode('Use ConstantExpression.toDartText() or '
         'ConstantExpression.toStructuredText() instead of '
@@ -136,8 +139,10 @@
 
 /// A synthetic constant used to recover from errors.
 class ErroneousConstantExpression extends ConstantExpression {
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.ERRONEOUS;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     // Do nothing. This is an error.
   }
@@ -166,8 +171,10 @@
 
   BoolConstantExpression(this.boolValue);
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.BOOL;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitBool(this, context);
   }
@@ -201,8 +208,10 @@
 
   IntConstantExpression(this.intValue);
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.INT;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitInt(this, context);
   }
@@ -236,8 +245,10 @@
 
   DoubleConstantExpression(this.doubleValue);
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.DOUBLE;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitDouble(this, context);
   }
@@ -271,8 +282,10 @@
 
   StringConstantExpression(this.stringValue);
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.STRING;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitString(this, context);
   }
@@ -304,8 +317,10 @@
 class NullConstantExpression extends ConstantExpression {
   NullConstantExpression();
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.NULL;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitNull(this, context);
   }
@@ -338,8 +353,10 @@
 
   ListConstantExpression(this.type, this.values);
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.LIST;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitList(this, context);
   }
@@ -362,6 +379,7 @@
         type, values.map((v) => v.evaluate(environment)).toList());
   }
 
+  @override
   ConstantExpression apply(NormalizedArguments arguments) {
     return new ListConstantExpression(
         type, values.map((v) => v.apply(arguments)).toList());
@@ -475,8 +493,10 @@
 
   MapConstantExpression(this.type, this.keys, this.values);
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.MAP;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitMap(this, context);
   }
@@ -519,6 +539,7 @@
     });
   }
 
+  @override
   ConstantExpression apply(NormalizedArguments arguments) {
     return new MapConstantExpression(
         type,
@@ -571,8 +592,10 @@
     assert(!arguments.contains(null));
   }
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.CONSTRUCTED;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitConstructed(this, context);
   }
@@ -605,6 +628,7 @@
         .computeInstanceType(environment, type);
   }
 
+  @override
   ConstructedConstantExpression apply(NormalizedArguments arguments) {
     return new ConstructedConstantExpression(type, target, callStructure,
         this.arguments.map((a) => a.apply(arguments)).toList());
@@ -683,8 +707,10 @@
 
   ConcatenateConstantExpression(this.expressions);
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.CONCATENATE;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitConcatenate(this, context);
   }
@@ -701,6 +727,7 @@
     sb.write('])');
   }
 
+  @override
   ConstantExpression apply(NormalizedArguments arguments) {
     return new ConcatenateConstantExpression(
         expressions.map((a) => a.apply(arguments)).toList());
@@ -782,8 +809,10 @@
 
   SymbolConstantExpression(this.name);
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.SYMBOL;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitSymbol(this, context);
   }
@@ -822,8 +851,10 @@
         "Unexpected type constant type: $type");
   }
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.TYPE;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitType(this, context);
   }
@@ -859,8 +890,10 @@
 
   AsConstantExpression(this.expression, this.type);
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.AS;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitAs(this, context);
   }
@@ -936,8 +969,10 @@
 
   FieldConstantExpression(this.element);
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.FIELD;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitField(this, context);
   }
@@ -970,8 +1005,10 @@
 
   LocalVariableConstantExpression(this.element);
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.LOCAL_VARIABLE;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitLocalVariable(this, context);
   }
@@ -1003,8 +1040,10 @@
 
   FunctionConstantExpression(this.element, this.type);
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.FUNCTION;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitFunction(this, context);
   }
@@ -1046,8 +1085,10 @@
   static bool potentialOperator(BinaryOperator operator) =>
       PRECEDENCE_MAP[operator.kind] != null;
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.BINARY;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitBinary(this, context);
   }
@@ -1302,11 +1343,13 @@
     return new NonConstantValue();
   }
 
+  @override
   ConstantExpression apply(NormalizedArguments arguments) {
     return new BinaryConstantExpression(
         left.apply(arguments), operator, right.apply(arguments));
   }
 
+  @override
   // ignore: MISSING_RETURN
   InterfaceType getKnownType(CommonElements commonElements) {
     DartType knownLeftType = left.getKnownType(commonElements);
@@ -1359,6 +1402,7 @@
     }
   }
 
+  @override
   int get precedence => PRECEDENCE_MAP[operator.kind];
 
   @override
@@ -1410,8 +1454,10 @@
 
   IdenticalConstantExpression(this.left, this.right);
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.IDENTICAL;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitIdentical(this, context);
   }
@@ -1435,11 +1481,13 @@
     return new NonConstantValue();
   }
 
+  @override
   ConstantExpression apply(NormalizedArguments arguments) {
     return new IdenticalConstantExpression(
         left.apply(arguments), right.apply(arguments));
   }
 
+  @override
   int get precedence => 15;
 
   @override
@@ -1471,8 +1519,10 @@
     assert(PRECEDENCE_MAP[operator.kind] != null);
   }
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.UNARY;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitUnary(this, context);
   }
@@ -1533,10 +1583,12 @@
     return new NonConstantValue();
   }
 
+  @override
   ConstantExpression apply(NormalizedArguments arguments) {
     return new UnaryConstantExpression(operator, expression.apply(arguments));
   }
 
+  @override
   int get precedence => PRECEDENCE_MAP[operator.kind];
 
   @override
@@ -1572,8 +1624,10 @@
 
   StringLengthConstantExpression(this.expression);
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.STRING_LENGTH;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitStringLength(this, context);
   }
@@ -1602,10 +1656,12 @@
     }
   }
 
+  @override
   ConstantExpression apply(NormalizedArguments arguments) {
     return new StringLengthConstantExpression(expression.apply(arguments));
   }
 
+  @override
   int get precedence => 15;
 
   @override
@@ -1636,8 +1692,10 @@
 
   ConditionalConstantExpression(this.condition, this.trueExp, this.falseExp);
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.CONDITIONAL;
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitConditional(this, context);
   }
@@ -1653,11 +1711,13 @@
     sb.write(')');
   }
 
+  @override
   ConstantExpression apply(NormalizedArguments arguments) {
     return new ConditionalConstantExpression(condition.apply(arguments),
         trueExp.apply(arguments), falseExp.apply(arguments));
   }
 
+  @override
   int get precedence => 3;
 
   @override
@@ -1720,10 +1780,12 @@
 
   PositionalArgumentReference(this.index);
 
+  @override
   ConstantExpressionKind get kind {
     return ConstantExpressionKind.POSITIONAL_REFERENCE;
   }
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitPositional(this, context);
   }
@@ -1733,6 +1795,7 @@
     sb.write('Positional(index=$index)');
   }
 
+  @override
   ConstantExpression apply(NormalizedArguments arguments) {
     return arguments.getPositionalArgument(index);
   }
@@ -1758,10 +1821,12 @@
 
   NamedArgumentReference(this.name);
 
+  @override
   ConstantExpressionKind get kind {
     return ConstantExpressionKind.NAMED_REFERENCE;
   }
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitNamed(this, context);
   }
@@ -1771,6 +1836,7 @@
     sb.write('Named(name=$name)');
   }
 
+  @override
   ConstantExpression apply(NormalizedArguments arguments) {
     return arguments.getNamedArgument(name);
   }
@@ -1838,10 +1904,12 @@
       ConstantExpression name, ConstantExpression defaultValue)
       : super(name, defaultValue);
 
+  @override
   ConstantExpressionKind get kind {
     return ConstantExpressionKind.BOOL_FROM_ENVIRONMENT;
   }
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitBoolFromEnvironment(this, context);
   }
@@ -1898,6 +1966,7 @@
     return new NonConstantValue();
   }
 
+  @override
   ConstantExpression apply(NormalizedArguments arguments) {
     return new BoolFromEnvironmentConstantExpression(name.apply(arguments),
         defaultValue != null ? defaultValue.apply(arguments) : null);
@@ -1915,10 +1984,12 @@
       ConstantExpression name, ConstantExpression defaultValue)
       : super(name, defaultValue);
 
+  @override
   ConstantExpressionKind get kind {
     return ConstantExpressionKind.INT_FROM_ENVIRONMENT;
   }
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitIntFromEnvironment(this, context);
   }
@@ -1977,6 +2048,7 @@
     return new NonConstantValue();
   }
 
+  @override
   ConstantExpression apply(NormalizedArguments arguments) {
     return new IntFromEnvironmentConstantExpression(name.apply(arguments),
         defaultValue != null ? defaultValue.apply(arguments) : null);
@@ -1994,10 +2066,12 @@
       ConstantExpression name, ConstantExpression defaultValue)
       : super(name, defaultValue);
 
+  @override
   ConstantExpressionKind get kind {
     return ConstantExpressionKind.STRING_FROM_ENVIRONMENT;
   }
 
+  @override
   accept(ConstantExpressionVisitor visitor, [context]) {
     return visitor.visitStringFromEnvironment(this, context);
   }
@@ -2052,6 +2126,7 @@
     return new NonConstantValue();
   }
 
+  @override
   ConstantExpression apply(NormalizedArguments arguments) {
     return new StringFromEnvironmentConstantExpression(name.apply(arguments),
         defaultValue != null ? defaultValue.apply(arguments) : null);
@@ -2133,6 +2208,7 @@
     return visitor.visitAssert(this, context);
   }
 
+  @override
   ConstantExpression apply(NormalizedArguments arguments) {
     return new AssertConstantExpression(
         condition.apply(arguments), message?.apply(arguments));
@@ -2145,6 +2221,7 @@
 
   InstantiationConstantExpression(this.typeArguments, this.expression);
 
+  @override
   ConstantExpressionKind get kind => ConstantExpressionKind.INSTANTIATION;
 
   @override
@@ -2167,6 +2244,7 @@
     return Hashing.objectHash(expression, Hashing.listHash(typeArguments));
   }
 
+  @override
   ConstantExpression apply(NormalizedArguments arguments) {
     return new InstantiationConstantExpression(
         typeArguments, expression.apply(arguments));
@@ -2527,5 +2605,6 @@
     sb.write(')');
   }
 
+  @override
   String toString() => sb.toString();
 }
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index dc26f40..98af5f5 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -113,6 +113,7 @@
 
   ConstantValueKind get kind;
 
+  @override
   String toString() {
     assertDebugMode("Use ConstantValue.toDartText() or "
         "ConstantValue.toStructuredText() "
@@ -128,23 +129,31 @@
 
   FunctionConstantValue(this.element, this.type);
 
+  @override
   bool get isFunction => true;
 
+  @override
   bool operator ==(var other) {
     if (other is! FunctionConstantValue) return false;
     return identical(other.element, element);
   }
 
+  @override
   List<ConstantValue> getDependencies() => const <ConstantValue>[];
 
+  @override
   FunctionType getType(CommonElements types) => type;
 
+  @override
   int get hashCode => (17 * element.hashCode) & 0x7fffffff;
 
+  @override
   accept(ConstantValueVisitor visitor, arg) => visitor.visitFunction(this, arg);
 
+  @override
   ConstantValueKind get kind => ConstantValueKind.FUNCTION;
 
+  @override
   String toDartText() {
     if (element.enclosingClass != null) {
       return '${element.enclosingClass.name}.${element.name}';
@@ -153,6 +162,7 @@
     }
   }
 
+  @override
   String toStructuredText() {
     return 'FunctionConstant(${toDartText()})';
   }
@@ -161,16 +171,20 @@
 abstract class PrimitiveConstantValue extends ConstantValue {
   const PrimitiveConstantValue();
 
+  @override
   bool get isPrimitive => true;
 
+  @override
   bool operator ==(var other) {
     // Making this method abstract does not give us an error.
     throw new UnsupportedError('PrimitiveConstant.==');
   }
 
+  @override
   int get hashCode => throw new UnsupportedError('PrimitiveConstant.hashCode');
 
   // Primitive constants don't have dependencies.
+  @override
   List<ConstantValue> getDependencies() => const <ConstantValue>[];
 }
 
@@ -182,27 +196,36 @@
 
   const NullConstantValue._internal();
 
+  @override
   bool get isNull => true;
 
+  @override
   DartType getType(CommonElements types) => types.nullType;
 
+  @override
   bool operator ==(other) => other is NullConstantValue;
 
   // The magic constant has no meaning. It is just a random value.
+  @override
   int get hashCode => 785965825;
 
+  @override
   accept(ConstantValueVisitor visitor, arg) => visitor.visitNull(this, arg);
 
+  @override
   ConstantValueKind get kind => ConstantValueKind.NULL;
 
+  @override
   String toStructuredText() => 'NullConstant';
 
+  @override
   String toDartText() => 'null';
 }
 
 abstract class NumConstantValue extends PrimitiveConstantValue {
   double get doubleValue;
 
+  @override
   bool get isNum => true;
 
   const NumConstantValue();
@@ -215,6 +238,7 @@
   // to create new ones every time those values are used.
   static Map<BigInt, IntConstantValue> _cachedValues = {};
 
+  @override
   double get doubleValue => intValue.toDouble();
 
   factory IntConstantValue(BigInt value) {
@@ -230,6 +254,7 @@
 
   const IntConstantValue._internal(this.intValue);
 
+  @override
   bool get isInt => true;
 
   bool isUInt31() => intValue.toUnsigned(31) == intValue;
@@ -238,12 +263,16 @@
 
   bool isPositive() => intValue >= BigInt.zero;
 
+  @override
   bool get isZero => intValue == BigInt.zero;
 
+  @override
   bool get isOne => intValue == BigInt.one;
 
+  @override
   DartType getType(CommonElements types) => types.intType;
 
+  @override
   bool operator ==(var other) {
     // Ints and doubles are treated as separate constants.
     if (other is! IntConstantValue) return false;
@@ -251,18 +280,24 @@
     return intValue == otherInt.intValue;
   }
 
+  @override
   int get hashCode => intValue.hashCode & Hashing.SMI_MASK;
 
+  @override
   accept(ConstantValueVisitor visitor, arg) => visitor.visitInt(this, arg);
 
+  @override
   ConstantValueKind get kind => ConstantValueKind.INT;
 
+  @override
   String toStructuredText() => 'IntConstant(${toDartText()})';
 
+  @override
   String toDartText() => intValue.toString();
 }
 
 class DoubleConstantValue extends NumConstantValue {
+  @override
   final double doubleValue;
 
   factory DoubleConstantValue(double value) {
@@ -283,23 +318,32 @@
 
   const DoubleConstantValue._internal(this.doubleValue);
 
+  @override
   bool get isDouble => true;
 
+  @override
   bool get isNaN => doubleValue.isNaN;
 
   // We need to check for the negative sign since -0.0 == 0.0.
+  @override
   bool get isMinusZero => doubleValue == 0.0 && doubleValue.isNegative;
 
+  @override
   bool get isZero => doubleValue == 0.0;
 
+  @override
   bool get isOne => doubleValue == 1.0;
 
+  @override
   bool get isPositiveInfinity => doubleValue == double.infinity;
 
+  @override
   bool get isNegativeInfinity => doubleValue == -double.infinity;
 
+  @override
   DartType getType(CommonElements types) => types.doubleType;
 
+  @override
   bool operator ==(var other) {
     if (other is! DoubleConstantValue) return false;
     DoubleConstantValue otherDouble = other;
@@ -313,14 +357,19 @@
     }
   }
 
+  @override
   int get hashCode => doubleValue.hashCode;
 
+  @override
   accept(ConstantValueVisitor visitor, arg) => visitor.visitDouble(this, arg);
 
+  @override
   ConstantValueKind get kind => ConstantValueKind.DOUBLE;
 
+  @override
   String toStructuredText() => 'DoubleConstant(${toDartText()})';
 
+  @override
   String toDartText() => doubleValue.toString();
 }
 
@@ -331,18 +380,23 @@
 
   const BoolConstantValue._internal();
 
+  @override
   bool get isBool => true;
 
   bool get boolValue;
 
+  @override
   DartType getType(CommonElements types) => types.boolType;
 
   BoolConstantValue negate();
 
+  @override
   accept(ConstantValueVisitor visitor, arg) => visitor.visitBool(this, arg);
 
+  @override
   ConstantValueKind get kind => ConstantValueKind.BOOL;
 
+  @override
   String toStructuredText() => 'BoolConstant(${toDartText()})';
 }
 
@@ -351,18 +405,24 @@
 
   const TrueConstantValue._internal() : super._internal();
 
+  @override
   bool get isTrue => true;
 
+  @override
   bool get boolValue => true;
 
+  @override
   FalseConstantValue negate() => new FalseConstantValue();
 
+  @override
   bool operator ==(var other) => identical(this, other);
 
   // The magic constant is just a random value. It does not have any
   // significance.
+  @override
   int get hashCode => 499;
 
+  @override
   String toDartText() => boolValue.toString();
 }
 
@@ -371,24 +431,31 @@
 
   const FalseConstantValue._internal() : super._internal();
 
+  @override
   bool get isFalse => true;
 
+  @override
   bool get boolValue => false;
 
+  @override
   TrueConstantValue negate() => new TrueConstantValue();
 
+  @override
   bool operator ==(var other) => identical(this, other);
 
   // The magic constant is just a random value. It does not have any
   // significance.
+  @override
   int get hashCode => 536555975;
 
+  @override
   String toDartText() => boolValue.toString();
 }
 
 class StringConstantValue extends PrimitiveConstantValue {
   final String stringValue;
 
+  @override
   final int hashCode;
 
   // TODO(floitsch): cache StringConstants.
@@ -396,10 +463,13 @@
       : this.stringValue = value,
         this.hashCode = value.hashCode;
 
+  @override
   bool get isString => true;
 
+  @override
   DartType getType(CommonElements types) => types.stringType;
 
+  @override
   bool operator ==(var other) {
     if (identical(this, other)) return true;
     if (other is! StringConstantValue) return false;
@@ -412,13 +482,17 @@
 
   int get length => stringValue.length;
 
+  @override
   accept(ConstantValueVisitor visitor, arg) => visitor.visitString(this, arg);
 
+  @override
   ConstantValueKind get kind => ConstantValueKind.STRING;
 
   // TODO(johnniwinther): Ensure correct escaping.
+  @override
   String toDartText() => '"${stringValue}"';
 
+  @override
   String toStructuredText() => 'StringConstant(${toDartText()})';
 }
 
@@ -427,8 +501,10 @@
 
   ObjectConstantValue(this.type);
 
+  @override
   bool get isObject => true;
 
+  @override
   DartType getType(CommonElements types) => type;
 
   void _unparseTypeArguments(StringBuffer sb) {
@@ -446,28 +522,37 @@
 
   TypeConstantValue(this.representedType, InterfaceType type) : super(type);
 
+  @override
   bool get isType => true;
 
+  @override
   bool operator ==(other) {
     return other is TypeConstantValue &&
         representedType.unaliased == other.representedType.unaliased;
   }
 
+  @override
   int get hashCode => representedType.unaliased.hashCode * 13;
 
+  @override
   List<ConstantValue> getDependencies() => const <ConstantValue>[];
 
+  @override
   accept(ConstantValueVisitor visitor, arg) => visitor.visitType(this, arg);
 
+  @override
   ConstantValueKind get kind => ConstantValueKind.TYPE;
 
+  @override
   String toDartText() => '$representedType';
 
+  @override
   String toStructuredText() => 'TypeConstant(${representedType})';
 }
 
 class ListConstantValue extends ObjectConstantValue {
   final List<ConstantValue> entries;
+  @override
   final int hashCode;
 
   ListConstantValue(InterfaceType type, List<ConstantValue> entries)
@@ -475,8 +560,10 @@
         hashCode = Hashing.listHash(entries, Hashing.objectHash(type)),
         super(type);
 
+  @override
   bool get isList => true;
 
+  @override
   bool operator ==(var other) {
     if (identical(this, other)) return true;
     if (other is! ListConstantValue) return false;
@@ -490,14 +577,18 @@
     return true;
   }
 
+  @override
   List<ConstantValue> getDependencies() => entries;
 
   int get length => entries.length;
 
+  @override
   accept(ConstantValueVisitor visitor, arg) => visitor.visitList(this, arg);
 
+  @override
   ConstantValueKind get kind => ConstantValueKind.LIST;
 
+  @override
   String toDartText() {
     StringBuffer sb = new StringBuffer();
     _unparseTypeArguments(sb);
@@ -510,6 +601,7 @@
     return sb.toString();
   }
 
+  @override
   String toStructuredText() {
     StringBuffer sb = new StringBuffer();
     sb.write('ListConstant(');
@@ -526,6 +618,7 @@
 
 abstract class SetConstantValue extends ObjectConstantValue {
   final List<ConstantValue> values;
+  @override
   final int hashCode;
 
   SetConstantValue(InterfaceType type, List<ConstantValue> values)
@@ -536,6 +629,7 @@
   @override
   bool get isSet => true;
 
+  @override
   bool operator ==(var other) {
     if (identical(this, other)) return true;
     if (other is! SetConstantValue) return false;
@@ -585,6 +679,7 @@
 abstract class MapConstantValue extends ObjectConstantValue {
   final List<ConstantValue> keys;
   final List<ConstantValue> values;
+  @override
   final int hashCode;
   Map<ConstantValue, ConstantValue> _lookupMap;
 
@@ -598,8 +693,10 @@
     assert(keys.length == values.length);
   }
 
+  @override
   bool get isMap => true;
 
+  @override
   bool operator ==(var other) {
     if (identical(this, other)) return true;
     if (other is! MapConstantValue) return false;
@@ -614,6 +711,7 @@
     return true;
   }
 
+  @override
   List<ConstantValue> getDependencies() {
     List<ConstantValue> result = <ConstantValue>[];
     result.addAll(keys);
@@ -629,10 +727,13 @@
     return lookupMap[key];
   }
 
+  @override
   accept(ConstantValueVisitor visitor, arg) => visitor.visitMap(this, arg);
 
+  @override
   ConstantValueKind get kind => ConstantValueKind.MAP;
 
+  @override
   String toDartText() {
     StringBuffer sb = new StringBuffer();
     _unparseTypeArguments(sb);
@@ -647,6 +748,7 @@
     return sb.toString();
   }
 
+  @override
   String toStructuredText() {
     StringBuffer sb = new StringBuffer();
     sb.write('MapConstant(');
@@ -670,28 +772,37 @@
 
   InterceptorConstantValue(this.cls);
 
+  @override
   bool get isInterceptor => true;
 
+  @override
   bool operator ==(other) {
     return other is InterceptorConstantValue && cls == other.cls;
   }
 
+  @override
   int get hashCode => cls.hashCode * 43;
 
+  @override
   List<ConstantValue> getDependencies() => const <ConstantValue>[];
 
+  @override
   accept(ConstantValueVisitor visitor, arg) {
     return visitor.visitInterceptor(this, arg);
   }
 
+  @override
   DartType getType(CommonElements types) => types.dynamicType;
 
+  @override
   ConstantValueKind get kind => ConstantValueKind.INTERCEPTOR;
 
+  @override
   String toDartText() {
     return 'interceptor($cls)';
   }
 
+  @override
   String toStructuredText() {
     return 'InterceptorConstant(${cls.name})';
   }
@@ -703,26 +814,35 @@
 
   SyntheticConstantValue(this.valueKind, this.payload);
 
+  @override
   bool get isDummy => true;
 
+  @override
   bool operator ==(other) {
     return other is SyntheticConstantValue && payload == other.payload;
   }
 
+  @override
   get hashCode => payload.hashCode * 17 + valueKind.hashCode;
 
+  @override
   List<ConstantValue> getDependencies() => const <ConstantValue>[];
 
+  @override
   accept(ConstantValueVisitor visitor, arg) {
     return visitor.visitSynthetic(this, arg);
   }
 
+  @override
   DartType getType(CommonElements types) => types.dynamicType;
 
+  @override
   ConstantValueKind get kind => ConstantValueKind.SYNTHETIC;
 
+  @override
   String toDartText() => 'synthetic($valueKind, $payload)';
 
+  @override
   String toStructuredText() => 'SyntheticConstant($valueKind, $payload)';
 }
 
@@ -730,6 +850,7 @@
   // TODO(johnniwinther): Make [fields] private to avoid misuse of the map
   // ordering and mutability.
   final Map<FieldEntity, ConstantValue> fields;
+  @override
   final int hashCode;
 
   ConstructedConstantValue(
@@ -742,8 +863,10 @@
     assert(!fields.containsValue(null));
   }
 
+  @override
   bool get isConstructedObject => true;
 
+  @override
   bool operator ==(var otherVar) {
     if (identical(this, otherVar)) return true;
     if (otherVar is! ConstructedConstantValue) return false;
@@ -757,18 +880,22 @@
     return true;
   }
 
+  @override
   List<ConstantValue> getDependencies() => fields.values.toList();
 
+  @override
   accept(ConstantValueVisitor visitor, arg) {
     return visitor.visitConstructed(this, arg);
   }
 
+  @override
   ConstantValueKind get kind => ConstantValueKind.CONSTRUCTED;
 
   Iterable<FieldEntity> get _fieldsSortedByName {
     return fields.keys.toList()..sort((a, b) => a.name.compareTo(b.name));
   }
 
+  @override
   String toDartText() {
     StringBuffer sb = new StringBuffer();
     sb.write(type.element.name);
@@ -787,6 +914,7 @@
     return sb.toString();
   }
 
+  @override
   String toStructuredText() {
     StringBuffer sb = new StringBuffer();
     sb.write('ConstructedConstant(');
@@ -812,6 +940,7 @@
 
   InstantiationConstantValue(this.typeArguments, this.function);
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     return other is InstantiationConstantValue &&
@@ -824,21 +953,27 @@
     return Hashing.objectHash(function, Hashing.listHash(typeArguments));
   }
 
+  @override
   List<ConstantValue> getDependencies() => <ConstantValue>[function];
 
+  @override
   accept(ConstantValueVisitor visitor, arg) =>
       visitor.visitInstantiation(this, arg);
 
+  @override
   DartType getType(CommonElements types) {
     FunctionType type = function.getType(types);
     return type.instantiate(typeArguments);
   }
 
+  @override
   ConstantValueKind get kind => ConstantValueKind.INSTANTIATION;
 
+  @override
   String toDartText() =>
       '<${typeArguments.join(', ')}>(${function.toDartText()})';
 
+  @override
   String toStructuredText() {
     return 'InstantiationConstant($typeArguments,'
         '${function.toStructuredText()})';
@@ -865,25 +1000,33 @@
 
   bool get isReference => true;
 
+  @override
   bool operator ==(other) {
     return other is DeferredGlobalConstantValue &&
         referenced == other.referenced &&
         unit == other.unit;
   }
 
+  @override
   get hashCode => (referenced.hashCode * 17 + unit.hashCode) & 0x3fffffff;
 
+  @override
   List<ConstantValue> getDependencies() => <ConstantValue>[referenced];
 
+  @override
   accept(ConstantValueVisitor visitor, arg) =>
       visitor.visitDeferredGlobal(this, arg);
 
+  @override
   DartType getType(CommonElements types) => referenced.getType(types);
 
+  @override
   ConstantValueKind get kind => ConstantValueKind.DEFERRED_GLOBAL;
 
+  @override
   String toDartText() => 'deferred_global(${referenced.toDartText()})';
 
+  @override
   String toStructuredText() {
     return 'DeferredGlobalConstant(${referenced.toStructuredText()})';
   }
@@ -893,6 +1036,7 @@
 /// expression.
 // TODO(johnniwinther): Expand this to contain the error kind.
 class NonConstantValue extends ConstantValue {
+  @override
   bool get isConstant => false;
 
   @override
@@ -906,6 +1050,7 @@
   @override
   DartType getType(CommonElements types) => types.dynamicType;
 
+  @override
   ConstantValueKind get kind => ConstantValueKind.NON_CONSTANT;
 
   @override
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 3aa386e..65dc8c6 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -664,6 +664,7 @@
 class AbortLeg {
   final message;
   AbortLeg(this.message);
+  @override
   toString() => 'Aborted due to --throw-on-error: $message';
 }
 
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index d2fd134..dbce4ff 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -51,6 +51,7 @@
 
   OutputUnit(this.isMainOutput, this.name, this._imports);
 
+  @override
   int compareTo(OutputUnit other) {
     if (identical(this, other)) return 0;
     if (isMainOutput && !other.isMainOutput) return -1;
@@ -76,6 +77,7 @@
 
   Set<ImportEntity> get importsForTesting => _imports;
 
+  @override
   String toString() => "OutputUnit($name, $_imports)";
 }
 
@@ -84,6 +86,7 @@
 /// shared OutputUnits.
 abstract class DeferredLoadTask extends CompilerTask {
   /// The name of this task.
+  @override
   String get name => 'Deferred Loading';
 
   /// The OutputUnit that will be loaded when the program starts.
@@ -1092,6 +1095,7 @@
     return result;
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('ImportSet(size: $length, ');
@@ -1200,6 +1204,7 @@
 
   ClassWorkItem(this.cls, ImportSet newSet) : super(newSet);
 
+  @override
   void update(DeferredLoadTask task, WorkQueue queue) {
     queue.pendingClasses.remove(cls);
     ImportSet oldSet = task._classToSet[cls];
@@ -1215,6 +1220,7 @@
 
   MemberWorkItem(this.member, ImportSet newSet) : super(newSet);
 
+  @override
   void update(DeferredLoadTask task, WorkQueue queue) {
     queue.pendingMembers.remove(member);
     ImportSet oldSet = task._memberToSet[member];
@@ -1230,6 +1236,7 @@
 
   ConstantWorkItem(this.constant, ImportSet newSet) : super(newSet);
 
+  @override
   void update(DeferredLoadTask task, WorkQueue queue) {
     queue.pendingConstants.remove(constant);
     ImportSet oldSet = task._constantToSet[constant];
diff --git a/pkg/compiler/lib/src/diagnostics/code_location.dart b/pkg/compiler/lib/src/diagnostics/code_location.dart
index 63fee22..8e923f9 100644
--- a/pkg/compiler/lib/src/diagnostics/code_location.dart
+++ b/pkg/compiler/lib/src/diagnostics/code_location.dart
@@ -40,10 +40,12 @@
 
   SchemeLocation(this.uri);
 
+  @override
   bool inSameLocation(Uri uri) {
     return this.uri.scheme == uri.scheme;
   }
 
+  @override
   String relativize(Uri baseUri) {
     return uri_extras.relativize(baseUri, uri, false);
   }
@@ -58,10 +60,12 @@
 
   PackageLocation(this.packageName);
 
+  @override
   bool inSameLocation(Uri uri) {
     return uri.scheme == 'package' && uri.path.startsWith('$packageName/');
   }
 
+  @override
   String relativize(Uri baseUri) => 'package:$packageName';
 }
 
@@ -73,8 +77,10 @@
 
   UriLocation(this.uri);
 
+  @override
   bool inSameLocation(Uri uri) => this.uri == uri;
 
+  @override
   String relativize(Uri baseUri) {
     return uri_extras.relativize(baseUri, uri, false);
   }
@@ -84,7 +90,9 @@
 class AnyLocation implements CodeLocation {
   const AnyLocation();
 
+  @override
   bool inSameLocation(Uri uri) => true;
 
+  @override
   String relativize(Uri baseUri) => '$baseUri';
 }
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index a3532c9..16aee21 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -607,7 +607,7 @@
 
       MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE: const MessageTemplate(
           MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE,
-          "`#{constant}` of type '#{type}' is not a valid logical and operand. "
+          "`#{constant}` of type '#{type}' is not a valid logical or operand. "
           "Must be a value of type 'bool'."),
 
       MessageKind.INVALID_CONSTANT_CONSTRUCTOR: const MessageTemplate(
@@ -692,6 +692,7 @@
           "'case' expression of type '#{type}'."),
     }); // End of TEMPLATES.
 
+  @override
   String toString() => template;
 
   Message message([Map arguments = const {}, bool terse = false]) {
@@ -738,15 +739,18 @@
     return message;
   }
 
+  @override
   String toString() {
     return computeMessage();
   }
 
+  @override
   bool operator ==(other) {
     if (other is! Message) return false;
     return (template == other.template) && (toString() == other.toString());
   }
 
+  @override
   int get hashCode => throw new UnsupportedError('Message.hashCode');
 
   static String convertToString(value) {
diff --git a/pkg/compiler/lib/src/diagnostics/source_span.dart b/pkg/compiler/lib/src/diagnostics/source_span.dart
index 3fffc29..2b24c11 100644
--- a/pkg/compiler/lib/src/diagnostics/source_span.dart
+++ b/pkg/compiler/lib/src/diagnostics/source_span.dart
@@ -13,15 +13,18 @@
 
   const SourceSpan(this.uri, this.begin, this.end);
 
+  @override
   int get hashCode {
     return 13 * uri.hashCode + 17 * begin.hashCode + 19 * end.hashCode;
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! SourceSpan) return false;
     return uri == other.uri && begin == other.begin && end == other.end;
   }
 
+  @override
   String toString() => 'SourceSpan($uri, $begin, $end)';
 }
diff --git a/pkg/compiler/lib/src/diagnostics/spannable.dart b/pkg/compiler/lib/src/diagnostics/spannable.dart
index cdba684..356e2e4 100644
--- a/pkg/compiler/lib/src/diagnostics/spannable.dart
+++ b/pkg/compiler/lib/src/diagnostics/spannable.dart
@@ -14,6 +14,7 @@
 
   const _SpannableSentinel(this.name);
 
+  @override
   String toString() => name;
 }
 
@@ -33,6 +34,7 @@
   final String message;
   SpannableAssertionFailure(this.node, this.message);
 
+  @override
   String toString() => 'Assertion failure'
       '${message != null ? ': $message' : ''}';
 }
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index d4c2161..35be4dd 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -402,6 +402,7 @@
       : useBinaryFormat = compiler.options.useDumpInfoBinaryFormat,
         super(compiler.measurer);
 
+  @override
   String get name => "Dump Info";
 
   ElementInfoCollector infoCollector;
@@ -433,6 +434,7 @@
     _programSize = programSize;
   }
 
+  @override
   void reportInlined(FunctionEntity element, MemberEntity inlinedFrom) {
     inlineCount.putIfAbsent(element, () => 0);
     inlineCount[element] += 1;
@@ -675,6 +677,7 @@
 // TODO(sigmund): delete once we no longer emit text by default.
 class _CodeData extends CodeSpan {
   StringBuffer _text = new StringBuffer();
+  @override
   String get text => '$_text';
   int get length => end - start;
 }
diff --git a/pkg/compiler/lib/src/elements/entities.dart b/pkg/compiler/lib/src/elements/entities.dart
index a3a5c4d..a621644 100644
--- a/pkg/compiler/lib/src/elements/entities.dart
+++ b/pkg/compiler/lib/src/elements/entities.dart
@@ -53,6 +53,7 @@
 
   ImportEntity(this.isDeferred, this.name, this.uri, this.enclosingLibraryUri);
 
+  @override
   String toString() => 'import($name:${isDeferred ? ' deferred' : ''})';
 }
 
@@ -196,6 +197,7 @@
   const AsyncMarker._(this.asyncParserState,
       {this.isAsync: false, this.isYielding: false});
 
+  @override
   String toString() {
     return '${isAsync ? 'async' : 'sync'}${isYielding ? '*' : ''}';
   }
@@ -326,6 +328,7 @@
         namedParameters, typeParameters);
   }
 
+  @override
   int get hashCode => Hashing.listHash(
       namedParameters,
       Hashing.objectHash(
@@ -333,6 +336,7 @@
           Hashing.objectHash(
               requiredParameters, Hashing.objectHash(typeParameters))));
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! ParameterStructure) return false;
@@ -368,6 +372,7 @@
     return sb.toString();
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('ParameterStructure(');
diff --git a/pkg/compiler/lib/src/elements/indexed.dart b/pkg/compiler/lib/src/elements/indexed.dart
index 56defb0..e83b8a0 100644
--- a/pkg/compiler/lib/src/elements/indexed.dart
+++ b/pkg/compiler/lib/src/elements/indexed.dart
@@ -13,18 +13,21 @@
 abstract class IndexedLibrary extends _Indexed implements LibraryEntity {
   /// Library index used for fast lookup in [KernelToElementMapBase].
   int get libraryIndex => _index;
+  @override
   int get hashCode => 7 * _index + 2;
 }
 
 abstract class IndexedClass extends _Indexed implements ClassEntity {
   /// Class index used for fast lookup in [KernelToElementMapBase].
   int get classIndex => _index;
+  @override
   int get hashCode => 7 * _index + 1;
 }
 
 abstract class IndexedMember extends _Indexed implements MemberEntity {
   /// Member index used for fast lookup in [KernelToElementMapBase].
   int get memberIndex => _index;
+  @override
   int get hashCode => 7 * _index;
 }
 
diff --git a/pkg/compiler/lib/src/elements/jumps.dart b/pkg/compiler/lib/src/elements/jumps.dart
index 05a25e7..53bf887 100644
--- a/pkg/compiler/lib/src/elements/jumps.dart
+++ b/pkg/compiler/lib/src/elements/jumps.dart
@@ -20,6 +20,7 @@
 /// A jump target is the reference point of a statement or switch-case,
 /// either by label or as the default target of a break or continue.
 abstract class JumpTarget extends Local {
+  @override
   String get name => 'target';
 
   bool get isTarget => isBreakTarget || isContinueTarget;
diff --git a/pkg/compiler/lib/src/elements/names.dart b/pkg/compiler/lib/src/elements/names.dart
index dd60ab4..0a004de 100644
--- a/pkg/compiler/lib/src/elements/names.dart
+++ b/pkg/compiler/lib/src/elements/names.dart
@@ -61,57 +61,77 @@
 }
 
 class PublicName implements Name {
+  @override
   final String text;
+  @override
   final bool isSetter;
 
   const PublicName(this.text, {this.isSetter: false});
 
+  @override
   Name get getter => isSetter ? new PublicName(text) : this;
 
+  @override
   Name get setter => isSetter ? this : new PublicName(text, isSetter: true);
 
+  @override
   bool isAccessibleFrom(LibraryEntity element) => true;
 
+  @override
   bool get isPrivate => false;
 
+  @override
   int get hashCode => similarHashCode;
 
+  @override
   bool operator ==(other) {
     if (other is! PublicName) return false;
     return isSimilarTo(other);
   }
 
+  @override
   bool isSimilarTo(Name other) =>
       text == other.text && isSetter == other.isSetter;
+  @override
   int get similarHashCode => text.hashCode + 11 * isSetter.hashCode;
 
+  @override
   LibraryEntity get library => null;
 
+  @override
   String toString() => isSetter ? '$text=' : text;
 }
 
 class PrivateName extends PublicName {
+  @override
   final LibraryEntity library;
 
   PrivateName(String text, this.library, {bool isSetter: false})
       : super(text, isSetter: isSetter);
 
+  @override
   Name get getter => isSetter ? new PrivateName(text, library) : this;
 
+  @override
   Name get setter {
     return isSetter ? this : new PrivateName(text, library, isSetter: true);
   }
 
+  @override
   bool isAccessibleFrom(LibraryEntity element) => library == element;
 
+  @override
   bool get isPrivate => true;
 
+  @override
   int get hashCode => super.hashCode + 13 * library.hashCode;
 
+  @override
   bool operator ==(other) {
     if (other is! PrivateName) return false;
     return super == (other) && library == other.library;
   }
 
+  @override
   String toString() => '${library.name}#${super.toString()}';
 }
diff --git a/pkg/compiler/lib/src/elements/operators.dart b/pkg/compiler/lib/src/elements/operators.dart
index ddc9cff3..e3fc7d9 100644
--- a/pkg/compiler/lib/src/elements/operators.dart
+++ b/pkg/compiler/lib/src/elements/operators.dart
@@ -26,6 +26,7 @@
   Selector get selector => new Selector(SelectorKind.OPERATOR,
       new PublicName(selectorName), CallStructure.NO_ARGS);
 
+  @override
   String toString() => name;
 
   /// The unary ! operator.
@@ -102,6 +103,7 @@
 
   String get selectorName => name;
 
+  @override
   String toString() => name;
 
   /// The == operator.
@@ -297,8 +299,10 @@
 class _NotEqualsOperator extends BinaryOperator {
   const _NotEqualsOperator() : super._(BinaryOperatorKind.NOT_EQ, '!=');
 
+  @override
   bool get isUserDefinable => false;
 
+  @override
   String get selectorName => '==';
 }
 
@@ -308,8 +312,10 @@
   const _LogicalOperator(BinaryOperatorKind kind, String name)
       : super._(kind, name);
 
+  @override
   bool get isUserDefinable => false;
 
+  @override
   String get selectorName => null;
 }
 
@@ -318,7 +324,9 @@
   const _IfNullOperator(BinaryOperatorKind kind, String name)
       : super._(kind, name);
 
+  @override
   bool get isUserDefinable => false;
 
+  @override
   String get selectorName => '??';
 }
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index d42f31a..ef7c2f8 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -144,6 +144,7 @@
     return _assumptionMap[a]?.contains(b) ?? false;
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('_Assumptions(');
@@ -165,25 +166,31 @@
 
   InterfaceType(this.element, this.typeArguments);
 
+  @override
   bool get isInterfaceType => true;
 
+  @override
   bool get isObject {
     return element.name == 'Object' &&
         element.library.canonicalUri == Uris.dart_core;
   }
 
+  @override
   bool get containsTypeVariables =>
       typeArguments.any((type) => type.containsTypeVariables);
 
+  @override
   void forEachTypeVariable(f(TypeVariableType variable)) {
     typeArguments.forEach((type) => type.forEachTypeVariable(f));
   }
 
+  @override
   bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) {
     return typeArguments
         .any((type) => type._containsFreeTypeVariables(bindings));
   }
 
+  @override
   InterfaceType subst(List<DartType> arguments, List<DartType> parameters) {
     if (typeArguments.isEmpty) {
       // Return fast on non-generic types.
@@ -203,6 +210,7 @@
     return this;
   }
 
+  @override
   bool get treatAsRaw {
     for (DartType type in typeArguments) {
       if (!type.treatAsDynamic) return false;
@@ -214,6 +222,7 @@
   R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
       visitor.visitInterfaceType(this, argument);
 
+  @override
   int get hashCode {
     int hash = element.hashCode;
     for (DartType argument in typeArguments) {
@@ -223,12 +232,14 @@
     return hash;
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! InterfaceType) return false;
     return _equalsInternal(other, null);
   }
 
+  @override
   bool _equals(DartType other, _Assumptions assumptions) {
     if (identical(this, other)) return true;
     if (other is! InterfaceType) return false;
@@ -240,6 +251,7 @@
         _equalTypes(typeArguments, other.typeArguments, assumptions);
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write(element.name);
@@ -262,22 +274,28 @@
 class TypedefType extends DartType {
   final TypedefEntity element;
   final List<DartType> typeArguments;
+  @override
   final FunctionType unaliased;
 
   TypedefType(this.element, this.typeArguments, this.unaliased);
 
+  @override
   bool get isTypedef => true;
 
+  @override
   bool get containsTypeVariables =>
       typeArguments.any((type) => type.containsTypeVariables);
 
+  @override
   void forEachTypeVariable(f(TypeVariableType variable)) {
     typeArguments.forEach((type) => type.forEachTypeVariable(f));
   }
 
+  @override
   bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) =>
       typeArguments.any((type) => type._containsFreeTypeVariables(bindings));
 
+  @override
   TypedefType subst(List<DartType> arguments, List<DartType> parameters) {
     if (typeArguments.isEmpty) {
       // Return fast on non-generic types.
@@ -299,6 +317,7 @@
     return this;
   }
 
+  @override
   bool get treatAsRaw {
     for (DartType type in typeArguments) {
       if (!type.treatAsDynamic) return false;
@@ -310,6 +329,7 @@
   R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
       visitor.visitTypedefType(this, argument);
 
+  @override
   int get hashCode {
     int hash = element.hashCode;
     for (DartType argument in typeArguments) {
@@ -319,12 +339,14 @@
     return hash;
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! TypedefType) return false;
     return _equalsInternal(other, null);
   }
 
+  @override
   bool _equals(DartType other, _Assumptions assumptions) {
     if (identical(this, other)) return true;
     if (other is! TypedefType) return false;
@@ -336,6 +358,7 @@
         _equalTypes(typeArguments, other.typeArguments, assumptions);
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write(element.name);
@@ -360,16 +383,21 @@
 
   TypeVariableType(this.element);
 
+  @override
   bool get isTypeVariable => true;
 
+  @override
   bool get containsTypeVariables => true;
 
+  @override
   void forEachTypeVariable(f(TypeVariableType variable)) {
     f(this);
   }
 
+  @override
   bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) => true;
 
+  @override
   DartType subst(List<DartType> arguments, List<DartType> parameters) {
     assert(arguments.length == parameters.length);
     if (parameters.isEmpty) {
@@ -388,8 +416,10 @@
   R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
       visitor.visitTypeVariableType(this, argument);
 
+  @override
   int get hashCode => 17 * element.hashCode;
 
+  @override
   bool operator ==(other) {
     if (other is! TypeVariableType) return false;
     return identical(other.element, element);
@@ -403,6 +433,7 @@
     return false;
   }
 
+  @override
   String toString() => '${element.typeDeclaration.name}.${element.name}';
 }
 
@@ -438,12 +469,14 @@
   @override
   bool get isFunctionTypeVariable => true;
 
+  @override
   bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) {
     if (bindings == null) return true;
     if (bindings.indexOf(this) >= 0) return false;
     return true;
   }
 
+  @override
   DartType subst(List<DartType> arguments, List<DartType> parameters) {
     assert(arguments.length == parameters.length);
     if (parameters.isEmpty) {
@@ -458,8 +491,10 @@
     return this;
   }
 
+  @override
   int get hashCode => index.hashCode * 19;
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! FunctionTypeVariable) return false;
@@ -478,14 +513,17 @@
   R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
       visitor.visitFunctionTypeVariable(this, argument);
 
+  @override
   String toString() => '#${new String.fromCharCode(0x41 + index)}';
 }
 
 class VoidType extends DartType {
   const VoidType();
 
+  @override
   bool get isVoid => true;
 
+  @override
   DartType subst(List<DartType> arguments, List<DartType> parameters) {
     // `void` cannot be substituted.
     return this;
@@ -495,6 +533,7 @@
   R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
       visitor.visitVoidType(this, argument);
 
+  @override
   int get hashCode => 6007;
 
   @override
@@ -502,6 +541,7 @@
     return identical(this, other);
   }
 
+  @override
   String toString() => 'void';
 }
 
@@ -514,6 +554,7 @@
   @override
   bool get treatAsDynamic => true;
 
+  @override
   DartType subst(List<DartType> arguments, List<DartType> parameters) {
     // `dynamic` cannot be substituted.
     return this;
@@ -523,6 +564,7 @@
   R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
       visitor.visitDynamicType(this, argument);
 
+  @override
   int get hashCode => 91;
 
   @override
@@ -530,6 +572,7 @@
     return identical(this, other);
   }
 
+  @override
   String toString() => 'dynamic';
 }
 
@@ -565,6 +608,7 @@
     assert(!typeVariables.contains(null), "Invalid type variables in $this.");
   }
 
+  @override
   bool get containsTypeVariables {
     return typeVariables.any((type) => type.bound.containsTypeVariables) ||
         returnType.containsTypeVariables ||
@@ -573,6 +617,7 @@
         namedParameterTypes.any((type) => type.containsTypeVariables);
   }
 
+  @override
   void forEachTypeVariable(f(TypeVariableType variable)) {
     typeVariables.forEach((type) => type.bound.forEachTypeVariable(f));
     returnType.forEachTypeVariable(f);
@@ -581,6 +626,7 @@
     namedParameterTypes.forEach((type) => type.forEachTypeVariable(f));
   }
 
+  @override
   bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) {
     int restore;
     if (typeVariables.isNotEmpty) {
@@ -604,8 +650,10 @@
     return result;
   }
 
+  @override
   bool get isFunctionType => true;
 
+  @override
   DartType subst(List<DartType> arguments, List<DartType> parameters) {
     if (parameters.isEmpty) {
       assert(arguments.isEmpty);
@@ -669,6 +717,7 @@
   R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
       visitor.visitFunctionType(this, argument);
 
+  @override
   int get hashCode {
     int hash = 3 * returnType.hashCode;
     for (DartType parameter in parameterTypes) {
@@ -686,12 +735,14 @@
     return hash;
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! FunctionType) return false;
     return _equalsInternal(other, null);
   }
 
+  @override
   bool _equals(DartType other, _Assumptions assumptions) {
     if (identical(this, other)) return true;
     if (other is! FunctionType) return false;
@@ -728,6 +779,7 @@
     return result;
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write(returnType);
@@ -811,26 +863,33 @@
     return new FutureOrType(newTypeArgument);
   }
 
+  @override
   bool get containsTypeVariables => typeArgument.containsTypeVariables;
 
+  @override
   void forEachTypeVariable(f(TypeVariableType variable)) {
     typeArgument.forEachTypeVariable(f);
   }
 
+  @override
   bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) =>
       typeArgument._containsFreeTypeVariables(bindings);
 
+  @override
   R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
       visitor.visitFutureOrType(this, argument);
 
+  @override
   int get hashCode => typeArgument.hashCode * 13;
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! FutureOrType) return false;
     return _equalsInternal(other, null);
   }
 
+  @override
   bool _equals(DartType other, _Assumptions assumptions) {
     if (identical(this, other)) return true;
     if (other is! FutureOrType) return false;
@@ -841,6 +900,7 @@
     return typeArgument._equals(other.typeArgument, assumptions);
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('FutureOr');
@@ -964,10 +1024,12 @@
   /// Returns the declared bound of [element].
   DartType getTypeVariableBound(TypeVariableEntity element);
 
+  @override
   bool visitType(T t, T s) {
     throw 'internal error: unknown type ${t}';
   }
 
+  @override
   bool visitVoidType(VoidType t, T s) {
     assert(s is! VoidType);
     return false;
@@ -983,6 +1045,7 @@
 
   bool invalidCallableType(covariant DartType callType, covariant DartType s);
 
+  @override
   bool visitInterfaceType(InterfaceType t, covariant DartType s) {
     ensureResolved(t);
 
@@ -1015,6 +1078,7 @@
     return false;
   }
 
+  @override
   bool visitFunctionType(FunctionType t, DartType s) {
     if (s == commonElements.functionType) {
       return true;
@@ -1141,6 +1205,7 @@
     return true;
   }
 
+  @override
   bool visitTypeVariableType(TypeVariableType t, T s) {
     // Identity check is handled in [isSubtype].
     DartType bound = getTypeVariableBound(t.element);
@@ -1168,6 +1233,7 @@
     return true;
   }
 
+  @override
   bool visitFunctionTypeVariable(FunctionTypeVariable t, DartType s) {
     if (!s.isFunctionTypeVariable) return false;
     return assumptions.isAssumed(t, s);
@@ -1194,27 +1260,33 @@
     return t.accept(this, s);
   }
 
+  @override
   bool invalidTypeArguments(T t, T s) {
     return !isMoreSpecific(t, s);
   }
 
+  @override
   bool invalidFunctionReturnTypes(T t, T s) {
     if (s.treatAsDynamic && t.isVoid) return true;
     return !s.isVoid && !isMoreSpecific(t, s);
   }
 
+  @override
   bool invalidFunctionParameterTypes(T t, T s) {
     return !isMoreSpecific(t, s);
   }
 
+  @override
   bool invalidTypeVariableBounds(T bound, T s) {
     return !isMoreSpecific(bound, s);
   }
 
+  @override
   bool invalidCallableType(covariant DartType callType, covariant DartType s) {
     return !isMoreSpecific(callType, s);
   }
 
+  @override
   bool visitFutureOrType(FutureOrType t, covariant DartType s) {
     return false;
   }
@@ -1244,26 +1316,32 @@
     return isSubtype(t, s) || isSubtype(s, t);
   }
 
+  @override
   bool invalidTypeArguments(T t, T s) {
     return !isSubtype(t, s);
   }
 
+  @override
   bool invalidFunctionReturnTypes(T t, T s) {
     return !isSubtype(t, s);
   }
 
+  @override
   bool invalidFunctionParameterTypes(T t, T s) {
     return !isSubtype(s, t);
   }
 
+  @override
   bool invalidTypeVariableBounds(T bound, T s) {
     return !isSubtype(bound, s);
   }
 
+  @override
   bool invalidCallableType(covariant DartType callType, covariant DartType s) {
     return !isSubtype(callType, s);
   }
 
+  @override
   bool visitFutureOrType(FutureOrType t, covariant DartType s) {
     if (s.isFutureOr) {
       FutureOrType sFutureOr = s;
@@ -1280,6 +1358,7 @@
     extends SubtypeVisitor<T> {
   bool _assumeInstantiations = true;
 
+  @override
   bool isSubtype(DartType t, DartType s) {
     if (t is TypeVariableType || s is TypeVariableType) {
       return true;
@@ -1291,6 +1370,7 @@
     return super.isSubtype(t, s);
   }
 
+  @override
   int getCommonTypeVariablesCount(FunctionType t, FunctionType s) {
     if (t.typeVariables.length == s.typeVariables.length) {
       return t.typeVariables.length;
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 4defca5..d42e48c 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -39,6 +39,7 @@
   CodegenEnqueuer codegenEnqueuerForTesting;
   final Compiler compiler;
 
+  @override
   String get name => 'Enqueue';
 
   EnqueueTask(Compiler compiler)
@@ -189,12 +190,14 @@
 
   ImpactStrategy get impactStrategy => _impactStrategy;
 
+  @override
   void open(ImpactStrategy impactStrategy, FunctionEntity mainMethod,
       Iterable<Uri> libraries) {
     _impactStrategy = impactStrategy;
     listener.onQueueOpen(this, mainMethod, libraries);
   }
 
+  @override
   void close() {
     // TODO(johnniwinther): Set [_impactStrategy] to `null` and [queueIsClosed]
     // to `true` here.
@@ -224,9 +227,11 @@
   static const ImpactUseCase IMPACT_USE =
       const ImpactUseCase('ResolutionEnqueuer');
 
+  @override
   final CompilerTask task;
   final String name;
   final CompilerOptions _options;
+  @override
   final EnqueuerListener listener;
 
   final Set<ClassEntity> _recentClasses = new Setlet<ClassEntity>();
@@ -235,6 +240,7 @@
   final WorkItemBuilder _workItemBuilder;
   final DiagnosticReporter _reporter;
 
+  @override
   bool queueIsClosed = false;
 
   WorldImpactVisitor _impactVisitor;
@@ -251,8 +257,10 @@
     _impactVisitor = new EnqueuerImplImpactVisitor(this);
   }
 
+  @override
   ResolutionWorldBuilder get worldBuilder => _worldBuilder;
 
+  @override
   bool get queueIsEmpty => _queue.isEmpty;
 
   @override
@@ -262,8 +270,10 @@
     }
   }
 
+  @override
   Iterable<ClassEntity> get processedClasses => _worldBuilder.processedClasses;
 
+  @override
   void applyImpact(WorldImpact worldImpact, {var impactSource}) {
     if (worldImpact.isEmpty) return;
     impactStrategy.visitImpact(
@@ -283,12 +293,14 @@
     });
   }
 
+  @override
   bool checkNoEnqueuedInvokedInstanceMethods(
       ElementEnvironment elementEnvironment) {
     if (Enqueuer.skipEnqueuerCheckForTesting) return true;
     return checkEnqueuerConsistency(elementEnvironment);
   }
 
+  @override
   void checkClass(ClassEntity cls) {
     _worldBuilder.processClassMembers(cls,
         (MemberEntity member, EnumSet<MemberUse> useSet) {
@@ -330,12 +342,14 @@
     }
   }
 
+  @override
   void processDynamicUse(DynamicUse dynamicUse) {
     task.measure(() {
       _worldBuilder.registerDynamicUse(dynamicUse, _applyMemberUse);
     });
   }
 
+  @override
   void processConstantUse(ConstantUse constantUse) {
     task.measure(() {
       if (_worldBuilder.registerConstantUse(constantUse)) {
@@ -346,6 +360,7 @@
     });
   }
 
+  @override
   void processStaticUse(StaticUse staticUse) {
     _worldBuilder.registerStaticUse(staticUse, _applyMemberUse);
     // TODO(johnniwinther): Add `ResolutionWorldBuilder.registerConstructorUse`
@@ -367,6 +382,7 @@
     }
   }
 
+  @override
   void processTypeUse(TypeUse typeUse) {
     DartType type = typeUse.type;
     switch (typeUse.kind) {
@@ -439,6 +455,7 @@
         _queue.isNotEmpty || _recentClasses.isNotEmpty || _recentConstants);
   }
 
+  @override
   void forEach(void f(WorkItem work)) {
     _forEach(f);
     if (onEmptyForTesting != null) {
@@ -447,18 +464,23 @@
     }
   }
 
+  @override
   void logSummary(void log(String message)) {
     log('Resolved ${processedEntities.length} elements.');
     listener.logSummary(log);
   }
 
+  @override
   String toString() => 'Enqueuer($name)';
 
+  @override
   Iterable<MemberEntity> get processedEntities =>
       _worldBuilder.processedMembers;
 
+  @override
   ImpactUseCase get impactUse => IMPACT_USE;
 
+  @override
   bool get isResolutionQueue => true;
 
   /// Registers [entity] as processed by the resolution enqueuer. Used only for
diff --git a/pkg/compiler/lib/src/frontend_strategy.dart b/pkg/compiler/lib/src/frontend_strategy.dart
index 39d0872..4d0e320 100644
--- a/pkg/compiler/lib/src/frontend_strategy.dart
+++ b/pkg/compiler/lib/src/frontend_strategy.dart
@@ -117,6 +117,7 @@
       new NativeBasicDataBuilderImpl();
   NativeBasicData _nativeBasicData;
 
+  @override
   NativeBasicData get nativeBasicData {
     if (_nativeBasicData == null) {
       _nativeBasicData = nativeBasicDataBuilder.close(elementEnvironment);
diff --git a/pkg/compiler/lib/src/helpers/debug_collection.dart b/pkg/compiler/lib/src/helpers/debug_collection.dart
index c7b9f79..1636e9e 100644
--- a/pkg/compiler/lib/src/helpers/debug_collection.dart
+++ b/pkg/compiler/lib/src/helpers/debug_collection.dart
@@ -21,15 +21,20 @@
     putIfAbsentCallback = value;
   }
 
+  @override
   Map<RK, RV> cast<RK, RV>() => Map.castFrom<K, V, RK, RV>(this);
+  @override
   bool containsValue(Object value) {
     return sourceMap.containsValue(value);
   }
 
+  @override
   bool containsKey(Object key) => sourceMap.containsKey(key);
 
+  @override
   V operator [](Object key) => sourceMap[key];
 
+  @override
   void operator []=(K key, V value) {
     if (indexSetCallback != null) {
       indexSetCallback('[]=', key, value);
@@ -37,6 +42,7 @@
     sourceMap[key] = value;
   }
 
+  @override
   V putIfAbsent(K key, V ifAbsent()) {
     return sourceMap.putIfAbsent(key, () {
       V v = ifAbsent();
@@ -47,8 +53,10 @@
     });
   }
 
+  @override
   void addAll(Map<K, V> other) => sourceMap.addAll(other);
 
+  @override
   V remove(Object key) {
     if (removeCallback != null) {
       removeCallback('remove', key, sourceMap[key]);
@@ -56,6 +64,7 @@
     return sourceMap.remove(key);
   }
 
+  @override
   void clear() {
     if (removeCallback != null) {
       removeCallback('clear', sourceMap, null);
@@ -63,34 +72,46 @@
     sourceMap.clear();
   }
 
+  @override
   void forEach(void f(K key, V value)) => sourceMap.forEach(f);
 
+  @override
   Iterable<K> get keys => sourceMap.keys;
 
+  @override
   Iterable<V> get values => sourceMap.values;
 
+  @override
   Iterable<MapEntry<K, V>> get entries => sourceMap.entries;
 
+  @override
   void addEntries(Iterable<MapEntry<K, V>> entries) {
     sourceMap.addEntries(entries);
   }
 
+  @override
   Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> transform(K key, V value)) =>
       sourceMap.map(transform);
 
+  @override
   int get length => sourceMap.length;
 
+  @override
   bool get isEmpty => sourceMap.isEmpty;
 
+  @override
   bool get isNotEmpty => sourceMap.isNotEmpty;
 
+  @override
   V update(K key, V update(V value), {V ifAbsent()}) =>
       sourceMap.update(key, update, ifAbsent: ifAbsent);
 
+  @override
   void updateAll(V update(K key, V value)) {
     sourceMap.updateAll(update);
   }
 
+  @override
   void removeWhere(bool test(K key, V value)) {
     sourceMap.removeWhere(test);
   }
@@ -101,74 +122,105 @@
 
   DebugIterable(this.iterable);
 
+  @override
   Iterator<E> get iterator => iterable.iterator;
 
+  @override
   Iterable<R> cast<R>() => Iterable.castFrom<E, R>(this);
+  @override
   Iterable<T> map<T>(T f(E element)) => iterable.map(f);
 
+  @override
   Iterable<E> where(bool test(E element)) => iterable.where(test);
 
+  @override
   Iterable<T> expand<T>(Iterable<T> f(E element)) => iterable.expand(f);
 
+  @override
   bool contains(Object element) => iterable.contains(element);
 
+  @override
   void forEach(void f(E element)) => iterable.forEach(f);
 
+  @override
   E reduce(E combine(E value, E element)) => iterable.reduce(combine);
 
+  @override
   T fold<T>(T initialValue, T combine(T previousValue, E element)) {
     return iterable.fold(initialValue, combine);
   }
 
+  @override
   bool every(bool test(E element)) => iterable.every(test);
 
+  @override
   String join([String separator = ""]) => iterable.join(separator);
 
+  @override
   bool any(bool test(E element)) => iterable.any(test);
 
+  @override
   List<E> toList({bool growable: true}) {
     return iterable.toList(growable: growable);
   }
 
+  @override
   Set<E> toSet() => iterable.toSet();
 
+  @override
   int get length => iterable.length;
 
+  @override
   bool get isEmpty => iterable.isEmpty;
 
+  @override
   bool get isNotEmpty => iterable.isNotEmpty;
 
+  @override
   Iterable<E> take(int n) => iterable.take(n);
 
+  @override
   Iterable<E> takeWhile(bool test(E value)) => iterable.takeWhile(test);
 
+  @override
   Iterable<E> skip(int n) => iterable.skip(n);
 
+  @override
   Iterable<E> skipWhile(bool test(E value)) => iterable.skipWhile(test);
 
+  @override
   E get first => iterable.first;
 
+  @override
   E get last => iterable.last;
 
+  @override
   E get single => iterable.single;
 
+  @override
   E firstWhere(bool test(E element), {E orElse()}) {
     return iterable.firstWhere(test, orElse: orElse);
   }
 
+  @override
   E lastWhere(bool test(E element), {E orElse()}) {
     return iterable.lastWhere(test, orElse: orElse);
   }
 
+  @override
   E singleWhere(bool test(E element), {E orElse()}) =>
       iterable.singleWhere(test, orElse: orElse);
 
+  @override
   E elementAt(int index) => iterable.elementAt(index);
 
+  @override
   Iterable<E> followedBy(Iterable<E> other) => iterable.followedBy(other);
 
+  @override
   Iterable<T> whereType<T>() => iterable.whereType<T>();
 
+  @override
   String toString() => iterable.toString();
 }
 
@@ -181,29 +233,38 @@
 
   List<E> get list => iterable;
 
+  @override
   List<R> cast<R>() => List.castFrom<E, R>(this);
+  @override
   List<E> operator +(List<E> other) => list + other;
 
+  @override
   E operator [](int index) => list[index];
 
+  @override
   void operator []=(int index, E value) {
     list[index] = value;
   }
 
+  @override
   void set first(E element) {
     list.first = element;
   }
 
+  @override
   void set last(E element) {
     list.last = element;
   }
 
+  @override
   int get length => list.length;
 
+  @override
   void set length(int newLength) {
     list.length = newLength;
   }
 
+  @override
   void add(E value) {
     if (addCallback != null) {
       addCallback('add', value, null);
@@ -211,6 +272,7 @@
     list.add(value);
   }
 
+  @override
   void addAll(Iterable<E> iterable) {
     if (addAllCallback != null) {
       addAllCallback('addAll', iterable, null);
@@ -218,62 +280,85 @@
     list.addAll(iterable);
   }
 
+  @override
   Iterable<E> get reversed => list.reversed;
 
+  @override
   void sort([int compare(E a, E b)]) => list.sort(compare);
 
+  @override
   void shuffle([random]) => list.shuffle(random);
 
+  @override
   int indexOf(E element, [int start = 0]) => list.indexOf(element, start);
 
+  @override
   int indexWhere(bool test(E element), [int start = 0]) =>
       list.indexWhere(test, start);
 
+  @override
   int lastIndexOf(E element, [int start]) => list.lastIndexOf(element, start);
 
+  @override
   int lastIndexWhere(bool test(E element), [int start]) =>
       list.lastIndexWhere(test, start);
 
+  @override
   void clear() => list.clear();
 
+  @override
   void insert(int index, E element) => list.insert(index, element);
 
+  @override
   void insertAll(int index, Iterable<E> iterable) {
     list.insertAll(index, iterable);
   }
 
+  @override
   void setAll(int index, Iterable<E> iterable) => list.setAll(index, iterable);
 
+  @override
   bool remove(Object value) => list.remove(value);
 
+  @override
   E removeAt(int index) => list.removeAt(index);
 
+  @override
   E removeLast() => list.removeLast();
 
+  @override
   void removeWhere(bool test(E element)) => list.removeWhere(test);
 
+  @override
   void retainWhere(bool test(E element)) => list.retainWhere(test);
 
+  @override
   List<E> sublist(int start, [int end]) => list.sublist(start, end);
 
+  @override
   Iterable<E> getRange(int start, int end) => list.getRange(start, end);
 
+  @override
   void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
     list.setRange(start, end, iterable, skipCount);
   }
 
+  @override
   void removeRange(int start, int end) {
     list.removeRange(start, end);
   }
 
+  @override
   void fillRange(int start, int end, [E fillValue]) {
     list.fillRange(start, end, fillValue);
   }
 
+  @override
   void replaceRange(int start, int end, Iterable<E> replacement) {
     list.replaceRange(start, end, replacement);
   }
 
+  @override
   Map<int, E> asMap() => list.asMap();
 }
 
@@ -284,9 +369,12 @@
 
   Set<E> get set => iterable;
 
+  @override
   Set<R> cast<R>() => Set.castFrom<E, R>(this);
+  @override
   bool contains(Object value) => set.contains(value);
 
+  @override
   bool add(E value) {
     if (addCallback != null) {
       addCallback('add', value, null);
@@ -294,32 +382,45 @@
     return set.add(value);
   }
 
+  @override
   void addAll(Iterable<E> elements) {
     elements.forEach(add);
   }
 
+  @override
   bool remove(Object value) => set.remove(value);
 
+  @override
   E lookup(Object object) => set.lookup(object);
 
+  @override
   void removeAll(Iterable<Object> elements) => set.removeAll(elements);
 
+  @override
   void retainAll(Iterable<Object> elements) => set.retainAll(elements);
 
+  @override
   void removeWhere(bool test(E element)) => set.removeWhere(test);
 
+  @override
   void retainWhere(bool test(E element)) => set.retainWhere(test);
 
+  @override
   bool containsAll(Iterable<Object> other) => set.containsAll(other);
 
+  @override
   Set<E> intersection(Set<Object> other) => set.intersection(other);
 
+  @override
   Set<E> union(Set<E> other) => set.union(other);
 
+  @override
   Set<E> difference(Set<Object> other) => set.difference(other);
 
+  @override
   void clear() => set.clear();
 
+  @override
   Set<E> toSet() => set.toSet();
 }
 
diff --git a/pkg/compiler/lib/src/helpers/expensive_map.dart b/pkg/compiler/lib/src/helpers/expensive_map.dart
index ed95b22..149e811 100644
--- a/pkg/compiler/lib/src/helpers/expensive_map.dart
+++ b/pkg/compiler/lib/src/helpers/expensive_map.dart
@@ -17,28 +17,39 @@
     }
   }
 
+  @override
   int get length => _maps[0].length;
+  @override
   bool get isEmpty => _maps[0].isEmpty;
+  @override
   bool get isNotEmpty => _maps[0].isNotEmpty;
 
+  @override
   Iterable<K> get keys => _maps[0].keys;
+  @override
   Iterable<V> get values => _maps[0].values;
 
+  @override
   bool containsKey(Object key) => _maps[0].containsKey(key);
+  @override
   bool containsValue(Object value) => _maps[0].containsValue(value);
 
+  @override
   V operator [](Object key) => _maps[0][key];
 
+  @override
   void forEach(void action(K key, V value)) {
     _maps[0].forEach(action);
   }
 
+  @override
   void operator []=(K key, V value) {
     for (int i = 0; i < _maps.length; i++) {
       _maps[i][key] = value;
     }
   }
 
+  @override
   V putIfAbsent(K key, V ifAbsent()) {
     if (containsKey(key)) return this[key];
     V value = ifAbsent();
@@ -46,12 +57,14 @@
     return value;
   }
 
+  @override
   void addAll(Map<K, V> other) {
     for (int i = 0; i < _maps.length; i++) {
       _maps[i].addAll(other);
     }
   }
 
+  @override
   V remove(Object key) {
     V result = _maps[0].remove(key);
     for (int i = 1; i < _maps.length; i++) {
@@ -60,24 +73,30 @@
     return result;
   }
 
+  @override
   void clear() {
     for (int i = 0; i < _maps.length; i++) {
       _maps[i].clear();
     }
   }
 
+  @override
   Map<KR, VR> cast<KR, VR>() => Map.castFrom<K, V, KR, VR>(this);
+  @override
   Iterable<MapEntry<K, V>> get entries => _maps[0].entries;
 
+  @override
   void addEntries(Iterable<MapEntry<K, V>> entries) {
     for (int i = 0; i < _maps.length; i++) {
       _maps[i].addEntries(entries);
     }
   }
 
+  @override
   Map<KR, VR> map<KR, VR>(MapEntry<KR, VR> transform(K key, V value)) =>
       _maps[0].map(transform);
 
+  @override
   V update(K key, V update(V value), {V ifAbsent()}) {
     V result;
     for (int i = 0; i < _maps.length; i++) {
@@ -86,17 +105,20 @@
     return result;
   }
 
+  @override
   void updateAll(V update(K key, V value)) {
     for (int i = 0; i < _maps.length; i++) {
       _maps[i].updateAll(update);
     }
   }
 
+  @override
   void removeWhere(bool test(K key, V value)) {
     for (int i = 0; i < _maps.length; i++) {
       _maps[i].removeWhere(test);
     }
   }
 
+  @override
   String toString() => "expensive(${_maps[0]}x${_maps.length})";
 }
diff --git a/pkg/compiler/lib/src/helpers/expensive_set.dart b/pkg/compiler/lib/src/helpers/expensive_set.dart
index f4c2f4f..4c5101e 100644
--- a/pkg/compiler/lib/src/helpers/expensive_set.dart
+++ b/pkg/compiler/lib/src/helpers/expensive_set.dart
@@ -17,19 +17,27 @@
     }
   }
 
+  @override
   int get length => _sets[0].length;
+  @override
   bool get isEmpty => _sets[0].isEmpty;
+  @override
   bool get isNotEmpty => _sets[0].isNotEmpty;
 
+  @override
   Iterator<E> get iterator => _sets[0].iterator;
 
+  @override
   bool contains(Object object) => _sets[0].contains(object);
+  @override
   E lookup(Object object) => _sets[0].lookup(object);
 
+  @override
   void forEach(void action(E element)) {
     _sets[0].forEach(action);
   }
 
+  @override
   bool add(E element) {
     bool result = _sets[0].add(element);
     for (int i = 1; i < _sets.length; i++) {
@@ -38,12 +46,14 @@
     return result;
   }
 
+  @override
   void addAll(Iterable<E> objects) {
     for (E each in objects) {
       add(each);
     }
   }
 
+  @override
   bool remove(Object object) {
     bool result = _sets[0].remove(object);
     for (int i = 1; i < _sets.length; i++) {
@@ -52,26 +62,31 @@
     return result;
   }
 
+  @override
   void clear() {
     for (int i = 0; i < _sets.length; i++) {
       _sets[i].clear();
     }
   }
 
+  @override
   void removeAll(Iterable<Object> objectsToRemove) {
     for (var each in objectsToRemove) {
       remove(each);
     }
   }
 
+  @override
   void removeWhere(bool test(E element)) {
     removeAll(this.toList().where((e) => test(e)));
   }
 
+  @override
   void retainWhere(bool test(E element)) {
     removeAll(toList().where((e) => !test(e)));
   }
 
+  @override
   bool containsAll(Iterable<Object> other) {
     for (Object object in other) {
       if (!this.contains(object)) return false;
@@ -81,6 +96,7 @@
 
   Set _newSet() => new ExpensiveSet(_sets.length);
 
+  @override
   Set<E> intersection(Set<Object> other) {
     Set<E> result = _newSet();
     if (other.length < this.length) {
@@ -95,10 +111,12 @@
     return result;
   }
 
+  @override
   Set<E> union(Set<E> other) {
     return _newSet()..addAll(this)..addAll(other);
   }
 
+  @override
   Set<E> difference(Set<Object> other) {
     Set<E> result = _newSet();
     for (E element in this) {
@@ -107,6 +125,7 @@
     return result;
   }
 
+  @override
   void retainAll(Iterable objectsToRetain) {
     Set retainSet;
     if (objectsToRetain is Set) {
@@ -117,6 +136,7 @@
     retainWhere(retainSet.contains);
   }
 
+  @override
   Set<E> toSet() {
     var result = new ExpensiveSet<E>(_sets.length);
     for (int i = 0; i < _sets.length; i++) {
@@ -125,5 +145,6 @@
     return result;
   }
 
+  @override
   String toString() => "expensive(${_sets[0]}x${_sets.length})";
 }
diff --git a/pkg/compiler/lib/src/helpers/helpers.dart b/pkg/compiler/lib/src/helpers/helpers.dart
index 2182fc0..bf34252 100644
--- a/pkg/compiler/lib/src/helpers/helpers.dart
+++ b/pkg/compiler/lib/src/helpers/helpers.dart
@@ -32,6 +32,7 @@
 }
 
 class _DebugIndentation extends Indentation {
+  @override
   final String indentationUnit = " ";
 }
 
diff --git a/pkg/compiler/lib/src/helpers/stats.dart b/pkg/compiler/lib/src/helpers/stats.dart
index 935ac8c..e524b54 100644
--- a/pkg/compiler/lib/src/helpers/stats.dart
+++ b/pkg/compiler/lib/src/helpers/stats.dart
@@ -212,6 +212,7 @@
 class DebugOutput implements StatsOutput {
   const DebugOutput();
 
+  @override
   void println(String text) => debugPrint(text);
 }
 
@@ -222,6 +223,7 @@
 
   SinkOutput(this.sink);
 
+  @override
   void println(String text) {
     sink.add(text);
     sink.add('\n');
@@ -272,6 +274,7 @@
 
 /// Abstract base class for [ConsolePrinter] and [XMLPrinter].
 abstract class BasePrinter extends StatsPrinter with Indentation {
+  @override
   final int examples;
   final StatsOutput output;
 
@@ -287,6 +290,7 @@
   ConsolePrinter({StatsOutput output: const DebugOutput(), int examples: 10})
       : super(output: output, examples: examples);
 
+  @override
   void open(String id,
       [Map<String, dynamic> data = const <String, dynamic>{}]) {
     if (extraLevel > 0) return;
@@ -316,17 +320,20 @@
     indentMore();
   }
 
+  @override
   void close(String id) {
     if (extraLevel > 0) return;
 
     indentLess();
   }
 
+  @override
   void beginExtra() {
     if (extraLevel == 0) output.println('$indentation...');
     extraLevel++;
   }
 
+  @override
   void endExtra() {
     extraLevel--;
   }
@@ -340,6 +347,7 @@
   XMLPrinter({output: const DebugOutput(), int examples: 10})
       : super(output: output, examples: examples);
 
+  @override
   void start(String id) {
     if (!opened) {
       output.println('<?xml version="1.0" encoding="UTF-8"?>');
@@ -348,10 +356,12 @@
     open(id);
   }
 
+  @override
   void end(String id) {
     close(id);
   }
 
+  @override
   void open(String id,
       [Map<String, dynamic> data = const <String, dynamic>{}]) {
     StringBuffer sb = new StringBuffer();
@@ -367,15 +377,18 @@
     indentMore();
   }
 
+  @override
   void close(String id) {
     indentLess();
     output.println('${indentation}</$id>');
   }
 
+  @override
   void beginExtra() {
     open('extra');
   }
 
+  @override
   void endExtra() {
     close('extra');
   }
@@ -450,6 +463,7 @@
     }
   }
 
+  @override
   int compareTo(_StackTraceNode other) {
     // Sorts in decreasing count order.
     return other.count - count;
@@ -479,6 +493,7 @@
     }
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     printOn(sb, '');
@@ -493,6 +508,7 @@
 
   _StackTraceTree(this.id, this.sampleFrequency) : super.root();
 
+  @override
   void dumpTraces(StatsPrinter printer) {
     printer.open('trace', {
       'id': id,
@@ -519,10 +535,12 @@
   Map<dynamic, Map<dynamic, List>> countersMap =
       <dynamic, Map<dynamic, List>>{};
   Map<dynamic, _StackTraceTree> traceMap = {};
+  @override
   int stackTraceSampleFrequency = 1;
 
   ActiveStats(StatsPrinter this.printer);
 
+  @override
   void recordMap(id, key, value, {fromExisting(value)}) {
     Map map = maps.putIfAbsent(id, () => {});
     if (fromExisting != null && map.containsKey(key)) {
@@ -532,16 +550,19 @@
     }
   }
 
+  @override
   Map getMap(key) {
     return maps[key];
   }
 
+  @override
   void recordFrequency(id, value, [example]) {
     Map<dynamic, List> map = frequencyMaps.putIfAbsent(id, () => {});
     map.putIfAbsent(value, () => []);
     map[value].add(example);
   }
 
+  @override
   void recordFrequencies(id, Map<dynamic, Iterable> frequencyMap) {
     Map<dynamic, List> map = frequencyMaps.putIfAbsent(id, () => {});
     frequencyMap.forEach((value, examples) {
@@ -550,6 +571,7 @@
     });
   }
 
+  @override
   Iterable recordedFrequencies(id, value) {
     Map<dynamic, List> map = frequencyMaps[id];
     if (map == null) return const [];
@@ -558,15 +580,18 @@
     return list;
   }
 
+  @override
   void recordCounter(id, [reason, example]) {
     Map<dynamic, List> map = countersMap.putIfAbsent(id, () => {});
     map.putIfAbsent(reason, () => []).add(example);
   }
 
+  @override
   void recordElement(key, element, {data}) {
     setsMap.putIfAbsent(key, () => new Map())[element] = data;
   }
 
+  @override
   void recordTrace(key, {int sampleFrequency}) {
     if (sampleFrequency == null) {
       sampleFrequency = stackTraceSampleFrequency;
@@ -576,12 +601,14 @@
         .sample();
   }
 
+  @override
   Iterable getList(String key) {
     Map map = setsMap[key];
     if (map == null) return const [];
     return map.keys;
   }
 
+  @override
   void dumpStats({void beforeClose()}) {
     printer.start('stats');
     dumpFrequencies();
@@ -688,6 +715,7 @@
     tree.dumpTraces(printer);
   }
 
+  @override
   void dumpCorrelation(keyA, Iterable a, keyB, Iterable b,
       {Map dataA, Map dataB}) {
     printer.child('correlations', {'title': '$keyA vs $keyB'}, () {
diff --git a/pkg/compiler/lib/src/helpers/trace.dart b/pkg/compiler/lib/src/helpers/trace.dart
index 104c227..51022cd 100644
--- a/pkg/compiler/lib/src/helpers/trace.dart
+++ b/pkg/compiler/lib/src/helpers/trace.dart
@@ -232,6 +232,7 @@
     return sb.toString();
   }
 
+  @override
   String toString() {
     return prettify();
   }
@@ -269,6 +270,7 @@
     sb.write('$fileText $lineNoText$columnNoText $method\n');
   }
 
+  @override
   int get hashCode {
     return 13 * index +
         17 * file.hashCode +
@@ -277,6 +279,7 @@
         29 * method.hashCode;
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! StackTraceLine) return false;
@@ -287,6 +290,7 @@
         method == other.method;
   }
 
+  @override
   String toString() => "$method @ $file [$lineNo:$columnNo]";
 }
 
diff --git a/pkg/compiler/lib/src/helpers/track_map.dart b/pkg/compiler/lib/src/helpers/track_map.dart
index 6cb7121..23d3ce4 100644
--- a/pkg/compiler/lib/src/helpers/track_map.dart
+++ b/pkg/compiler/lib/src/helpers/track_map.dart
@@ -48,23 +48,34 @@
     });
   }
 
+  @override
   int get length => _map.length;
+  @override
   bool get isEmpty => _map.isEmpty;
+  @override
   bool get isNotEmpty => _map.isNotEmpty;
 
+  @override
   Iterable<K> get keys => _map.keys;
+  @override
   Iterable<V> get values => _map.values;
 
+  @override
   bool containsKey(Object key) => _map.containsKey(key);
+  @override
   bool containsValue(Object value) => _map.containsValue(value);
 
+  @override
   V operator [](Object key) => _map[key];
+  @override
   String toString() => _map.toString();
 
+  @override
   void forEach(void action(K key, V value)) {
     _map.forEach(action);
   }
 
+  @override
   void operator []=(K key, V value) {
     if (!_map.containsKey(key)) {
       _notifyLengthChanged(1);
@@ -72,6 +83,7 @@
     }
   }
 
+  @override
   V putIfAbsent(K key, V ifAbsent()) {
     if (containsKey(key)) return this[key];
     V value = ifAbsent();
@@ -79,6 +91,7 @@
     return value;
   }
 
+  @override
   V remove(Object key) {
     if (_map.containsKey(key)) {
       _notifyLengthChanged(-1);
@@ -86,32 +99,41 @@
     return _map.remove(key);
   }
 
+  @override
   void addAll(Map<K, V> other) {
     other.forEach((key, value) => this[key] = value);
   }
 
+  @override
   void clear() {
     _notifyLengthChanged(-_map.length);
     _map.clear();
   }
 
+  @override
   Map<KR, VR> cast<KR, VR>() => _map.cast<KR, VR>();
+  @override
   Iterable<MapEntry<K, V>> get entries => _map.entries;
 
+  @override
   void addEntries(Iterable<MapEntry<K, V>> entries) {
     for (var entry in entries) this[entry.key] = entry.value;
   }
 
+  @override
   Map<KR, VR> map<KR, VR>(MapEntry<KR, VR> transform(K key, V value)) =>
       _map.map(transform);
 
+  @override
   V update(K key, V update(V value), {V ifAbsent()}) =>
       _map.update(key, update, ifAbsent: ifAbsent);
 
+  @override
   void updateAll(V update(K key, V value)) {
     _map.updateAll(update);
   }
 
+  @override
   void removeWhere(bool test(K key, V value)) {
     int before = _map.length;
     _map.removeWhere(test);
diff --git a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
index 1352562..1503b1d 100644
--- a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
+++ b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
@@ -45,6 +45,7 @@
 
   static AbstractBool maybeOrFalse(bool value) => value ? Maybe : False;
 
+  @override
   String toString() =>
       'AbstractBool.${_value == null ? 'Maybe' : (_value ? 'True' : 'False')}';
 }
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index b88d849..dd872ab 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -1973,6 +1973,7 @@
     sb.write('\n]');
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('LocalState(');
diff --git a/pkg/compiler/lib/src/inferrer/closure_tracer.dart b/pkg/compiler/lib/src/inferrer/closure_tracer.dart
index e7ecf72..7558fcc 100644
--- a/pkg/compiler/lib/src/inferrer/closure_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/closure_tracer.dart
@@ -28,6 +28,7 @@
         "${tracedElements.where((f) => f.isAbstract)}");
   }
 
+  @override
   ApplyableTypeInformation get tracedType => super.tracedType;
 
   void run() {
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index 9692c59..801da74 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -252,6 +252,7 @@
   final Map<Local, TypeInformation> defaultTypeOfParameter =
       new Map<Local, TypeInformation>();
   final WorkQueue workQueue = new WorkQueue();
+  @override
   final FunctionEntity mainElement;
   final Set<MemberEntity> analyzedElements = new Set<MemberEntity>();
 
@@ -263,16 +264,22 @@
   int overallRefineCount = 0;
   int addedInGraph = 0;
 
+  @override
   final CompilerOptions options;
   final Progress progress;
+  @override
   final DiagnosticReporter reporter;
   final CompilerOutput _compilerOutput;
 
   /// The [JClosedWorld] on which inference reasoning is based.
+  @override
   final JsClosedWorld closedWorld;
+  @override
   final InferredDataBuilder inferredDataBuilder;
 
+  @override
   final TypeSystem types;
+  @override
   final Map<ir.Node, TypeInformation> concreteTypes =
       new Map<ir.Node, TypeInformation>();
 
@@ -300,6 +307,7 @@
 
   ElementEnvironment get _elementEnvironment => closedWorld.elementEnvironment;
 
+  @override
   void forEachElementMatching(
       Selector selector, AbstractValue mask, bool f(MemberEntity element)) {
     Iterable<MemberEntity> elements = closedWorld.locateMembers(selector, mask);
@@ -309,6 +317,7 @@
   }
 
   // TODO(johnniwinther): Make this private again.
+  @override
   GlobalTypeInferenceElementData dataOfMember(MemberEntity element) =>
       _memberData[element] ??= new KernelGlobalTypeInferenceElementData();
 
@@ -342,6 +351,7 @@
     }
   }
 
+  @override
   TypeInformation typeOfNativeBehavior(NativeBehavior nativeBehavior) {
     if (nativeBehavior == null) return types.dynamicType;
     List typesReturned = nativeBehavior.typesReturned;
@@ -382,6 +392,7 @@
     return returnType;
   }
 
+  @override
   void updateSelectorInMember(MemberEntity owner, CallType callType,
       ir.Node node, Selector selector, AbstractValue mask) {
     KernelGlobalTypeInferenceElementData data = dataOfMember(owner);
@@ -403,26 +414,31 @@
     }
   }
 
+  @override
   bool checkIfExposesThis(ConstructorEntity element) {
     return generativeConstructorsExposingThis.contains(element);
   }
 
+  @override
   void recordExposesThis(ConstructorEntity element, bool exposesThis) {
     if (exposesThis) {
       generativeConstructorsExposingThis.add(element);
     }
   }
 
+  @override
   bool returnsListElementType(Selector selector, AbstractValue mask) {
     return mask != null &&
         abstractValueDomain.isContainer(mask) &&
         returnsListElementTypeSet.contains(selector);
   }
 
+  @override
   bool returnsMapValueType(Selector selector, AbstractValue mask) {
     return mask != null && abstractValueDomain.isMap(mask) && selector.isIndex;
   }
 
+  @override
   void analyzeListAndEnqueue(ListTypeInformation info) {
     if (info.analyzed) return;
     info.analyzed = true;
@@ -443,6 +459,7 @@
     workQueue.add(info.elementType);
   }
 
+  @override
   void analyzeSetAndEnqueue(SetTypeInformation info) {
     if (info.analyzed) return;
     info.analyzed = true;
@@ -460,6 +477,7 @@
     workQueue.add(info.elementType);
   }
 
+  @override
   void analyzeMapAndEnqueue(MapTypeInformation info) {
     if (info.analyzed) return;
     info.analyzed = true;
@@ -485,6 +503,7 @@
     workQueue.add(info);
   }
 
+  @override
   void runOverAllElements() {
     analyzeAllElements();
     TypeGraphDump dump =
@@ -733,6 +752,7 @@
     return function;
   }
 
+  @override
   void analyze(MemberEntity element) {
     if (analyzedElements.contains(element)) return;
     analyzedElements.add(element);
@@ -906,6 +926,7 @@
     workQueue.addAll(types.allocatedCalls);
   }
 
+  @override
   void updateParameterAssignments(TypeInformation caller, MemberEntity callee,
       ArgumentsTypes arguments, Selector selector, AbstractValue mask,
       {bool remove, bool addToQueue: true}) {
@@ -970,6 +991,7 @@
     }
   }
 
+  @override
   void setDefaultTypeOfParameter(Local parameter, TypeInformation type,
       {bool isInstanceMember}) {
     assert(
@@ -997,6 +1019,7 @@
     }
   }
 
+  @override
   TypeInformation getDefaultTypeOfParameter(Local parameter) {
     return defaultTypeOfParameter.putIfAbsent(parameter, () {
       return new PlaceholderTypeInformation(
@@ -1004,29 +1027,35 @@
     });
   }
 
+  @override
   bool hasAlreadyComputedTypeOfParameterDefault(Local parameter) {
     TypeInformation seen = defaultTypeOfParameter[parameter];
     return (seen != null && seen is! PlaceholderTypeInformation);
   }
 
+  @override
   TypeInformation typeOfParameter(Local element) {
     return types.getInferredTypeOfParameter(element);
   }
 
+  @override
   TypeInformation typeOfMember(MemberEntity element) {
     if (element is FunctionEntity) return types.functionType;
     return types.getInferredTypeOfMember(element);
   }
 
+  @override
   TypeInformation returnTypeOfMember(MemberEntity element) {
     if (element is! FunctionEntity) return types.dynamicType;
     return types.getInferredTypeOfMember(element);
   }
 
+  @override
   void recordTypeOfField(FieldEntity element, TypeInformation type) {
     types.getInferredTypeOfMember(element).addAssignment(type);
   }
 
+  @override
   void recordReturnType(FunctionEntity element, TypeInformation type) {
     TypeInformation info = types.getInferredTypeOfMember(element);
     if (element.name == '==') {
@@ -1039,6 +1068,7 @@
     if (info.assignments.isEmpty) info.addAssignment(type);
   }
 
+  @override
   TypeInformation addReturnTypeForMethod(
       FunctionEntity element, TypeInformation unused, TypeInformation newType) {
     TypeInformation type = types.getInferredTypeOfMember(element);
@@ -1051,6 +1081,7 @@
     return type;
   }
 
+  @override
   TypeInformation registerCalledMember(
       Object node,
       Selector selector,
@@ -1090,6 +1121,7 @@
     return info;
   }
 
+  @override
   TypeInformation registerCalledSelector(
       CallType callType,
       ir.Node node,
@@ -1132,6 +1164,7 @@
     return info;
   }
 
+  @override
   TypeInformation registerAwait(ir.Node node, TypeInformation argument) {
     AwaitTypeInformation info = new AwaitTypeInformation(
         abstractValueDomain, types.currentMember, node);
@@ -1140,6 +1173,7 @@
     return info;
   }
 
+  @override
   TypeInformation registerYield(ir.Node node, TypeInformation argument) {
     YieldTypeInformation info = new YieldTypeInformation(
         abstractValueDomain, types.currentMember, node);
@@ -1148,6 +1182,7 @@
     return info;
   }
 
+  @override
   TypeInformation registerCalledClosure(
       ir.Node node,
       Selector selector,
@@ -1173,6 +1208,7 @@
     return info;
   }
 
+  @override
   void close() {
     for (MemberTypeInformation typeInformation
         in types.memberTypeInformations.values) {
@@ -1180,6 +1216,7 @@
     }
   }
 
+  @override
   void clear() {
     if (retainDataForTesting) return;
 
@@ -1213,11 +1250,13 @@
     _memberData.clear();
   }
 
+  @override
   Iterable<MemberEntity> getCallersOfForTesting(MemberEntity element) {
     MemberTypeInformation info = types.getInferredTypeOfMember(element);
     return info.callersForTesting;
   }
 
+  @override
   TypeInformation typeOfMemberWithSelector(
       MemberEntity element, Selector selector) {
     if (element.name == Identifiers.noSuchMethod_ &&
@@ -1252,6 +1291,7 @@
   ///
   /// One category of elements that do not apply is runtime helpers that the
   /// backend calls, but the optimizations don't see those calls.
+  @override
   bool canFieldBeUsedForGlobalOptimizations(FieldEntity element) {
     if (closedWorld.backendUsage.isFieldUsedByBackend(element)) {
       return false;
@@ -1267,6 +1307,7 @@
   ///
   /// One category of elements that do not apply is runtime helpers that the
   /// backend calls, but the optimizations don't see those calls.
+  @override
   bool canFunctionParametersBeUsedForGlobalOptimizations(
       FunctionEntity function) {
     return !closedWorld.backendUsage.isFunctionUsedByBackend(function);
@@ -1427,6 +1468,7 @@
   }
 
   /// Serializes this [GlobalTypeInferenceElementData] to [sink].
+  @override
   void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
     sink.begin(tag);
     sink.writeTreeNodeMap(
diff --git a/pkg/compiler/lib/src/inferrer/list_tracer.dart b/pkg/compiler/lib/src/inferrer/list_tracer.dart
index dfe10a0..0f7aa07 100644
--- a/pkg/compiler/lib/src/inferrer/list_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/list_tracer.dart
@@ -154,10 +154,12 @@
     }
   }
 
+  @override
   visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) {
     bailout('Passed to a closure');
   }
 
+  @override
   visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
     super.visitStaticCallSiteTypeInformation(info);
     MemberEntity called = info.calledElement;
@@ -167,6 +169,7 @@
     }
   }
 
+  @override
   visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) {
     super.visitDynamicCallSiteTypeInformation(info);
     Selector selector = info.selector;
diff --git a/pkg/compiler/lib/src/inferrer/locals_handler.dart b/pkg/compiler/lib/src/inferrer/locals_handler.dart
index aff2896..a94ddbd 100644
--- a/pkg/compiler/lib/src/inferrer/locals_handler.dart
+++ b/pkg/compiler/lib/src/inferrer/locals_handler.dart
@@ -170,6 +170,7 @@
     sb.write(']');
   }
 
+  @override
   String toString() {
     String rest = parent == null ? "null" : parent.toString();
     return '{$variables} $rest';
@@ -253,12 +254,16 @@
       : positional = const [],
         named = const {};
 
+  @override
   int get length => positional.length + named.length;
 
+  @override
   Iterator<TypeInformation> get iterator => new ArgumentsTypesIterator(this);
 
+  @override
   String toString() => "{ positional = $positional, named = $named }";
 
+  @override
   bool operator ==(other) {
     if (positional.length != other.positional.length) return false;
     if (named.length != other.named.length) return false;
@@ -272,19 +277,23 @@
     return result;
   }
 
+  @override
   int get hashCode => throw new UnsupportedError('ArgumentsTypes.hashCode');
 
   bool hasNoArguments() => positional.isEmpty && named.isEmpty;
 
+  @override
   void forEach(void f(TypeInformation type)) {
     positional.forEach(f);
     named.values.forEach(f);
   }
 
+  @override
   bool every(bool f(TypeInformation type)) {
     return positional.every(f) && named.values.every(f);
   }
 
+  @override
   bool contains(Object type) {
     return positional.contains(type) || named.containsValue(type);
   }
@@ -302,8 +311,10 @@
   Iterator<TypeInformation> get _currentIterator =>
       _iteratePositional ? positional : named;
 
+  @override
   TypeInformation get current => _currentIterator.current;
 
+  @override
   bool moveNext() {
     if (_iteratePositional && positional.moveNext()) {
       return true;
@@ -587,6 +598,7 @@
     sb.write('\n]');
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('LocalsHandler(');
diff --git a/pkg/compiler/lib/src/inferrer/map_tracer.dart b/pkg/compiler/lib/src/inferrer/map_tracer.dart
index e9da06a..4925dfc 100644
--- a/pkg/compiler/lib/src/inferrer/map_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/map_tracer.dart
@@ -58,10 +58,12 @@
     return false;
   }
 
+  @override
   visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) {
     bailout('Passed to a closure');
   }
 
+  @override
   visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
     super.visitStaticCallSiteTypeInformation(info);
     MemberEntity called = info.calledElement;
@@ -71,6 +73,7 @@
     }
   }
 
+  @override
   visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) {
     super.visitDynamicCallSiteTypeInformation(info);
     Selector selector = info.selector;
diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart
index 0a3d2ee..987cb11 100644
--- a/pkg/compiler/lib/src/inferrer/node_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart
@@ -184,10 +184,12 @@
     continueAnalyzing = false;
   }
 
+  @override
   void visitAwaitTypeInformation(AwaitTypeInformation info) {
     bailout("Passed through await");
   }
 
+  @override
   void visitYieldTypeInformation(YieldTypeInformation info) {
     // TODO(29344): The enclosing sync*/async/async* method could have a
     // tracable TypeInformation for the Iterable / Future / Stream with an
@@ -196,55 +198,70 @@
     bailout("Passed through yield");
   }
 
+  @override
   void visitNarrowTypeInformation(NarrowTypeInformation info) {
     addNewEscapeInformation(info);
   }
 
+  @override
   void visitPhiElementTypeInformation(PhiElementTypeInformation info) {
     addNewEscapeInformation(info);
   }
 
+  @override
   void visitElementInContainerTypeInformation(
       ElementInContainerTypeInformation info) {
     addNewEscapeInformation(info);
   }
 
+  @override
   void visitElementInSetTypeInformation(ElementInSetTypeInformation info) {
     addNewEscapeInformation(info);
   }
 
+  @override
   void visitKeyInMapTypeInformation(KeyInMapTypeInformation info) {
     // We do not track the use of keys from a map, so we have to bail.
     bailout('Used as key in Map');
   }
 
+  @override
   void visitValueInMapTypeInformation(ValueInMapTypeInformation info) {
     addNewEscapeInformation(info);
   }
 
+  @override
   void visitListTypeInformation(ListTypeInformation info) {
     listsToAnalyze.add(info);
   }
 
+  @override
   void visitSetTypeInformation(SetTypeInformation info) {
     setsToAnalyze.add(info);
   }
 
+  @override
   void visitMapTypeInformation(MapTypeInformation info) {
     mapsToAnalyze.add(info);
   }
 
+  @override
   void visitConcreteTypeInformation(ConcreteTypeInformation info) {}
 
+  @override
   void visitStringLiteralTypeInformation(StringLiteralTypeInformation info) {}
 
+  @override
   void visitBoolLiteralTypeInformation(BoolLiteralTypeInformation info) {}
 
+  @override
   void visitClosureTypeInformation(ClosureTypeInformation info) {}
 
+  @override
   void visitClosureCallSiteTypeInformation(
       ClosureCallSiteTypeInformation info) {}
 
+  @override
   visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
     MemberEntity called = info.calledElement;
     TypeInformation inferred = inferrer.types.getInferredTypeOfMember(called);
@@ -258,14 +275,15 @@
     if (list.bailedOut) {
       bailout('Stored in a list that bailed out');
     } else {
-      list.flowsInto.forEach((flow) {
-        flow.users.forEach((dynamic user) {
-          if (user is! DynamicCallSiteTypeInformation) return;
-          if (user.receiver != flow) return;
-          if (inferrer.returnsListElementTypeSet.contains(user.selector)) {
-            addNewEscapeInformation(user);
-          } else if (!doesNotEscapeListSet.contains(user.selector.name)) {
-            bailout('Escape from a list via [${user.selector.name}]');
+      list.flowsInto.forEach((TypeInformation flow) {
+        flow.users.forEach((TypeInformation user) {
+          if (user is DynamicCallSiteTypeInformation) {
+            if (user.receiver != flow) return;
+            if (inferrer.returnsListElementTypeSet.contains(user.selector)) {
+              addNewEscapeInformation(user);
+            } else if (!doesNotEscapeListSet.contains(user.selector.name)) {
+              bailout('Escape from a list via [${user.selector.name}]');
+            }
           }
         });
       });
@@ -277,13 +295,15 @@
     if (set.bailedOut) {
       bailout('Stored in a set that bailed out');
     } else {
-      set.flowsInto.forEach((flow) {
-        flow.users.forEach((dynamic user) {
-          if (user.receiver != flow) return;
-          if (user.selector.isIndex) {
-            addNewEscapeInformation(user);
-          } else if (!doesNotEscapeSetSet.contains(user.selector.name)) {
-            bailout('Escape from a set via [${user.selector.name}]');
+      set.flowsInto.forEach((TypeInformation flow) {
+        flow.users.forEach((TypeInformation user) {
+          if (user is DynamicCallSiteTypeInformation) {
+            if (user.receiver != flow) return;
+            if (user.selector.isIndex) {
+              addNewEscapeInformation(user);
+            } else if (!doesNotEscapeSetSet.contains(user.selector.name)) {
+              bailout('Escape from a set via [${user.selector.name}]');
+            }
           }
         });
       });
@@ -295,14 +315,15 @@
     if (map.bailedOut) {
       bailout('Stored in a map that bailed out');
     } else {
-      map.flowsInto.forEach((flow) {
-        flow.users.forEach((dynamic user) {
-          if (user is! DynamicCallSiteTypeInformation) return;
-          if (user.receiver != flow) return;
-          if (user.selector.isIndex) {
-            addNewEscapeInformation(user);
-          } else if (!doesNotEscapeMapSet.contains(user.selector.name)) {
-            bailout('Escape from a map via [${user.selector.name}]');
+      map.flowsInto.forEach((TypeInformation flow) {
+        flow.users.forEach((TypeInformation user) {
+          if (user is DynamicCallSiteTypeInformation) {
+            if (user.receiver != flow) return;
+            if (user.selector.isIndex) {
+              addNewEscapeInformation(user);
+            } else if (!doesNotEscapeMapSet.contains(user.selector.name)) {
+              bailout('Escape from a map via [${user.selector.name}]');
+            }
           }
         });
       });
@@ -358,6 +379,7 @@
     }
   }
 
+  @override
   void visitDynamicCallSiteTypeInformation(
       DynamicCallSiteTypeInformation info) {
     void addsToContainer(AbstractValue mask) {
@@ -493,6 +515,7 @@
     return cls != null && cls.isClosure;
   }
 
+  @override
   void visitMemberTypeInformation(MemberTypeInformation info) {
     if (info.isClosurized) {
       bailout('Returned from a closurized method');
@@ -507,6 +530,7 @@
     addNewEscapeInformation(info);
   }
 
+  @override
   void visitParameterTypeInformation(ParameterTypeInformation info) {
     if (inferrer.closedWorld.nativeData.isNativeMember(info.method)) {
       bailout('Passed to a native method');
diff --git a/pkg/compiler/lib/src/inferrer/trivial.dart b/pkg/compiler/lib/src/inferrer/trivial.dart
index dcd5e97..9d4d5ef 100644
--- a/pkg/compiler/lib/src/inferrer/trivial.dart
+++ b/pkg/compiler/lib/src/inferrer/trivial.dart
@@ -16,6 +16,7 @@
 class TrivialAbstractValue implements AbstractValue {
   const TrivialAbstractValue();
 
+  @override
   String toString() => '?';
 }
 
@@ -472,5 +473,6 @@
   @override
   bool canHit(MemberEntity element, Name name, World world) => true;
 
+  @override
   String toString() => 'TrivialUniverseSelectorConstraints:$hashCode';
 }
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_dump.dart b/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
index d9ddd4d..70d3fa0 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
@@ -317,6 +317,7 @@
     }
   }
 
+  @override
   void visitNarrowTypeInformation(NarrowTypeInformation info) {
     // Omit unused Narrows.
     if (!PRINT_GRAPH_ALL_NODES && info.users.isEmpty) return;
@@ -324,50 +325,61 @@
         color: narrowColor);
   }
 
+  @override
   void visitPhiElementTypeInformation(PhiElementTypeInformation info) {
     // Omit unused Phis.
     if (!PRINT_GRAPH_ALL_NODES && info.users.isEmpty) return;
     addNode(info, 'Phi ${info.variable?.name ?? ''}', color: phiColor);
   }
 
+  @override
   void visitElementInContainerTypeInformation(
       ElementInContainerTypeInformation info) {
     addNode(info, 'ElementInContainer');
   }
 
+  @override
   void visitElementInSetTypeInformation(ElementInSetTypeInformation info) {
     addNode(info, 'ElementInSet');
   }
 
+  @override
   void visitKeyInMapTypeInformation(KeyInMapTypeInformation info) {
     addNode(info, 'KeyInMap');
   }
 
+  @override
   void visitValueInMapTypeInformation(ValueInMapTypeInformation info) {
     addNode(info, 'ValueInMap');
   }
 
+  @override
   void visitListTypeInformation(ListTypeInformation info) {
     addNode(info, 'List');
   }
 
+  @override
   void visitSetTypeInformation(SetTypeInformation info) {
     addNode(info, 'Set');
   }
 
+  @override
   void visitMapTypeInformation(MapTypeInformation info) {
     addNode(info, 'Map');
   }
 
+  @override
   void visitConcreteTypeInformation(ConcreteTypeInformation info) {
     addNode(info, 'Concrete');
   }
 
+  @override
   void visitStringLiteralTypeInformation(StringLiteralTypeInformation info) {
     String text = shorten(info.value).replaceAll('\n', '\\n');
     addNode(info, 'StringLiteral\n"$text"');
   }
 
+  @override
   void visitBoolLiteralTypeInformation(BoolLiteralTypeInformation info) {
     addNode(info, 'BoolLiteral\n${info.value}');
   }
@@ -387,38 +399,46 @@
     addNode(info, text, color: callColor, inputs: inputs);
   }
 
+  @override
   void visitClosureCallSiteTypeInformation(
       ClosureCallSiteTypeInformation info) {
     handleCall(info, 'ClosureCallSite', {});
   }
 
+  @override
   void visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
     handleCall(info, 'StaticCallSite', {});
   }
 
+  @override
   void visitDynamicCallSiteTypeInformation(
       DynamicCallSiteTypeInformation info) {
     handleCall(info, 'DynamicCallSite', {'obj': info.receiver});
   }
 
+  @override
   void visitMemberTypeInformation(MemberTypeInformation info) {
     addNode(info, 'Member\n${info.debugName}');
   }
 
+  @override
   void visitParameterTypeInformation(ParameterTypeInformation info) {
     addNode(info, 'Parameter ${info.debugName}');
   }
 
+  @override
   void visitClosureTypeInformation(ClosureTypeInformation info) {
     String text = shorten('${info.debugName}');
     addNode(info, 'Closure\n$text');
   }
 
+  @override
   void visitAwaitTypeInformation(AwaitTypeInformation info) {
     String text = shorten('${info.debugName}');
     addNode(info, 'Await\n$text');
   }
 
+  @override
   void visitYieldTypeInformation(YieldTypeInformation info) {
     String text = shorten('${info.debugName}');
     addNode(info, 'Yield\n$text');
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index d9f69ca..d1b919c 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -62,6 +62,7 @@
   AbstractValueDomain get abstractValueDomain =>
       closedWorld.abstractValueDomain;
 
+  @override
   GlobalTypeInferenceResults analyzeMain(FunctionEntity main) {
     inferrer = createInferrerEngineFor(main);
     inferrer.runOverAllElements();
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index 467890a..b8d5dcc 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -79,6 +79,7 @@
 
   // TypeInformations are unique. Store an arbitrary identity hash code.
   static int _staticHashCode = 0;
+  @override
   final int hashCode = _staticHashCode = (_staticHashCode + 1).toUnsigned(30);
 
   bool get isConcrete => false;
@@ -248,14 +249,17 @@
       AbstractValueDomain abstractValueDomain, MemberTypeInformation context)
       : super(abstractValueDomain.emptyType, context);
 
+  @override
   void accept(TypeInformationVisitor visitor) {
     throw new UnsupportedError("Cannot visit placeholder");
   }
 
+  @override
   AbstractValue computeType(InferrerEngine inferrer) {
     throw new UnsupportedError("Cannot refine placeholder");
   }
 
+  @override
   toString() => "Placeholder [$hashCode]";
 }
 
@@ -296,11 +300,15 @@
     }
   }
 
+  @override
   Iterator<TypeInformation> get iterator => assignments.keys.iterator;
+  @override
   Iterable<TypeInformation> where(Function f) => assignments.keys.where(f);
 
+  @override
   bool contains(Object info) => assignments.containsKey(info);
 
+  @override
   String toString() => assignments.keys.toList().toString();
 }
 
@@ -386,6 +394,7 @@
 
   MemberEntity get member => _member;
 
+  @override
   String get debugName => '$member';
 
   void addCall(MemberEntity caller, Object node) {
@@ -438,6 +447,7 @@
   // [users] is accurate. The inference stops tracking users for stable types.
   // Note that we only override the getter, the setter will still modify the
   // state of the [isStable] field inherited from [TypeInformation].
+  @override
   bool get isStable => super.isStable && !isClosurized;
 
   AbstractValue handleSpecialCases(InferrerEngine inferrer);
@@ -469,6 +479,7 @@
   AbstractValue _potentiallyNarrowType(
       AbstractValue mask, InferrerEngine inferrer);
 
+  @override
   AbstractValue computeType(InferrerEngine inferrer) {
     AbstractValue special = handleSpecialCases(inferrer);
     if (special != null) return potentiallyNarrowType(special, inferrer);
@@ -476,16 +487,20 @@
         inferrer.types.computeTypeMask(assignments), inferrer);
   }
 
+  @override
   AbstractValue safeType(InferrerEngine inferrer) {
     return potentiallyNarrowType(super.safeType(inferrer), inferrer);
   }
 
+  @override
   String toString() => 'Member $_member $type';
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitMemberTypeInformation(this);
   }
 
+  @override
   void cleanup() {
     _callers = null;
     super.cleanup();
@@ -505,6 +520,7 @@
       AbstractValueDomain abstractValueDomain, FieldEntity element, this._type)
       : super._internal(abstractValueDomain, element);
 
+  @override
   AbstractValue handleSpecialCases(InferrerEngine inferrer) {
     if (!inferrer.canFieldBeUsedForGlobalOptimizations(_field) ||
         inferrer.assumeDynamic(_field)) {
@@ -527,11 +543,13 @@
     return null;
   }
 
+  @override
   AbstractValue _potentiallyNarrowType(
       AbstractValue mask, InferrerEngine inferrer) {
     return _narrowType(inferrer.closedWorld, mask, _type);
   }
 
+  @override
   bool hasStableType(InferrerEngine inferrer) {
     // The number of assignments of non-final fields is
     // not stable. Therefore such a field cannot be stable.
@@ -550,10 +568,12 @@
       FunctionEntity element, this._type)
       : super._internal(abstractValueDomain, element);
 
+  @override
   AbstractValue handleSpecialCases(InferrerEngine inferrer) {
     return _handleFunctionCase(_getter, inferrer);
   }
 
+  @override
   AbstractValue _potentiallyNarrowType(
       AbstractValue mask, InferrerEngine inferrer) {
     return _narrowType(inferrer.closedWorld, mask, _type.returnType);
@@ -567,10 +587,12 @@
       AbstractValueDomain abstractValueDomain, FunctionEntity element)
       : super._internal(abstractValueDomain, element);
 
+  @override
   AbstractValue handleSpecialCases(InferrerEngine inferrer) {
     return _handleFunctionCase(_setter, inferrer);
   }
 
+  @override
   AbstractValue _potentiallyNarrowType(
       AbstractValue mask, InferrerEngine inferrer) {
     return mask;
@@ -585,15 +607,18 @@
       FunctionEntity element, this._type)
       : super._internal(abstractValueDomain, element);
 
+  @override
   AbstractValue handleSpecialCases(InferrerEngine inferrer) {
     return _handleFunctionCase(_method, inferrer);
   }
 
+  @override
   AbstractValue _potentiallyNarrowType(
       AbstractValue mask, InferrerEngine inferrer) {
     return _narrowType(inferrer.closedWorld, mask, _type.returnType);
   }
 
+  @override
   bool hasStableType(InferrerEngine inferrer) => false;
 }
 
@@ -605,6 +630,7 @@
       ConstructorEntity element, this._type)
       : super._internal(abstractValueDomain, element);
 
+  @override
   AbstractValue handleSpecialCases(InferrerEngine inferrer) {
     AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
     if (_constructor.isFromEnvironmentConstructor) {
@@ -624,11 +650,13 @@
     return _handleFunctionCase(_constructor, inferrer);
   }
 
+  @override
   AbstractValue _potentiallyNarrowType(
       AbstractValue mask, InferrerEngine inferrer) {
     return _narrowType(inferrer.closedWorld, mask, _type.returnType);
   }
 
+  @override
   bool hasStableType(InferrerEngine inferrer) {
     return super.hasStableType(inferrer);
   }
@@ -641,15 +669,18 @@
       AbstractValueDomain abstractValueDomain, ConstructorEntity element)
       : super._internal(abstractValueDomain, element);
 
+  @override
   AbstractValue handleSpecialCases(InferrerEngine inferrer) {
     return _handleFunctionCase(_constructor, inferrer);
   }
 
+  @override
   AbstractValue _potentiallyNarrowType(
       AbstractValue mask, InferrerEngine inferrer) {
     return mask;
   }
 
+  @override
   bool hasStableType(InferrerEngine inferrer) {
     return super.hasStableType(inferrer);
   }
@@ -708,6 +739,7 @@
 
   bool get isRegularParameter => !_isInitializingFormal;
 
+  @override
   String get debugName => '$parameter';
 
   void tagAsTearOffClosureParameter(InferrerEngine inferrer) {
@@ -805,6 +837,7 @@
     return mask;
   }
 
+  @override
   AbstractValue computeType(InferrerEngine inferrer) {
     AbstractValue special = handleSpecialCases(inferrer);
     if (special != null) return special;
@@ -812,10 +845,12 @@
         inferrer.types.computeTypeMask(assignments), inferrer);
   }
 
+  @override
   AbstractValue safeType(InferrerEngine inferrer) {
     return potentiallyNarrowType(super.safeType(inferrer), inferrer);
   }
 
+  @override
   bool hasStableType(InferrerEngine inferrer) {
     // The number of assignments of parameters of instance methods is
     // not stable. Therefore such a parameter cannot be stable.
@@ -825,10 +860,12 @@
     return super.hasStableType(inferrer);
   }
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitParameterTypeInformation(this);
   }
 
+  @override
   String toString() => 'Parameter $_parameter $type';
 
   @override
@@ -882,6 +919,7 @@
     assert(_call is ir.Node);
   }
 
+  @override
   String toString() => 'Call site $debugName $type';
 
   /// Add [this] to the graph being computed by [engine].
@@ -913,6 +951,7 @@
     return inferrer.types.getInferredTypeOfMember(calledElement);
   }
 
+  @override
   void addToGraph(InferrerEngine inferrer) {
     MemberTypeInformation callee = _getCalledTypeInfo(inferrer);
     callee.addCall(caller, _call);
@@ -937,6 +976,7 @@
     return inferrer.typeOfMemberWithSelector(calledElement, selector);
   }
 
+  @override
   AbstractValue computeType(InferrerEngine inferrer) {
     if (isSynthesized) {
       assert(arguments != null);
@@ -946,12 +986,15 @@
     }
   }
 
+  @override
   Iterable<MemberEntity> get callees => [calledElement];
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitStaticCallSiteTypeInformation(this);
   }
 
+  @override
   bool hasStableType(InferrerEngine inferrer) {
     bool isStable = _getCalledTypeInfo(inferrer).isStable;
     return isStable &&
@@ -959,6 +1002,7 @@
         super.hasStableType(inferrer);
   }
 
+  @override
   void removeAndClearReferences(InferrerEngine inferrer) {
     ElementTypeInformation callee = _getCalledTypeInfo(inferrer);
     callee.removeUser(this);
@@ -995,6 +1039,7 @@
     assert(validCallType(_callType, _call));
   }
 
+  @override
   void addToGraph(InferrerEngine inferrer) {
     assert(receiver != null);
     AbstractValue typeMask = computeTypedSelector(inferrer);
@@ -1024,6 +1069,7 @@
   /// methods on closures.
   Iterable<MemberEntity> get concreteTargets => _concreteTargets;
 
+  @override
   Iterable<MemberEntity> get callees => _concreteTargets;
 
   AbstractValue computeTypedSelector(InferrerEngine inferrer) {
@@ -1151,6 +1197,7 @@
     }
   }
 
+  @override
   AbstractValue computeType(InferrerEngine inferrer) {
     JClosedWorld closedWorld = inferrer.closedWorld;
     AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
@@ -1248,6 +1295,7 @@
     return result;
   }
 
+  @override
   void giveUp(InferrerEngine inferrer, {bool clearAssignments: true}) {
     if (!abandonInferencing) {
       inferrer.updateSelectorInMember(caller, _callType, _call, selector, mask);
@@ -1269,6 +1317,7 @@
     super.giveUp(inferrer, clearAssignments: clearAssignments);
   }
 
+  @override
   void removeAndClearReferences(InferrerEngine inferrer) {
     for (MemberEntity element in _concreteTargets) {
       MemberTypeInformation callee =
@@ -1281,12 +1330,15 @@
     super.removeAndClearReferences(inferrer);
   }
 
+  @override
   String toString() => 'Call site $debugName on ${receiver.type} $type';
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitDynamicCallSiteTypeInformation(this);
   }
 
+  @override
   bool hasStableType(InferrerEngine inferrer) {
     return receiver.isStable &&
         _concreteTargets.every((MemberEntity element) =>
@@ -1312,23 +1364,29 @@
       : super(abstractValueDomain, context, call, enclosing, selector, mask,
             arguments, inLoop);
 
+  @override
   void addToGraph(InferrerEngine inferrer) {
     arguments.forEach((info) => info.addUser(this));
     closure.addUser(this);
   }
 
+  @override
   AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
 
+  @override
   Iterable<MemberEntity> get callees {
     throw new UnsupportedError("Cannot compute callees of a closure call.");
   }
 
+  @override
   String toString() => 'Closure call $debugName on $closure';
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitClosureCallSiteTypeInformation(this);
   }
 
+  @override
   void removeAndClearReferences(InferrerEngine inferrer) {
     // This method is a placeholder for the following comment:
     // We should maintain the information that the closure is a user
@@ -1353,40 +1411,51 @@
     this.isStable = true;
   }
 
+  @override
   bool get isConcrete => true;
 
+  @override
   void addUser(TypeInformation user) {
     // Nothing to do, a concrete type does not get updated so never
     // needs to notify its users.
   }
 
+  @override
   void addUsersOf(TypeInformation other) {
     // Nothing to do, a concrete type does not get updated so never
     // needs to notify its users.
   }
 
+  @override
   void removeUser(TypeInformation user) {}
 
+  @override
   void addAssignment(TypeInformation assignment) {
     throw "Not supported";
   }
 
+  @override
   void removeAssignment(TypeInformation assignment) {
     throw "Not supported";
   }
 
+  @override
   AbstractValue computeType(InferrerEngine inferrer) => type;
 
+  @override
   bool reset(InferrerEngine inferrer) {
     throw "Not supported";
   }
 
+  @override
   String toString() => 'Type $type';
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitConcreteTypeInformation(this);
   }
 
+  @override
   bool hasStableType(InferrerEngine inferrer) => true;
 }
 
@@ -1399,8 +1468,10 @@
             mask, new StringConstantValue(value)));
 
   String asString() => value;
+  @override
   String toString() => 'Type $type value ${value}';
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitStringLiteralTypeInformation(this);
   }
@@ -1414,8 +1485,10 @@
       : super(abstractValueDomain.createPrimitiveValue(
             mask, value ? new TrueConstantValue() : new FalseConstantValue()));
 
+  @override
   String toString() => 'Type $type value ${value}';
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitBoolLiteralTypeInformation(this);
   }
@@ -1447,11 +1520,13 @@
     addAssignment(narrowedType);
   }
 
+  @override
   addAssignment(TypeInformation info) {
     super.addAssignment(info);
     assert(assignments.length == 1);
   }
 
+  @override
   AbstractValue computeType(InferrerEngine inferrer) {
     AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
     AbstractValue input = assignments.first.type;
@@ -1469,10 +1544,12 @@
     return intersection;
   }
 
+  @override
   String toString() {
     return 'Narrow to $typeAnnotation $type';
   }
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitNarrowTypeInformation(this);
   }
@@ -1492,11 +1569,13 @@
     if (parentType != null) addAssignment(parentType);
   }
 
+  @override
   AbstractValue computeType(InferrerEngine inferrer) {
     if (!inferred) return safeType(inferrer);
     return inferrer.types.computeTypeMask(assignments);
   }
 
+  @override
   bool hasStableType(InferrerEngine inferrer) {
     return inferred && super.hasStableType(inferrer);
   }
@@ -1531,16 +1610,20 @@
     elementType.addUser(this);
   }
 
+  @override
   String toString() => 'List type $type';
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitListTypeInformation(this);
   }
 
+  @override
   bool hasStableType(InferrerEngine inferrer) {
     return elementType.isStable && super.hasStableType(inferrer);
   }
 
+  @override
   AbstractValue computeType(InferrerEngine inferrer) {
     AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
     AbstractValue mask = type;
@@ -1557,8 +1640,10 @@
     return mask;
   }
 
+  @override
   AbstractValue safeType(InferrerEngine inferrer) => originalType;
 
+  @override
   void cleanup() {
     super.cleanup();
     elementType.cleanup();
@@ -1573,8 +1658,10 @@
       MemberTypeInformation context, elementType)
       : super(abstractValueDomain, context, elementType);
 
+  @override
   String toString() => 'Element in container $type';
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitElementInContainerTypeInformation(this);
   }
@@ -1592,12 +1679,15 @@
     elementType.addUser(this);
   }
 
+  @override
   String toString() => 'Set type $type';
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitSetTypeInformation(this);
   }
 
+  @override
   AbstractValue computeType(InferrerEngine inferrer) {
     AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
     AbstractValue mask = type;
@@ -1612,12 +1702,15 @@
     return mask;
   }
 
+  @override
   AbstractValue safeType(InferrerEngine inferrer) => originalType;
 
+  @override
   bool hasStableType(InferrerEngine inferrer) {
     return elementType.isStable && super.hasStableType(inferrer);
   }
 
+  @override
   void cleanup() {
     super.cleanup();
     elementType.cleanup();
@@ -1632,8 +1725,10 @@
       MemberTypeInformation context, elementType)
       : super(abstractValueDomain, context, elementType);
 
+  @override
   String toString() => 'Element in set $type';
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitElementInSetTypeInformation(this);
   }
@@ -1713,10 +1808,12 @@
     typeInfoMap.values.forEach((v) => v.inferred = true);
   }
 
+  @override
   addAssignment(TypeInformation other) {
     throw "not supported";
   }
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitMapTypeInformation(this);
   }
@@ -1745,6 +1842,7 @@
     }
   }
 
+  @override
   AbstractValue computeType(InferrerEngine inferrer) {
     AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
     if (abstractValueDomain.isDictionary(type) != inDictionaryMode) {
@@ -1775,14 +1873,17 @@
     return type;
   }
 
+  @override
   AbstractValue safeType(InferrerEngine inferrer) => originalType;
 
+  @override
   bool hasStableType(InferrerEngine inferrer) {
     return keyType.isStable &&
         valueType.isStable &&
         super.hasStableType(inferrer);
   }
 
+  @override
   void cleanup() {
     super.cleanup();
     keyType.cleanup();
@@ -1793,6 +1894,7 @@
     _flowsInto = null;
   }
 
+  @override
   String toString() {
     return 'Map $type (K:$keyType, V:$valueType) contents $typeInfoMap';
   }
@@ -1805,10 +1907,12 @@
       MemberTypeInformation context, TypeInformation keyType)
       : super(abstractValueDomain, context, keyType);
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitKeyInMapTypeInformation(this);
   }
 
+  @override
   String toString() => 'Key in Map $type';
 }
 
@@ -1825,16 +1929,19 @@
       [this.nonNull = false])
       : super(abstractValueDomain, context, valueType);
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitValueInMapTypeInformation(this);
   }
 
+  @override
   AbstractValue computeType(InferrerEngine inferrer) {
     return nonNull
         ? super.computeType(inferrer)
         : inferrer.abstractValueDomain.includeNull(super.computeType(inferrer));
   }
 
+  @override
   String toString() => 'Value in Map $type';
 }
 
@@ -1850,12 +1957,15 @@
       {this.isTry})
       : super(abstractValueDomain.emptyType, context);
 
+  @override
   AbstractValue computeType(InferrerEngine inferrer) {
     return inferrer.types.computeTypeMask(assignments);
   }
 
+  @override
   String toString() => 'Phi($hashCode) $variable $type';
 
+  @override
   void _toStructuredText(
       StringBuffer sb, String indent, Set<TypeInformation> seen) {
     if (seen.add(this)) {
@@ -1870,6 +1980,7 @@
     }
   }
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitPhiElementTypeInformation(this);
   }
@@ -1885,20 +1996,25 @@
 
   FunctionEntity get closure => _element;
 
+  @override
   AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
 
+  @override
   AbstractValue safeType(InferrerEngine inferrer) {
     return inferrer.types.functionType.type;
   }
 
   String get debugName => '$closure';
 
+  @override
   String toString() => 'Closure $_element';
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitClosureTypeInformation(this);
   }
 
+  @override
   bool hasStableType(InferrerEngine inferrer) {
     return false;
   }
@@ -1945,12 +2061,15 @@
       : super(abstractValueDomain.emptyType, context);
 
   // TODO(22894): Compute a better type here.
+  @override
   AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
 
   String get debugName => '$_node';
 
+  @override
   String toString() => 'Await';
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitAwaitTypeInformation(this);
   }
@@ -1963,12 +2082,15 @@
       MemberTypeInformation context, this._node)
       : super(abstractValueDomain.emptyType, context);
 
+  @override
   AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
 
   String get debugName => '$_node';
 
+  @override
   String toString() => 'Yield';
 
+  @override
   accept(TypeInformationVisitor visitor) {
     return visitor.visitYieldTypeInformation(this);
   }
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/container_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/container_type_mask.dart
index 4b27265..e920091 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/container_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/container_type_mask.dart
@@ -12,12 +12,15 @@
   /// debugging data stream.
   static const String tag = 'container-type-mask';
 
+  @override
   final TypeMask forwardTo;
 
   // The [Node] where this type mask was created.
+  @override
   final ir.TreeNode allocationNode;
 
   // The [Entity] where this type mask was created.
+  @override
   final MemberEntity allocationElement;
 
   // The element type of this container.
@@ -44,6 +47,7 @@
   }
 
   /// Serializes this [ContainerTypeMask] to [sink].
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(TypeMaskKind.container);
     sink.begin(tag);
@@ -55,6 +59,7 @@
     sink.end(tag);
   }
 
+  @override
   TypeMask nullable() {
     return isNullable
         ? this
@@ -62,6 +67,7 @@
             allocationElement, elementType, length);
   }
 
+  @override
   TypeMask nonNullable() {
     return isNullable
         ? new ContainerTypeMask(forwardTo.nonNullable(), allocationNode,
@@ -69,9 +75,12 @@
         : this;
   }
 
+  @override
   bool get isContainer => true;
+  @override
   bool get isExact => true;
 
+  @override
   bool equalsDisregardNull(other) {
     if (other is! ContainerTypeMask) return false;
     return super.equalsDisregardNull(other) &&
@@ -80,12 +89,14 @@
         length == other.length;
   }
 
+  @override
   TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
     TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
     if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
     return forwardIntersection.isNullable ? nullable() : nonNullable();
   }
 
+  @override
   TypeMask union(dynamic other, JClosedWorld closedWorld) {
     if (this == other) {
       return this;
@@ -113,13 +124,16 @@
     }
   }
 
+  @override
   bool operator ==(other) => super == other;
 
+  @override
   int get hashCode {
     return computeHashCode(
         allocationNode, isNullable, elementType, length, forwardTo);
   }
 
+  @override
   String toString() {
     return 'Container($forwardTo, element: $elementType, length: $length)';
   }
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
index 8463350..827840c 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
@@ -44,6 +44,7 @@
   }
 
   /// Serializes this [DictionaryTypeMask] to [sink].
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(TypeMaskKind.dictionary);
     sink.begin(tag);
@@ -59,6 +60,7 @@
     sink.end(tag);
   }
 
+  @override
   TypeMask nullable() {
     return isNullable
         ? this
@@ -66,6 +68,7 @@
             allocationElement, keyType, valueType, _typeMap);
   }
 
+  @override
   TypeMask nonNullable() {
     return isNullable
         ? new DictionaryTypeMask(forwardTo.nonNullable(), allocationNode,
@@ -73,13 +76,16 @@
         : this;
   }
 
+  @override
   bool get isDictionary => true;
+  @override
   bool get isExact => true;
 
   bool containsKey(String key) => _typeMap.containsKey(key);
 
   TypeMask getValueForKey(String key) => _typeMap[key];
 
+  @override
   bool equalsDisregardNull(other) {
     if (other is! DictionaryTypeMask) return false;
     return allocationNode == other.allocationNode &&
@@ -90,12 +96,14 @@
             (k) => _typeMap.containsKey(k) && _typeMap[k] == other._typeMap[k]);
   }
 
+  @override
   TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
     TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
     if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
     return forwardIntersection.isNullable ? nullable() : nonNullable();
   }
 
+  @override
   TypeMask union(dynamic other, JClosedWorld closedWorld) {
     if (this == other) {
       return this;
@@ -135,12 +143,15 @@
     }
   }
 
+  @override
   bool operator ==(other) => super == other;
 
+  @override
   int get hashCode {
     return computeHashCode(allocationNode, isNullable, _typeMap, forwardTo);
   }
 
+  @override
   String toString() {
     return 'Dictionary($forwardTo, key: $keyType, '
         'value: $valueType, map: $_typeMap)';
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart
index 8478b0f..d8ddc8a 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart
@@ -78,6 +78,7 @@
   }
 
   /// Serializes this [FlatTypeMask] to [sink].
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(TypeMaskKind.flat);
     sink.begin(tag);
@@ -90,18 +91,30 @@
       ? ClassQuery.EXACT
       : (isSubclass ? ClassQuery.SUBCLASS : ClassQuery.SUBTYPE);
 
+  @override
   bool get isEmpty => isEmptyOrNull && !isNullable;
+  @override
   bool get isNull => isEmptyOrNull && isNullable;
+  @override
   bool get isEmptyOrNull => (flags >> 1) == EMPTY;
+  @override
   bool get isExact => (flags >> 1) == EXACT;
+  @override
   bool get isNullable => (flags & 1) != 0;
 
+  @override
   bool get isUnion => false;
+  @override
   bool get isContainer => false;
+  @override
   bool get isSet => false;
+  @override
   bool get isMap => false;
+  @override
   bool get isDictionary => false;
+  @override
   bool get isForwarding => false;
+  @override
   bool get isValue => false;
 
   // TODO(kasperl): Get rid of these. They should not be a visible
@@ -110,14 +123,17 @@
   bool get isSubclass => (flags >> 1) == SUBCLASS;
   bool get isSubtype => (flags >> 1) == SUBTYPE;
 
+  @override
   TypeMask nullable() {
     return isNullable ? this : new FlatTypeMask.internal(base, flags | 1);
   }
 
+  @override
   TypeMask nonNullable() {
     return isNullable ? new FlatTypeMask.internal(base, flags & ~1) : this;
   }
 
+  @override
   bool contains(ClassEntity other, JClosedWorld closedWorld) {
     if (isEmptyOrNull) {
       return false;
@@ -162,6 +178,7 @@
     return false;
   }
 
+  @override
   bool isInMask(TypeMask other, JClosedWorld closedWorld) {
     if (isEmptyOrNull) return isNullable ? other.isNullable : true;
     // The empty type contains no classes.
@@ -195,10 +212,12 @@
     return satisfies(otherBase, closedWorld);
   }
 
+  @override
   bool containsMask(TypeMask other, JClosedWorld closedWorld) {
     return other.isInMask(this, closedWorld);
   }
 
+  @override
   bool containsOnlyInt(JClosedWorld closedWorld) {
     CommonElements commonElements = closedWorld.commonElements;
     return base == closedWorld.commonElements.intClass ||
@@ -208,11 +227,13 @@
         base == commonElements.jsUInt32Class;
   }
 
+  @override
   bool containsOnlyDouble(JClosedWorld closedWorld) {
     return base == closedWorld.commonElements.doubleClass ||
         base == closedWorld.commonElements.jsDoubleClass;
   }
 
+  @override
   bool containsOnlyNum(JClosedWorld closedWorld) {
     return containsOnlyInt(closedWorld) ||
         containsOnlyDouble(closedWorld) ||
@@ -220,20 +241,24 @@
         base == closedWorld.commonElements.jsNumberClass;
   }
 
+  @override
   bool containsOnlyBool(JClosedWorld closedWorld) {
     return base == closedWorld.commonElements.boolClass ||
         base == closedWorld.commonElements.jsBoolClass;
   }
 
+  @override
   bool containsOnlyString(JClosedWorld closedWorld) {
     return base == closedWorld.commonElements.stringClass ||
         base == closedWorld.commonElements.jsStringClass;
   }
 
+  @override
   bool containsOnly(ClassEntity cls) {
     return base == cls;
   }
 
+  @override
   bool satisfies(ClassEntity cls, JClosedWorld closedWorld) {
     if (isEmptyOrNull) return false;
     if (closedWorld.classHierarchy.isSubtypeOf(base, cls)) return true;
@@ -242,6 +267,7 @@
 
   /// Returns the [Entity] if this type represents a single class, otherwise
   /// returns `null`.  This method is conservative.
+  @override
   ClassEntity singleClass(JClosedWorld closedWorld) {
     if (isEmptyOrNull) return null;
     if (isNullable) return null; // It is Null and some other class.
@@ -258,11 +284,13 @@
   }
 
   /// Returns whether or not this type mask contains all types.
+  @override
   bool containsAll(JClosedWorld closedWorld) {
     if (isEmptyOrNull || isExact) return false;
     return identical(base, closedWorld.commonElements.objectClass);
   }
 
+  @override
   TypeMask union(TypeMask other, JClosedWorld closedWorld) {
     assert(other != null);
     assert(TypeMask.assertIsNormalized(this, closedWorld));
@@ -352,6 +380,7 @@
         : this;
   }
 
+  @override
   TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
     assert(other != null);
     if (other is! FlatTypeMask) return other.intersection(this, closedWorld);
@@ -425,6 +454,7 @@
     }
   }
 
+  @override
   bool isDisjoint(TypeMask other, JClosedWorld closedWorld) {
     if (other is! FlatTypeMask) return other.isDisjoint(this, closedWorld);
     FlatTypeMask flatOther = other;
@@ -517,6 +547,7 @@
   /// Returns whether [element] is a potential target when being
   /// invoked on this type mask. [selector] is used to ensure library
   /// privacy is taken into account.
+  @override
   bool canHit(MemberEntity element, Name name, JClosedWorld closedWorld) {
     CommonElements commonElements = closedWorld.commonElements;
     assert(element.name == name.text);
@@ -552,6 +583,7 @@
     }
   }
 
+  @override
   bool needsNoSuchMethodHandling(
       Selector selector, covariant JClosedWorld closedWorld) {
     // A call on an empty type mask is either dead code, or a call on
@@ -566,6 +598,7 @@
     return closedWorld.needsNoSuchMethod(base, selector, _classQuery);
   }
 
+  @override
   MemberEntity locateSingleMember(Selector selector, JClosedWorld closedWorld) {
     if (isEmptyOrNull) return null;
     if (closedWorld.includesClosureCall(selector, this)) return null;
@@ -593,6 +626,7 @@
     return null;
   }
 
+  @override
   bool operator ==(var other) {
     if (identical(this, other)) return true;
     if (other is! FlatTypeMask) return false;
@@ -600,10 +634,12 @@
     return (flags == otherMask.flags) && (base == otherMask.base);
   }
 
+  @override
   int get hashCode {
     return (base == null ? 0 : base.hashCode) + 31 * flags.hashCode;
   }
 
+  @override
   String toString() {
     if (isEmptyOrNull) return isNullable ? '[null]' : '[empty]';
     StringBuffer buffer = new StringBuffer();
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart
index 6021460..39f850c 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart
@@ -11,68 +11,93 @@
 
   ForwardingTypeMask();
 
+  @override
   bool get isEmptyOrNull => forwardTo.isEmptyOrNull;
+  @override
   bool get isEmpty => forwardTo.isEmpty;
+  @override
   bool get isNullable => forwardTo.isNullable;
+  @override
   bool get isNull => forwardTo.isNull;
+  @override
   bool get isExact => forwardTo.isExact;
 
+  @override
   bool get isUnion => false;
+  @override
   bool get isContainer => false;
+  @override
   bool get isSet => false;
+  @override
   bool get isMap => false;
+  @override
   bool get isDictionary => false;
+  @override
   bool get isValue => false;
+  @override
   bool get isForwarding => true;
 
+  @override
   bool isInMask(TypeMask other, JClosedWorld closedWorld) {
     return forwardTo.isInMask(other, closedWorld);
   }
 
+  @override
   bool containsMask(TypeMask other, JClosedWorld closedWorld) {
     return forwardTo.containsMask(other, closedWorld);
   }
 
+  @override
   bool containsOnlyInt(JClosedWorld closedWorld) {
     return forwardTo.containsOnlyInt(closedWorld);
   }
 
+  @override
   bool containsOnlyDouble(JClosedWorld closedWorld) {
     return forwardTo.containsOnlyDouble(closedWorld);
   }
 
+  @override
   bool containsOnlyNum(JClosedWorld closedWorld) {
     return forwardTo.containsOnlyNum(closedWorld);
   }
 
+  @override
   bool containsOnlyBool(JClosedWorld closedWorld) {
     return forwardTo.containsOnlyBool(closedWorld);
   }
 
+  @override
   bool containsOnlyString(JClosedWorld closedWorld) {
     return forwardTo.containsOnlyString(closedWorld);
   }
 
+  @override
   bool containsOnly(ClassEntity cls) {
     return forwardTo.containsOnly(cls);
   }
 
+  @override
   bool satisfies(ClassEntity cls, JClosedWorld closedWorld) {
     return forwardTo.satisfies(cls, closedWorld);
   }
 
+  @override
   bool contains(ClassEntity cls, JClosedWorld closedWorld) {
     return forwardTo.contains(cls, closedWorld);
   }
 
+  @override
   bool containsAll(JClosedWorld closedWorld) {
     return forwardTo.containsAll(closedWorld);
   }
 
+  @override
   ClassEntity singleClass(JClosedWorld closedWorld) {
     return forwardTo.singleClass(closedWorld);
   }
 
+  @override
   TypeMask union(other, JClosedWorld closedWorld) {
     if (this == other) {
       return this;
@@ -84,23 +109,28 @@
     return forwardTo.union(other, closedWorld);
   }
 
+  @override
   bool isDisjoint(TypeMask other, JClosedWorld closedWorld) {
     return forwardTo.isDisjoint(other, closedWorld);
   }
 
+  @override
   TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
     return forwardTo.intersection(other, closedWorld);
   }
 
+  @override
   bool needsNoSuchMethodHandling(
       Selector selector, covariant JClosedWorld closedWorld) {
     return forwardTo.needsNoSuchMethodHandling(selector, closedWorld);
   }
 
+  @override
   bool canHit(MemberEntity element, Name name, JClosedWorld closedWorld) {
     return forwardTo.canHit(element, name, closedWorld);
   }
 
+  @override
   MemberEntity locateSingleMember(Selector selector, JClosedWorld closedWorld) {
     return forwardTo.locateSingleMember(selector, closedWorld);
   }
@@ -114,10 +144,12 @@
     }
   }
 
+  @override
   bool operator ==(other) {
     return equalsDisregardNull(other) && isNullable == other.isNullable;
   }
 
+  @override
   int get hashCode => throw "Subclass should implement hashCode getter";
 }
 
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
index 2486256..7ba33af 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
@@ -12,12 +12,15 @@
   /// debugging data stream.
   static const String tag = 'map-type-mask';
 
+  @override
   final TypeMask forwardTo;
 
   // The [Node] where this type mask was created.
+  @override
   final ir.TreeNode allocationNode;
 
   // The [MemberEntity] where this type mask was created.
+  @override
   final MemberEntity allocationElement;
 
   // The value type of this map.
@@ -44,6 +47,7 @@
   }
 
   /// Serializes this [MapTypeMask] to [sink].
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(TypeMaskKind.map);
     sink.begin(tag);
@@ -55,6 +59,7 @@
     sink.end(tag);
   }
 
+  @override
   TypeMask nullable() {
     return isNullable
         ? this
@@ -62,6 +67,7 @@
             allocationElement, keyType, valueType);
   }
 
+  @override
   TypeMask nonNullable() {
     return isNullable
         ? new MapTypeMask(forwardTo.nonNullable(), allocationNode,
@@ -69,10 +75,14 @@
         : this;
   }
 
+  @override
   bool get isContainer => false;
+  @override
   bool get isMap => true;
+  @override
   bool get isExact => true;
 
+  @override
   bool equalsDisregardNull(other) {
     if (other is! MapTypeMask) return false;
     return super.equalsDisregardNull(other) &&
@@ -81,12 +91,14 @@
         valueType == other.valueType;
   }
 
+  @override
   TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
     TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
     if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
     return forwardIntersection.isNullable ? nullable() : nonNullable();
   }
 
+  @override
   TypeMask union(dynamic other, JClosedWorld closedWorld) {
     if (this == other) {
       return this;
@@ -128,13 +140,16 @@
     }
   }
 
+  @override
   bool operator ==(other) => super == other;
 
+  @override
   int get hashCode {
     return computeHashCode(
         allocationNode, isNullable, keyType, valueType, forwardTo);
   }
 
+  @override
   String toString() {
     return 'Map($forwardTo, key: $keyType, value: $valueType)';
   }
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/set_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/set_type_mask.dart
index fb0a7e2..966cbdf 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/set_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/set_type_mask.dart
@@ -12,12 +12,15 @@
   /// data stream.
   static const String tag = 'set-type-mask';
 
+  @override
   final TypeMask forwardTo;
 
   // The [Node] where this type mask was created.
+  @override
   final ir.TreeNode allocationNode;
 
   // The [Entity] where this type mask was created.
+  @override
   final MemberEntity allocationElement;
 
   // The element type of this set.
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart
index cb54ce7..cf6099d 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart
@@ -48,6 +48,7 @@
     return _masks.add(mask);
   }
 
+  @override
   String toString() {
     if (isAll) {
       return '<all>';
@@ -361,6 +362,7 @@
   ///
   /// Note: This may differ from semantic equality in the set containment sense.
   ///   Use [containsMask] and [isInMask] for that, instead.
+  @override
   bool operator ==(other);
 
   /// If this returns `true`, [other] is guaranteed to be a supertype of this
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart
index 98a5a87..1c3b7ec 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart
@@ -34,6 +34,7 @@
   }
 
   /// Serializes this [UnionTypeMask] to [sink].
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(TypeMaskKind.union);
     sink.begin(tag);
@@ -161,6 +162,7 @@
     return new TypeMask(bestElement, bestKind, isNullable, closedWorld);
   }
 
+  @override
   TypeMask union(dynamic other, JClosedWorld closedWorld) {
     other = TypeMask.nonForwardingMask(other);
     if (!other.isUnion && disjointMasks.contains(other)) return this;
@@ -175,6 +177,7 @@
     return new TypeMask.unionOf(newList, closedWorld);
   }
 
+  @override
   TypeMask intersection(dynamic other, JClosedWorld closedWorld) {
     other = TypeMask.nonForwardingMask(other);
     if (!other.isUnion && disjointMasks.contains(other)) return other;
@@ -197,6 +200,7 @@
     return new TypeMask.unionOf(intersections, closedWorld);
   }
 
+  @override
   bool isDisjoint(TypeMask other, JClosedWorld closedWorld) {
     for (var current in disjointMasks) {
       if (!current.isDisjoint(other, closedWorld)) return false;
@@ -204,6 +208,7 @@
     return true;
   }
 
+  @override
   TypeMask nullable() {
     if (isNullable) return this;
     List<FlatTypeMask> newList = new List<FlatTypeMask>.from(disjointMasks);
@@ -211,6 +216,7 @@
     return new UnionTypeMask._internal(newList);
   }
 
+  @override
   TypeMask nonNullable() {
     if (!isNullable) return this;
     Iterable<FlatTypeMask> newIterable = disjointMasks.map((e) {
@@ -220,17 +226,29 @@
     return new UnionTypeMask._internal(newIterable);
   }
 
+  @override
   bool get isEmptyOrNull => false;
+  @override
   bool get isEmpty => false;
+  @override
   bool get isNull => false;
+  @override
   bool get isNullable => disjointMasks.any((e) => e.isNullable);
+  @override
   bool get isExact => false;
+  @override
   bool get isUnion => true;
+  @override
   bool get isContainer => false;
+  @override
   bool get isSet => false;
+  @override
   bool get isMap => false;
+  @override
   bool get isDictionary => false;
+  @override
   bool get isForwarding => false;
+  @override
   bool get isValue => false;
 
   /// Checks whether [other] is contained in this union.
@@ -268,6 +286,7 @@
     return members.every((ClassEntity cls) => this.contains(cls, closedWorld));
   }
 
+  @override
   bool isInMask(TypeMask other, JClosedWorld closedWorld) {
     other = TypeMask.nonForwardingMask(other);
     if (isNullable && !other.isNullable) return false;
@@ -296,6 +315,7 @@
     return disjointMasks.every((mask) => mask.isInMask(other, closedWorld));
   }
 
+  @override
   bool containsMask(TypeMask other, JClosedWorld closedWorld) {
     other = TypeMask.nonForwardingMask(other);
     if (other.isNullable && !isNullable) return false;
@@ -311,55 +331,68 @@
     return contained;
   }
 
+  @override
   bool containsOnlyInt(JClosedWorld closedWorld) {
     return disjointMasks.every((mask) => mask.containsOnlyInt(closedWorld));
   }
 
+  @override
   bool containsOnlyDouble(JClosedWorld closedWorld) {
     return disjointMasks.every((mask) => mask.containsOnlyDouble(closedWorld));
   }
 
+  @override
   bool containsOnlyNum(JClosedWorld closedWorld) {
     return disjointMasks.every((mask) {
       return mask.containsOnlyNum(closedWorld);
     });
   }
 
+  @override
   bool containsOnlyBool(JClosedWorld closedWorld) {
     return disjointMasks.every((mask) => mask.containsOnlyBool(closedWorld));
   }
 
+  @override
   bool containsOnlyString(JClosedWorld closedWorld) {
     return disjointMasks.every((mask) => mask.containsOnlyString(closedWorld));
   }
 
+  @override
   bool containsOnly(ClassEntity element) {
     return disjointMasks.every((mask) => mask.containsOnly(element));
   }
 
+  @override
   bool satisfies(ClassEntity cls, JClosedWorld closedWorld) {
     return disjointMasks.every((mask) => mask.satisfies(cls, closedWorld));
   }
 
+  @override
   bool contains(ClassEntity cls, JClosedWorld closedWorld) {
     return disjointMasks.any((e) => e.contains(cls, closedWorld));
   }
 
+  @override
   bool containsAll(JClosedWorld closedWorld) {
     return disjointMasks.any((mask) => mask.containsAll(closedWorld));
   }
 
+  @override
   ClassEntity singleClass(JClosedWorld closedWorld) => null;
 
+  @override
   bool needsNoSuchMethodHandling(Selector selector, JClosedWorld closedWorld) {
     return disjointMasks
         .any((e) => e.needsNoSuchMethodHandling(selector, closedWorld));
   }
 
+  @override
   bool canHit(MemberEntity element, Name name, JClosedWorld closedWorld) {
     return disjointMasks.any((e) => e.canHit(element, name, closedWorld));
   }
 
+  @override
   MemberEntity locateSingleMember(Selector selector, JClosedWorld closedWorld) {
     MemberEntity candidate;
     for (FlatTypeMask mask in disjointMasks) {
@@ -375,6 +408,7 @@
     return candidate;
   }
 
+  @override
   String toString() {
     String masksString =
         (disjointMasks.map((TypeMask mask) => mask.toString()).toList()..sort())
@@ -382,6 +416,7 @@
     return 'Union($masksString)';
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
 
@@ -398,6 +433,7 @@
         containsAll();
   }
 
+  @override
   int get hashCode {
     int hashCode = isNullable ? 86 : 43;
     // The order of the masks in [disjointMasks] must not affect the
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/value_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/value_type_mask.dart
index 45c1300..1c965dc 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/value_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/value_type_mask.dart
@@ -9,6 +9,7 @@
   /// debugging data stream.
   static const String tag = 'value-type-mask';
 
+  @override
   final TypeMask forwardTo;
   final PrimitiveConstantValue value;
 
@@ -25,6 +26,7 @@
   }
 
   /// Serializes this [ValueTypeMask] to [sink].
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(TypeMaskKind.value);
     sink.begin(tag);
@@ -33,35 +35,43 @@
     sink.end(tag);
   }
 
+  @override
   TypeMask nullable() {
     return isNullable ? this : new ValueTypeMask(forwardTo.nullable(), value);
   }
 
+  @override
   TypeMask nonNullable() {
     return isNullable
         ? new ValueTypeMask(forwardTo.nonNullable(), value)
         : this;
   }
 
+  @override
   bool get isValue => true;
 
+  @override
   bool equalsDisregardNull(other) {
     if (other is! ValueTypeMask) return false;
     return super.equalsDisregardNull(other) && value == other.value;
   }
 
+  @override
   TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
     TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
     if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
     return forwardIntersection.isNullable ? nullable() : nonNullable();
   }
 
+  @override
   bool operator ==(other) => super == other;
 
+  @override
   int get hashCode {
     return computeHashCode(value, isNullable, forwardTo);
   }
 
+  @override
   String toString() {
     return 'Value($forwardTo, value: ${value.toDartText()})';
   }
diff --git a/pkg/compiler/lib/src/inferrer/types.dart b/pkg/compiler/lib/src/inferrer/types.dart
index 6a1017b..265d76d 100644
--- a/pkg/compiler/lib/src/inferrer/types.dart
+++ b/pkg/compiler/lib/src/inferrer/types.dart
@@ -147,6 +147,7 @@
 /// Global analysis that infers concrete types.
 class GlobalTypeInferenceTask extends CompilerTask {
   // TODO(sigmund): rename at the same time as our benchmarking tools.
+  @override
   final String name = 'Type inference';
 
   final Compiler compiler;
@@ -187,7 +188,9 @@
   /// in a debugging data stream.
   static const String tag = 'global-type-inference-results';
 
+  @override
   final JClosedWorld closedWorld;
+  @override
   final InferredData inferredData;
   final GlobalTypeInferenceMemberResult _deadFieldResult;
   final GlobalTypeInferenceMemberResult _deadMethodResult;
@@ -240,6 +243,7 @@
         allocatedLists);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeBool(false); // Is _not_ trivial.
     sink.begin(tag);
@@ -365,8 +369,10 @@
   bool isFixedArrayCheckedForGrowable(ir.Node ctorCall) =>
       checkedForGrowableLists.contains(ctorCall);
 
+  @override
   AbstractValue typeOfNewList(ir.Node node) => _allocatedLists[node];
 
+  @override
   AbstractValue typeOfListLiteral(ir.Node node) => _allocatedLists[node];
 }
 
@@ -377,9 +383,13 @@
   static const String tag = 'global-type-inference-member-result';
 
   final GlobalTypeInferenceElementData _data;
+  @override
   final AbstractValue returnType;
+  @override
   final AbstractValue type;
+  @override
   final bool throwsAlways;
+  @override
   final bool isCalledOnce;
 
   GlobalTypeInferenceMemberResultImpl(this._data, this.returnType, this.type,
@@ -403,6 +413,7 @@
         throwsAlways: throwsAlways, isCalledOnce: isCalledOnce);
   }
 
+  @override
   void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
     sink.begin(tag);
     sink.writeValueOrNull(_data, (GlobalTypeInferenceElementData data) {
@@ -415,19 +426,26 @@
     sink.end(tag);
   }
 
+  @override
   AbstractValue typeOfSend(ir.Node node) => _data?.typeOfSend(node);
+  @override
   AbstractValue typeOfGetter(ir.Node node) => _data?.typeOfGetter(node);
+  @override
   AbstractValue typeOfIterator(ir.Node node) => _data?.typeOfIterator(node);
+  @override
   AbstractValue typeOfIteratorMoveNext(ir.Node node) =>
       _data?.typeOfIteratorMoveNext(node);
+  @override
   AbstractValue typeOfIteratorCurrent(ir.Node node) =>
       _data?.typeOfIteratorCurrent(node);
 }
 
 class TrivialGlobalTypeInferenceResults implements GlobalTypeInferenceResults {
+  @override
   final JClosedWorld closedWorld;
   final TrivialGlobalTypeInferenceMemberResult _trivialMemberResult;
   final AbstractValue _trivialParameterResult;
+  @override
   final InferredData inferredData = new TrivialInferredData();
 
   TrivialGlobalTypeInferenceResults(this.closedWorld)
@@ -435,6 +453,7 @@
             closedWorld.abstractValueDomain.dynamicType),
         _trivialParameterResult = closedWorld.abstractValueDomain.dynamicType;
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeBool(true); // Is trivial.
   }
@@ -497,6 +516,7 @@
   @override
   bool get isCalledOnce => false;
 
+  @override
   void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
     throw new UnsupportedError(
         "TrivialGlobalTypeInferenceMemberResult.writeToDataSink");
@@ -539,6 +559,7 @@
   @override
   bool get isCalledOnce => false;
 
+  @override
   void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
     throw new UnsupportedError(
         "DeadFieldGlobalTypeInferenceResult.writeToDataSink");
@@ -581,6 +602,7 @@
   @override
   bool get isCalledOnce => false;
 
+  @override
   void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
     throw new UnsupportedError(
         "DeadFieldGlobalTypeInferenceResult.writeToDataSink");
diff --git a/pkg/compiler/lib/src/io/code_output.dart b/pkg/compiler/lib/src/io/code_output.dart
index 9ccc4b3..d7342ef 100644
--- a/pkg/compiler/lib/src/io/code_output.dart
+++ b/pkg/compiler/lib/src/io/code_output.dart
@@ -50,9 +50,11 @@
 }
 
 class _SourceLocationsImpl implements SourceLocations {
+  @override
   final String name;
   final AbstractCodeOutput codeOutput;
   Map<int, List<SourceLocation>> markers = <int, List<SourceLocation>>{};
+  @override
   Map<int, List<FrameEntry>> frameMarkers = <int, List<FrameEntry>>{};
 
   _SourceLocationsImpl(this.name, this.codeOutput);
@@ -143,6 +145,7 @@
 abstract class AbstractCodeOutput extends CodeOutput {
   Map<String, _SourceLocationsImpl> sourceLocationsMap =
       <String, _SourceLocationsImpl>{};
+  @override
   bool isClosed = false;
 
   void _addInternal(String text);
@@ -199,10 +202,12 @@
   @override
   int get length => buffer.length;
 
+  @override
   String getText() {
     return buffer.toString();
   }
 
+  @override
   String toString() {
     throw "Don't use CodeBuffer.toString() since it drops sourcemap data.";
   }
@@ -210,6 +215,7 @@
 
 /// [CodeOutput] using a [CompilationOutput] as backend.
 class StreamCodeOutput extends AbstractCodeOutput {
+  @override
   int length = 0;
   final OutputSink output;
   final List<CodeOutputListener> _listeners;
@@ -225,6 +231,7 @@
     }
   }
 
+  @override
   void close() {
     output.close();
     super.close();
diff --git a/pkg/compiler/lib/src/io/kernel_source_information.dart b/pkg/compiler/lib/src/io/kernel_source_information.dart
index 3e63370..520fbb40 100644
--- a/pkg/compiler/lib/src/io/kernel_source_information.dart
+++ b/pkg/compiler/lib/src/io/kernel_source_information.dart
@@ -109,6 +109,8 @@
       location = node.location;
       offset = node.fileOffset;
     }
+    assert(
+        location != null, "No location found for $node (${node.runtimeType})");
     return new KernelSourceLocation(location, offset, name);
   }
 
@@ -483,8 +485,11 @@
 }
 
 class KernelSourceLocation extends AbstractSourceLocation {
+  @override
   final int offset;
+  @override
   final String sourceName;
+  @override
   final Uri sourceUri;
 
   KernelSourceLocation(ir.Location location, this.offset, this.sourceName)
diff --git a/pkg/compiler/lib/src/io/location_provider.dart b/pkg/compiler/lib/src/io/location_provider.dart
index a015bab..3455e31 100644
--- a/pkg/compiler/lib/src/io/location_provider.dart
+++ b/pkg/compiler/lib/src/io/location_provider.dart
@@ -49,6 +49,7 @@
     this.length = length;
   }
 
+  @override
   String toString() {
     return 'lineStarts=$lineStarts,length=$length';
   }
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index 0d3b387..732b841 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -23,6 +23,7 @@
   @override
   final SourceLocation innerPosition;
 
+  @override
   final List<FrameContext> inliningContext;
 
   PositionSourceInformation(
@@ -49,11 +50,13 @@
     return new SourceSpan(uri, offset, offset);
   }
 
+  @override
   int get hashCode {
     return 0x7FFFFFFF &
         (startPosition.hashCode * 17 + innerPosition.hashCode * 19);
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! PositionSourceInformation) return false;
@@ -78,6 +81,7 @@
     return sb.toString();
   }
 
+  @override
   String get shortText {
     if (startPosition != null) {
       return _computeText(startPosition.sourceUri.pathSegments.last);
@@ -86,6 +90,7 @@
     }
   }
 
+  @override
   String toString() {
     if (startPosition != null) {
       return _computeText('${startPosition.sourceUri}');
@@ -152,6 +157,7 @@
     }
   }
 
+  @override
   String toString() {
     return 'CodePosition(start=$startPosition,'
         'end=$endPosition,closing=$closingPosition)';
@@ -178,6 +184,7 @@
     _codePositionMap[node] = codePosition;
   }
 
+  @override
   CodePosition operator [](js.Node node) => _codePositionMap[node];
 }
 
@@ -295,6 +302,7 @@
     }
   }
 
+  @override
   void process(js.Node node, BufferedCodeOutput code) {
     new JavaScriptTracer(codePositionMap, reader, traceListeners).apply(node);
     inliningListener?.finish();
@@ -379,6 +387,7 @@
 class InliningTraceListener extends TraceListener
     with NodeToSourceInformationMixin {
   final SourceMapper sourceMapper;
+  @override
   final SourceInformationReader reader;
   final Map<int, List<FrameContext>> _frames = {};
 
@@ -459,6 +468,7 @@
 class PositionTraceListener extends TraceListener
     with NodeToSourceInformationMixin {
   final SourceMapper sourceMapper;
+  @override
   final SourceInformationReader reader;
 
   PositionTraceListener(this.sourceMapper, this.reader);
@@ -752,6 +762,7 @@
 
   int get value => subexpressionOffset;
 
+  @override
   String toString() {
     return 'Offset[statementOffset=$statementOffset,'
         'leftToRightOffset=$leftToRightOffset,'
@@ -1369,12 +1380,14 @@
     return sb.toString();
   }
 
+  @override
   String toString() => getCoverageReport();
 }
 
 /// [TraceListener] that registers [onStep] callbacks with [coverage].
 class CoverageListener extends TraceListener with NodeToSourceInformationMixin {
   final Coverage coverage;
+  @override
   final SourceInformationReader reader;
 
   CoverageListener(this.coverage, this.reader);
diff --git a/pkg/compiler/lib/src/io/source_file.dart b/pkg/compiler/lib/src/io/source_file.dart
index ff227ae..ffdb8d0 100644
--- a/pkg/compiler/lib/src/io/source_file.dart
+++ b/pkg/compiler/lib/src/io/source_file.dart
@@ -17,8 +17,10 @@
 /// a UTF-8 encoded [List<int>] of bytes.
 abstract class SourceFile<T> implements Input<T>, LocationProvider {
   /// The absolute URI of the source file.
+  @override
   Uri get uri;
 
+  @override
   InputKind get inputKind => InputKind.UTF8;
 
   kernel.Source cachedKernelSource;
@@ -83,6 +85,7 @@
     return starts;
   }
 
+  @override
   kernel.Location getLocation(int offset) {
     return kernelSource.getLocation(null, offset);
   }
@@ -172,6 +175,7 @@
 }
 
 class Utf8BytesSourceFile extends SourceFile<List<int>> {
+  @override
   final Uri uri;
 
   /// The UTF-8 encoded content of the source file.
@@ -184,22 +188,27 @@
   Utf8BytesSourceFile(this.uri, List<int> content)
       : this.zeroTerminatedContent = _zeroTerminateIfNecessary(content);
 
+  @override
   List<int> get data => zeroTerminatedContent;
 
+  @override
   String slowText() {
     // Don't convert the trailing zero byte.
     return utf8.decoder
         .convert(zeroTerminatedContent, 0, zeroTerminatedContent.length - 1);
   }
 
+  @override
   List<int> slowUtf8ZeroTerminatedBytes() => zeroTerminatedContent;
 
+  @override
   String slowSubstring(int start, int end) {
     // TODO(lry): to make this faster, the scanner could record the UTF-8 slack
     // for all positions of the source text. We could use [:content.sublist:].
     return slowText().substring(start, end);
   }
 
+  @override
   int get length {
     if (lengthCache == -1) {
       // During scanning the length is not yet assigned, so we use a slow path.
@@ -208,17 +217,20 @@
     return lengthCache;
   }
 
+  @override
   set length(int v) => lengthCache = v;
   int lengthCache = -1;
 }
 
 class CachingUtf8BytesSourceFile extends Utf8BytesSourceFile {
   String cachedText;
+  @override
   final String filename;
 
   CachingUtf8BytesSourceFile(Uri uri, this.filename, List<int> content)
       : super(uri, content);
 
+  @override
   String slowText() {
     if (cachedText == null) {
       cachedText = super.slowText();
@@ -228,7 +240,9 @@
 }
 
 class StringSourceFile extends SourceFile<List<int>> {
+  @override
   final Uri uri;
+  @override
   final String filename;
   final String text;
 
@@ -240,26 +254,35 @@
   StringSourceFile.fromName(String filename, String text)
       : this(new Uri(path: filename), filename, text);
 
+  @override
   List<int> get data => utf8.encode(text);
 
+  @override
   int get length => text.length;
+  @override
   set length(int v) {}
 
+  @override
   String slowText() => text;
 
+  @override
   List<int> slowUtf8ZeroTerminatedBytes() {
     return _zeroTerminateIfNecessary(utf8.encode(text));
   }
 
+  @override
   String slowSubstring(int start, int end) => text.substring(start, end);
 }
 
 /// Binary input data.
 class Binary implements Input<List<int>> {
+  @override
   final Uri uri;
+  @override
   final List<int> data;
 
   Binary(this.uri, this.data);
 
+  @override
   InputKind get inputKind => InputKind.binary;
 }
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart
index 756340b..7709884 100644
--- a/pkg/compiler/lib/src/io/source_information.dart
+++ b/pkg/compiler/lib/src/io/source_information.dart
@@ -53,6 +53,7 @@
 
   FrameContext(this.callInformation, this.inlinedMethodName);
 
+  @override
   String toString() => "(FrameContext: $callInformation, $inlinedMethodName)";
 }
 
@@ -225,12 +226,14 @@
   /// `true` if the offset within the length of the source file.
   bool get isValid;
 
+  @override
   int get hashCode {
     return sourceUri.hashCode * 17 +
         offset.hashCode * 19 +
         sourceName.hashCode * 23;
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! SourceLocation) return false;
@@ -241,6 +244,7 @@
 
   String get shortText => '${sourceUri?.pathSegments?.last}:[$line,$column]';
 
+  @override
   String toString() => '${sourceUri}:[${line},${column}]';
 }
 
@@ -264,37 +268,49 @@
       : this.fromLocation(location._location);
 
   /// The absolute URI of the source file of this source location.
+  @override
   Uri get sourceUri => _sourceFile.uri;
 
   /// The character offset of the this source location into the source file.
+  @override
   int get offset;
 
   /// The 1-based line number of the [offset].
+  @override
   int get line => (_location ??= _sourceFile.getLocation(offset)).line;
 
   /// The 1-based column number of the [offset] with its line.
+  @override
   int get column => (_location ??= _sourceFile.getLocation(offset)).column;
 
   /// The name associated with this source location, if any.
+  @override
   String get sourceName;
 
   /// `true` if the offset within the length of the source file.
+  @override
   bool get isValid => offset < _sourceFile.length;
 
+  @override
   String get shortText => '${sourceUri.pathSegments.last}:[$line,$column]';
 
+  @override
   String toString() => '${sourceUri}:[$line,$column]';
 }
 
 class OffsetSourceLocation extends AbstractSourceLocation {
+  @override
   final int offset;
+  @override
   final String sourceName;
 
   OffsetSourceLocation(SourceFile sourceFile, this.offset, this.sourceName)
       : super(sourceFile);
 
+  @override
   String get shortText => '${super.shortText}:$sourceName';
 
+  @override
   String toString() => '${super.toString()}:$sourceName';
 }
 
@@ -365,6 +381,7 @@
 
   String get shortName => '<no-location>';
 
+  @override
   String toString() => '<no-location>';
 }
 
diff --git a/pkg/compiler/lib/src/ir/annotations.dart b/pkg/compiler/lib/src/ir/annotations.dart
index 485362e..1cd8bcf 100644
--- a/pkg/compiler/lib/src/ir/annotations.dart
+++ b/pkg/compiler/lib/src/ir/annotations.dart
@@ -7,33 +7,105 @@
 
 class IrAnnotationData {
   Map<ir.Class, String> _nativeClassNames = {};
+  Set<ir.Member> _nativeMembers = {};
+  Map<ir.Member, String> _nativeMemberNames = {};
+  Map<ir.Member, List<String>> _createsAnnotations = {};
+  Map<ir.Member, List<String>> _returnsAnnotations = {};
 
   Map<ir.Library, String> _jsInteropLibraryNames = {};
   Map<ir.Class, String> _jsInteropClassNames = {};
   Set<ir.Class> _anonymousJsInteropClasses = {};
   Map<ir.Member, String> _jsInteropMemberNames = {};
 
+  Map<ir.Member, List<PragmaAnnotationData>> _memberPragmaAnnotations = {};
+
+  // Returns the text from the `@Native(<text>)` annotation of [node], if any.
   String getNativeClassName(ir.Class node) => _nativeClassNames[node];
 
+  // Returns `true` if [node] has a native body, as in `method() native;`.
+  bool hasNativeBody(ir.Member node) => _nativeMembers.contains(node);
+
+  // Returns the text from the `@JSName(<text>)` annotation of [node], if any.
+  String getNativeMemberName(ir.Member node) => _nativeMemberNames[node];
+
+  // Returns a list of the text from the `@Creates(<text>)` annotation of
+  // [node].
+  List<String> getCreatesAnnotations(ir.Member node) =>
+      _createsAnnotations[node] ?? const [];
+
+  // Returns a list of the text from the `@Returns(<text>)` annotation of
+  // [node].
+  List<String> getReturnsAnnotations(ir.Member node) =>
+      _returnsAnnotations[node] ?? const [];
+
+  // Returns the text from the `@JS(<text>)` annotation of [node], if any.
   String getJsInteropLibraryName(ir.Library node) =>
       _jsInteropLibraryNames[node];
+
+  // Returns the text from the `@JS(<text>)` annotation of [node], if any.
   String getJsInteropClassName(ir.Class node) => _jsInteropClassNames[node];
+
+  // Returns `true` if [node] is annotated with `@anonymous`.
   bool isAnonymousJsInteropClass(ir.Class node) =>
       _anonymousJsInteropClasses.contains(node);
+
+  // Returns the text from the `@JS(<text>)` annotation of [node], if any.
   String getJsInteropMemberName(ir.Member node) => _jsInteropMemberNames[node];
+
+  // Returns a list of the `@pragma('dart2js:<suffix>')` annotations on [node].
+  List<PragmaAnnotationData> getMemberPragmaAnnotationData(ir.Member node) =>
+      _memberPragmaAnnotations[node] ?? const [];
 }
 
 IrAnnotationData processAnnotations(ir.Component component) {
   IrAnnotationData data = new IrAnnotationData();
 
   void processMember(ir.Member member) {
+    List<PragmaAnnotationData> pragmaAnnotations;
+    List<String> createsAnnotations;
+    List<String> returnsAnnotations;
     for (ir.Expression annotation in member.annotations) {
       if (annotation is ir.ConstantExpression) {
         ir.Constant constant = annotation.constant;
+
         String jsName = _getJsInteropName(constant);
         if (jsName != null) {
           data._jsInteropMemberNames[member] = jsName;
         }
+
+        bool isNativeMember = _isNativeMember(constant);
+        if (isNativeMember) {
+          data._nativeMembers.add(member);
+        }
+
+        String nativeName = _getNativeMemberName(constant);
+        if (nativeName != null) {
+          data._nativeMemberNames[member] = nativeName;
+        }
+
+        String creates = _getCreatesAnnotation(constant);
+        if (creates != null) {
+          if (createsAnnotations == null) {
+            data._createsAnnotations[member] = createsAnnotations = [];
+          }
+          createsAnnotations.add(creates);
+        }
+
+        String returns = _getReturnsAnnotation(constant);
+        if (returns != null) {
+          if (returnsAnnotations == null) {
+            data._returnsAnnotations[member] = returnsAnnotations = [];
+          }
+          returnsAnnotations.add(returns);
+        }
+
+        PragmaAnnotationData pragmaAnnotation = _getPragmaAnnotation(constant);
+        if (pragmaAnnotation != null) {
+          if (pragmaAnnotations == null) {
+            data._memberPragmaAnnotations[member] = pragmaAnnotations = [];
+          }
+          pragmaAnnotations.add(pragmaAnnotation);
+        }
       }
     }
   }
@@ -83,6 +155,8 @@
 
 String _getNativeClassName(ir.Constant constant) {
   if (constant is ir.InstanceConstant) {
+    // TODO(johnniwinther): Add an IrCommonElements for these queries; i.e.
+    // `commonElements.isNativeAnnotationClass(constant.classNode)`.
     if (constant.classNode.name == 'Native' &&
         constant.classNode.enclosingLibrary.importUri == Uris.dart__js_helper) {
       if (constant.fieldValues.length == 1) {
@@ -100,31 +174,131 @@
   return null;
 }
 
+bool _isNativeMember(ir.Constant constant) {
+  return constant is ir.InstanceConstant &&
+      constant.classNode.name == 'ExternalName' &&
+      constant.classNode.enclosingLibrary.importUri == Uris.dart__internal;
+}
+
+String _getNativeMemberName(ir.Constant constant) {
+  if (constant is ir.InstanceConstant &&
+      constant.classNode.name == 'JSName' &&
+      constant.classNode.enclosingLibrary.importUri == Uris.dart__js_helper) {
+    assert(constant.fieldValues.length == 1);
+    ir.Constant fieldValue = constant.fieldValues.values.single;
+    if (fieldValue is ir.StringConstant) {
+      return fieldValue.value;
+    }
+  }
+  return null;
+}
+
+String _getCreatesAnnotation(ir.Constant constant) {
+  if (constant is ir.InstanceConstant &&
+      constant.classNode.name == 'Creates' &&
+      constant.classNode.enclosingLibrary.importUri == Uris.dart__js_helper) {
+    assert(constant.fieldValues.length == 1);
+    ir.Constant fieldValue = constant.fieldValues.values.single;
+    if (fieldValue is ir.StringConstant) {
+      return fieldValue.value;
+    }
+  }
+  return null;
+}
+
+String _getReturnsAnnotation(ir.Constant constant) {
+  if (constant is ir.InstanceConstant &&
+      constant.classNode.name == 'Returns' &&
+      constant.classNode.enclosingLibrary.importUri == Uris.dart__js_helper) {
+    assert(constant.fieldValues.length == 1);
+    ir.Constant fieldValue = constant.fieldValues.values.single;
+    if (fieldValue is ir.StringConstant) {
+      return fieldValue.value;
+    }
+  }
+  return null;
+}
+
 String _getJsInteropName(ir.Constant constant) {
-  if (constant is ir.InstanceConstant) {
-    if (constant.classNode.name == 'JS' &&
-        constant.classNode.enclosingLibrary.importUri == Uris.package_js) {
-      if (constant.fieldValues.length == 1) {
-        ir.Constant fieldValue = constant.fieldValues.values.single;
-        String name;
-        if (fieldValue is ir.NullConstant) {
-          name = '';
-        } else if (fieldValue is ir.StringConstant) {
-          name = fieldValue.value;
-        }
-        if (name != null) {
-          return name;
-        }
-      }
+  if (constant is ir.InstanceConstant &&
+      constant.classNode.name == 'JS' &&
+      constant.classNode.enclosingLibrary.importUri == Uris.package_js) {
+    assert(constant.fieldValues.length == 1);
+    ir.Constant fieldValue = constant.fieldValues.values.single;
+    if (fieldValue is ir.NullConstant) {
+      return '';
+    } else if (fieldValue is ir.StringConstant) {
+      return fieldValue.value;
     }
   }
   return null;
 }
 
 bool _isAnonymousJsInterop(ir.Constant constant) {
-  if (constant is ir.InstanceConstant) {
-    return constant.classNode.name == '_Anonymous' &&
-        constant.classNode.enclosingLibrary.importUri == Uris.package_js;
+  return constant is ir.InstanceConstant &&
+      constant.classNode.name == '_Anonymous' &&
+      constant.classNode.enclosingLibrary.importUri == Uris.package_js;
+}
+
+class PragmaAnnotationData {
+  // TODO(johnniwinther): Support non 'dart2js:' pragma names if necessary.
+  final String suffix;
+
+  // TODO(johnniwinther): Support options objects when necessary.
+  final bool hasOptions;
+
+  const PragmaAnnotationData(this.suffix, {this.hasOptions: false});
+
+  String get name => 'dart2js:$suffix';
+
+  @override
+  String toString() => 'PragmaAnnotationData($name)';
+}
+
+PragmaAnnotationData _getPragmaAnnotation(ir.Constant constant) {
+  if (constant is! ir.InstanceConstant) return null;
+  ir.InstanceConstant value = constant;
+  ir.Class cls = value.classNode;
+  Uri uri = cls.enclosingLibrary.importUri;
+  if (uri == Uris.package_meta_dart2js) {
+    if (cls.name == '_NoInline') {
+      return const PragmaAnnotationData('noInline');
+    } else if (cls.name == '_TryInline') {
+      return const PragmaAnnotationData('tryInline');
+    }
+  } else if (uri == Uris.dart_core && cls.name == 'pragma') {
+    ir.Constant nameValue;
+    ir.Constant optionsValue;
+    value.fieldValues.forEach((ir.Reference reference, ir.Constant fieldValue) {
+      ir.Field field = reference.asField;
+      if (field.name.name == 'name') {
+        nameValue = fieldValue;
+      } else if (field.name.name == 'options') {
+        optionsValue = fieldValue;
+      }
+    });
+    if (nameValue is! ir.StringConstant) return null;
+    ir.StringConstant stringValue = nameValue;
+    String name = stringValue.value;
+    String prefix = 'dart2js:';
+    if (!name.startsWith(prefix)) return null;
+    String suffix = name.substring(prefix.length);
+    return new PragmaAnnotationData(suffix,
+        hasOptions: optionsValue is! ir.NullConstant);
   }
-  return false;
+  return null;
+}
+
+List<PragmaAnnotationData> computePragmaAnnotationDataFromIr(ir.Member member) {
+  List<PragmaAnnotationData> annotations = [];
+  for (ir.Expression metadata in member.annotations) {
+    if (metadata is! ir.ConstantExpression) continue;
+    ir.ConstantExpression constantExpression = metadata;
+    ir.Constant constant = constantExpression.constant;
+    PragmaAnnotationData data = _getPragmaAnnotation(constant);
+    if (data != null) {
+      annotations.add(data);
+    }
+  }
+  return annotations;
 }
diff --git a/pkg/compiler/lib/src/ir/cached_static_type.dart b/pkg/compiler/lib/src/ir/cached_static_type.dart
index 5daea39..6067b5e 100644
--- a/pkg/compiler/lib/src/ir/cached_static_type.dart
+++ b/pkg/compiler/lib/src/ir/cached_static_type.dart
@@ -14,6 +14,7 @@
 /// and a precomputed cache for complex expression type.
 class CachedStaticType extends StaticTypeBase implements StaticTypeProvider {
   final Map<ir.Expression, ir.DartType> _cache;
+  @override
   final ThisInterfaceType thisType;
 
   CachedStaticType(
diff --git a/pkg/compiler/lib/src/ir/closure.dart b/pkg/compiler/lib/src/ir/closure.dart
index 2bc573f..d237f3f 100644
--- a/pkg/compiler/lib/src/ir/closure.dart
+++ b/pkg/compiler/lib/src/ir/closure.dart
@@ -17,6 +17,7 @@
   Map<ir.TreeNode, KernelScopeInfo> closuresToGenerate =
       <ir.TreeNode, KernelScopeInfo>{};
 
+  @override
   String toString() {
     return '$scopeInfo\n$capturedScopesMap\n$closuresToGenerate';
   }
@@ -76,6 +77,7 @@
       this.thisUsedAsFreeVariableIfNeedsRti,
       this.hasThisLocal);
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('KernelScopeInfo(this=$hasThisLocal,');
@@ -319,6 +321,7 @@
   static const VariableUse fieldType =
       const VariableUse._simple(VariableUseKind.fieldType);
 
+  @override
   int get hashCode =>
       kind.hashCode * 11 +
       member.hashCode * 13 +
@@ -326,6 +329,7 @@
       invocation.hashCode * 19 +
       instantiation.hashCode * 23;
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! VariableUse) return false;
@@ -336,6 +340,7 @@
         instantiation == other.instantiation;
   }
 
+  @override
   String toString() => 'VariableUse(kind=$kind,member=$member,'
       'localFunction=$localFunction,invocation=$invocation,'
       'instantiation=$instantiation)';
@@ -398,21 +403,26 @@
   TypeVariableTypeWithContext.internal(
       this.type, this.context, this.kind, this.typeDeclaration);
 
+  @override
   accept(ir.Visitor v) {
     throw new UnsupportedError('TypeVariableTypeWithContext.accept');
   }
 
+  @override
   visitChildren(ir.Visitor v) {
     throw new UnsupportedError('TypeVariableTypeWithContext.visitChildren');
   }
 
+  @override
   int get hashCode => type.hashCode;
 
+  @override
   bool operator ==(other) {
     if (other is! TypeVariableTypeWithContext) return false;
     return type == other.type && context == other.context;
   }
 
+  @override
   String toString() =>
       'TypeVariableTypeWithContext(type=$type,context=$context,'
       'kind=$kind,typeDeclaration=$typeDeclaration)';
diff --git a/pkg/compiler/lib/src/ir/debug.dart b/pkg/compiler/lib/src/ir/debug.dart
index a61a77a..27fad8e 100644
--- a/pkg/compiler/lib/src/ir/debug.dart
+++ b/pkg/compiler/lib/src/ir/debug.dart
@@ -12,6 +12,7 @@
 import '../util/util.dart' show Indentation, Tagging;
 
 class DebugPrinter extends Visitor with Indentation, Tagging<Node> {
+  @override
   StringBuffer sb = new StringBuffer();
 
   void visitNodeWithChildren(Node node, String type, [Map params]) {
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
index dd5802a..c548eae 100644
--- a/pkg/compiler/lib/src/ir/impact.dart
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -188,6 +188,7 @@
 
 abstract class ImpactBuilderBase extends StaticTypeVisitor
     implements ImpactRegistry {
+  @override
   final VariableScopeModel variableScopeModel;
 
   ImpactBuilderBase(ir.TypeEnvironment typeEnvironment,
@@ -406,6 +407,7 @@
     registerLoadLibrary();
   }
 
+  @override
   void handleRedirectingInitializer(
       ir.RedirectingInitializer node, ArgumentTypes argumentTypes) {
     registerRedirectingInitializer(
@@ -643,6 +645,7 @@
     return super.visitSwitchStatement(node);
   }
 
+  @override
   void handleRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind,
       ir.DartType receiverType, ir.DartType argumentType) {
     registerRuntimeTypeUse(node, kind, receiverType, argumentType);
@@ -656,16 +659,36 @@
 
 /// Visitor that builds an [ImpactData] object for the world impact.
 class ImpactBuilder extends ImpactBuilderBase with ImpactRegistryMixin {
+  @override
   final bool useAsserts;
 
+  @override
   final inferEffectivelyFinalVariableTypes;
 
   ImpactBuilder(ir.TypeEnvironment typeEnvironment,
       ir.ClassHierarchy classHierarchy, VariableScopeModel variableScopeModel,
       {this.useAsserts: false, this.inferEffectivelyFinalVariableTypes: true})
       : super(typeEnvironment, classHierarchy, variableScopeModel);
+
+  ImpactBuilderData computeImpact(ir.Member node) {
+    if (retainDataForTesting) {
+      typeMapsForTesting = {};
+    }
+    node.accept(this);
+    return new ImpactBuilderData(
+        impactData, typeMapsForTesting, cachedStaticTypes);
+  }
 }
 
 /// Return the named arguments names as a list of strings.
 List<String> _getNamedArguments(ir.Arguments arguments) =>
     arguments.named.map((n) => n.name).toList();
+
+class ImpactBuilderData {
+  final ImpactData impactData;
+  final Map<ir.Expression, TypeMap> typeMapsForTesting;
+  final Map<ir.Expression, ir.DartType> cachedStaticTypes;
+
+  ImpactBuilderData(
+      this.impactData, this.typeMapsForTesting, this.cachedStaticTypes);
+}
diff --git a/pkg/compiler/lib/src/ir/modular.dart b/pkg/compiler/lib/src/ir/modular.dart
new file mode 100644
index 0000000..9d7ea73
--- /dev/null
+++ b/pkg/compiler/lib/src/ir/modular.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2019, 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 'package:kernel/ast.dart' as ir;
+import 'package:kernel/class_hierarchy.dart' as ir;
+import 'package:kernel/core_types.dart' as ir;
+import 'package:kernel/type_algebra.dart' as ir;
+import 'package:kernel/type_environment.dart' as ir;
+
+import '../js_backend/annotations.dart';
+import '../util/enumset.dart';
+import 'annotations.dart';
+import 'impact.dart';
+import 'scope.dart';
+
+class ModularMemberData {
+  final ScopeModel scopeModel;
+  final ImpactBuilderData impactBuilderData;
+
+  ModularMemberData(this.scopeModel, this.impactBuilderData);
+}
+
+abstract class ModularStrategy {
+  List<PragmaAnnotationData> getPragmaAnnotationData(ir.Member node);
+
+  // TODO(johnniwinther): Avoid the need for passing [pragmaAnnotations].
+  ModularMemberData getModularMemberData(
+      ir.Member node, EnumSet<PragmaAnnotation> pragmaAnnotations);
+}
diff --git a/pkg/compiler/lib/src/ir/runtime_type_analysis.dart b/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
index cde8217..d7e1d75 100644
--- a/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
+++ b/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
@@ -63,6 +63,7 @@
     throw new UnsupportedError("Unexpected RuntimeTypeUseKind $kind.");
   }
 
+  @override
   String toString() {
     return "RuntimeTypeUseData(kind=$kind,"
         "receiverGet=$leftRuntimeTypeExpression,receiver=$receiver,"
diff --git a/pkg/compiler/lib/src/ir/scope.dart b/pkg/compiler/lib/src/ir/scope.dart
index a323f6f..1d2a300 100644
--- a/pkg/compiler/lib/src/ir/scope.dart
+++ b/pkg/compiler/lib/src/ir/scope.dart
@@ -11,45 +11,17 @@
   final VariableScopeModel variableScopeModel;
   final InitializerComplexity initializerComplexity;
 
-  ScopeModel(this.closureScopeModel, this.variableScopeModel,
-      this.initializerComplexity);
+  const ScopeModel(
+      {this.closureScopeModel,
+      this.variableScopeModel,
+      this.initializerComplexity})
+      : assert(initializerComplexity != null);
 
   /// Inspect members and mark if those members capture any state that needs to
   /// be marked as free variables.
-  static ScopeModel computeScopeModel(ir.Member node) {
-    if (node.isAbstract && !node.isExternal) return null;
-    if (node is ir.Field && !node.isInstanceMember) {
-      ir.Field field = node;
-      // Skip top-level/static fields without an initializer.
-      if (field.initializer == null) return null;
-    }
-
-    bool hasThisLocal = false;
-    if (node is ir.Constructor) {
-      hasThisLocal = true;
-    } else if (node is ir.Procedure && node.kind == ir.ProcedureKind.Factory) {
-      hasThisLocal = false;
-    } else if (node.isInstanceMember) {
-      hasThisLocal = true;
-    }
-    ClosureScopeModel closureScopeModel = new ClosureScopeModel();
-    ScopeModelBuilder builder =
-        new ScopeModelBuilder(closureScopeModel, hasThisLocal: hasThisLocal);
-    InitializerComplexity initializerComplexity =
-        const InitializerComplexity.lazy();
-    if (node is ir.Field) {
-      if (node is ir.Field && node.initializer != null) {
-        initializerComplexity = node.accept(builder);
-      } else {
-        assert(node.isInstanceMember);
-        closureScopeModel.scopeInfo = new KernelScopeInfo(true);
-      }
-    } else {
-      assert(node is ir.Procedure || node is ir.Constructor);
-      node.accept(builder);
-    }
-    return new ScopeModel(
-        closureScopeModel, builder.variableScopeModel, initializerComplexity);
+  factory ScopeModel.from(ir.Member node) {
+    ScopeModelBuilder builder = new ScopeModelBuilder();
+    return builder.computeModel(node);
   }
 }
 
@@ -100,6 +72,7 @@
 class VariableScopeImpl implements VariableScope {
   List<VariableScope> _subScopes;
   Set<ir.VariableDeclaration> _assignedVariables;
+  @override
   bool hasContinueSwitch = false;
 
   void addSubScope(VariableScope scope) {
@@ -112,6 +85,7 @@
     _assignedVariables.add(variable);
   }
 
+  @override
   Iterable<ir.VariableDeclaration> get assignedVariables sync* {
     if (_assignedVariables != null) {
       yield* _assignedVariables;
diff --git a/pkg/compiler/lib/src/ir/scope_visitor.dart b/pkg/compiler/lib/src/ir/scope_visitor.dart
index 07ae385..7fcac8a 100644
--- a/pkg/compiler/lib/src/ir/scope_visitor.dart
+++ b/pkg/compiler/lib/src/ir/scope_visitor.dart
@@ -13,7 +13,7 @@
 /// variable is being used at any point in the code.
 class ScopeModelBuilder extends ir.Visitor<InitializerComplexity>
     with VariableCollectorMixin {
-  ClosureScopeModel _model;
+  final ClosureScopeModel _model = new ClosureScopeModel();
 
   /// A map of each visited call node with the associated information about what
   /// variables are captured/used. Each ir.Node key corresponds to a scope that
@@ -61,7 +61,7 @@
   /// The current scope we are in.
   KernelScopeInfo _currentScopeInfo;
 
-  final bool _hasThisLocal;
+  bool _hasThisLocal;
 
   /// Keeps track of the number of boxes that we've created so that they each
   /// have unique names.
@@ -74,8 +74,40 @@
   /// type variable usage, such as type argument in method invocations.
   VariableUse _currentTypeUsage;
 
-  ScopeModelBuilder(this._model, {bool hasThisLocal})
-      : this._hasThisLocal = hasThisLocal;
+  ScopeModel computeModel(ir.Member node) {
+    if (node.isAbstract && !node.isExternal) {
+      return const ScopeModel(
+          initializerComplexity: const InitializerComplexity.lazy());
+    }
+
+    if (node is ir.Constructor) {
+      _hasThisLocal = true;
+    } else if (node is ir.Procedure && node.kind == ir.ProcedureKind.Factory) {
+      _hasThisLocal = false;
+    } else if (node.isInstanceMember) {
+      _hasThisLocal = true;
+    } else {
+      _hasThisLocal = false;
+    }
+
+    InitializerComplexity initializerComplexity =
+        const InitializerComplexity.lazy();
+    if (node is ir.Field) {
+      if (node.initializer != null) {
+        initializerComplexity = node.accept(this);
+      } else {
+        initializerComplexity = const InitializerComplexity.constant();
+        _model.scopeInfo = new KernelScopeInfo(_hasThisLocal);
+      }
+    } else {
+      assert(node is ir.Procedure || node is ir.Constructor);
+      node.accept(this);
+    }
+    return new ScopeModel(
+        closureScopeModel: _model,
+        variableScopeModel: variableScopeModel,
+        initializerComplexity: initializerComplexity);
+  }
 
   @override
   InitializerComplexity defaultNode(ir.Node node) =>
@@ -338,6 +370,7 @@
     return const InitializerComplexity.lazy();
   }
 
+  @override
   InitializerComplexity visitWhileStatement(ir.WhileStatement node) {
     enterNewScope(node, () {
       visitInVariableScope(node, () {
@@ -348,6 +381,7 @@
     return const InitializerComplexity.lazy();
   }
 
+  @override
   InitializerComplexity visitDoStatement(ir.DoStatement node) {
     enterNewScope(node, () {
       visitInVariableScope(node, () {
@@ -412,6 +446,7 @@
     return const InitializerComplexity.lazy();
   }
 
+  @override
   InitializerComplexity visitSuperMethodInvocation(
       ir.SuperMethodInvocation node) {
     if (_hasThisLocal) {
@@ -426,6 +461,7 @@
     return const InitializerComplexity.lazy();
   }
 
+  @override
   InitializerComplexity visitSuperPropertySet(ir.SuperPropertySet node) {
     if (_hasThisLocal) {
       _registerNeedsThis(VariableUse.explicit);
@@ -434,6 +470,7 @@
     return const InitializerComplexity.lazy();
   }
 
+  @override
   InitializerComplexity visitSuperPropertyGet(ir.SuperPropertyGet node) {
     if (_hasThisLocal) {
       _registerNeedsThis(VariableUse.explicit);
@@ -683,30 +720,40 @@
 
   @override
   InitializerComplexity visitListLiteral(ir.ListLiteral node) {
-    visitInContext(node.typeArgument, VariableUse.listLiteral);
-    visitNodes(node.expressions);
-    return node.isConst
-        ? const InitializerComplexity.constant()
-        : const InitializerComplexity.lazy();
+    InitializerComplexity complexity =
+        visitInContext(node.typeArgument, VariableUse.listLiteral);
+    complexity = complexity.combine(visitNodes(node.expressions));
+    if (node.isConst) {
+      return const InitializerComplexity.constant();
+    } else {
+      return complexity.makeEager();
+    }
   }
 
   @override
   InitializerComplexity visitSetLiteral(ir.SetLiteral node) {
-    visitInContext(node.typeArgument, VariableUse.setLiteral);
-    visitNodes(node.expressions);
-    return node.isConst
-        ? const InitializerComplexity.constant()
-        : const InitializerComplexity.lazy();
+    InitializerComplexity complexity =
+        visitInContext(node.typeArgument, VariableUse.setLiteral);
+    complexity = complexity.combine(visitNodes(node.expressions));
+    if (node.isConst) {
+      return const InitializerComplexity.constant();
+    } else {
+      return complexity.makeEager();
+    }
   }
 
   @override
   InitializerComplexity visitMapLiteral(ir.MapLiteral node) {
-    visitInContext(node.keyType, VariableUse.mapLiteral);
-    visitInContext(node.valueType, VariableUse.mapLiteral);
-    visitNodes(node.entries);
-    return node.isConst
-        ? const InitializerComplexity.constant()
-        : const InitializerComplexity.lazy();
+    InitializerComplexity complexity =
+        visitInContext(node.keyType, VariableUse.mapLiteral);
+    complexity = complexity
+        .combine(visitInContext(node.valueType, VariableUse.mapLiteral));
+    complexity = complexity.combine(visitNodes(node.entries));
+    if (node.isConst) {
+      return const InitializerComplexity.constant();
+    } else {
+      return complexity.makeEager();
+    }
   }
 
   @override
@@ -747,9 +794,16 @@
 
   @override
   InitializerComplexity visitStaticGet(ir.StaticGet node) {
-    return node.target.isConst
-        ? const InitializerComplexity.constant()
-        : const InitializerComplexity.lazy();
+    ir.Member target = node.target;
+    if (target is ir.Field) {
+      return target.isConst
+          ? const InitializerComplexity.constant()
+          : new InitializerComplexity.eager(fields: <ir.Field>{target});
+    } else if (target is ir.Procedure &&
+        target.kind == ir.ProcedureKind.Method) {
+      return const InitializerComplexity.constant();
+    }
+    return const InitializerComplexity.lazy();
   }
 
   @override
@@ -1065,43 +1119,90 @@
 
 class InitializerComplexity {
   final ComplexityLevel level;
+  final Set<ir.Field> fields;
 
   // TODO(johnniwinther): This should hold the constant literal from CFE when
   // provided.
-  const InitializerComplexity.constant() : level = ComplexityLevel.constant;
+  const InitializerComplexity.constant()
+      : level = ComplexityLevel.constant,
+        fields = null;
 
   // TODO(johnniwinther): Use this to collect data on the size of the
   //  initializer.
-  const InitializerComplexity.eager()
+  InitializerComplexity.eager({this.fields})
       : level = ComplexityLevel.potentiallyEager;
 
-  const InitializerComplexity.lazy() : level = ComplexityLevel.definitelyLazy;
+  const InitializerComplexity.lazy()
+      : level = ComplexityLevel.definitelyLazy,
+        fields = null;
 
   InitializerComplexity combine(InitializerComplexity other) {
-    if (level == other.level) {
-      // TODO(johnniwinther): Special case 'eager' when it contains data.
+    if (identical(this, other)) {
       return this;
-    } else if (level == ComplexityLevel.definitelyLazy ||
-        other.level == ComplexityLevel.definitelyLazy) {
+    } else if (isLazy || other.isLazy) {
       return const InitializerComplexity.lazy();
-    } else if (level == ComplexityLevel.potentiallyEager) {
+    } else if (isEager || other.isEager) {
+      if (fields != null && other.fields != null) {
+        fields.addAll(other.fields);
+        return this;
+      } else if (fields != null) {
+        return this;
+      } else {
+        return other;
+      }
+    } else if (isConstant && other.isConstant) {
+      // TODO(johnniwinther): This is case doesn't work if InitializerComplexity
+      // objects of constant complexity hold the constant literal.
+      return this;
+    } else if (isEager) {
+      assert(other.isConstant);
       return this;
     } else {
-      assert(other.level == ComplexityLevel.potentiallyEager);
+      assert(isConstant);
+      assert(other.isEager);
       return other;
     }
   }
 
+  InitializerComplexity makeEager() {
+    if (isLazy || isEager) {
+      return this;
+    } else {
+      return new InitializerComplexity.eager();
+    }
+  }
+
+  bool get isConstant => level == ComplexityLevel.constant;
+
+  bool get isEager => level == ComplexityLevel.potentiallyEager;
+
+  bool get isLazy => level == ComplexityLevel.definitelyLazy;
+
   /// Returns a short textual representation used for testing.
   String get shortText {
+    StringBuffer sb = new StringBuffer();
     switch (level) {
       case ComplexityLevel.constant:
-        return 'constant';
+        sb.write('constant');
+        break;
       case ComplexityLevel.potentiallyEager:
-        return 'eager';
+        sb.write('eager');
+        if (fields != null) {
+          sb.write('&fields=[');
+          List<String> names = fields.map((f) => f.name.name).toList()..sort();
+          sb.write(names.join(','));
+          sb.write(']');
+        }
+        break;
       case ComplexityLevel.definitelyLazy:
-        return 'lazy';
+        sb.write('lazy');
+        break;
+      default:
+        throw new UnsupportedError("Unexpected complexity level $level");
     }
-    throw new UnsupportedError("Unexpected complexity level $level");
+    return sb.toString();
   }
+
+  @override
+  String toString() => 'InitializerComplexity($shortText)';
 }
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index b8d423c..1300bd8 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -58,6 +58,7 @@
 
   VariableScopeModel get variableScopeModel;
 
+  @override
   ThisInterfaceType get thisType {
     assert(_thisType != null);
     return _thisType;
@@ -249,11 +250,35 @@
   ir.DartType visitPropertySet(ir.PropertySet node) {
     ir.DartType receiverType = visitNode(node.receiver);
     ir.DartType valueType = super.visitPropertySet(node);
-    if (node.interfaceTarget == null && receiverType is ir.InterfaceType) {
-      node.interfaceTarget = hierarchy
+    ir.Member interfaceTarget = node.interfaceTarget;
+    if (interfaceTarget == null && receiverType is ir.InterfaceType) {
+      interfaceTarget = hierarchy
           .getInterfaceMember(receiverType.classNode, node.name, setter: true);
+      if (interfaceTarget != null) {
+        ir.Class superclass = interfaceTarget.enclosingClass;
+        ir.Substitution receiverSubstitution =
+            ir.Substitution.fromInterfaceType(
+                getTypeAsInstanceOf(receiverType, superclass));
+        ir.DartType setterType =
+            receiverSubstitution.substituteType(interfaceTarget.setterType);
+        if (!typeEnvironment.isSubtypeOf(valueType, setterType)) {
+          // We need to insert an implicit cast to preserve the invariant that
+          // a property set with a known interface target is also statically
+          // checked.
+          ir.AsExpression implicitCast =
+              new ir.AsExpression(node.value, setterType)
+                ..isTypeError = true
+                ..parent = node;
+          node.value = implicitCast;
+          // Visit the newly created as expression; the original value has
+          // already been visited.
+          handleAsExpression(implicitCast, valueType);
+          valueType = setterType;
+        }
+        node.interfaceTarget = interfaceTarget;
+      }
     }
-    receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
+    receiverType = _narrowInstanceReceiver(interfaceTarget, receiverType);
     handlePropertySet(node, receiverType, valueType);
     return valueType;
   }
@@ -415,6 +440,106 @@
     return false;
   }
 
+  /// Update the interface target on [node].
+  ///
+  /// This inserts any implicit cast of the arguments necessary to uphold the
+  /// invariant that a method invocation with an interface target handles
+  /// the static types at the call site.
+  void _updateMethodInvocationTarget(
+      ir.MethodInvocation node,
+      ArgumentTypes argumentTypes,
+      ir.DartType functionType,
+      ir.Member interfaceTarget) {
+    // TODO(johnniwinther): Handle incremental target improvement.
+    if (node.interfaceTarget != null) return;
+    node.interfaceTarget = interfaceTarget;
+    if (functionType is! ir.FunctionType) return;
+    ir.FunctionType parameterTypes = functionType;
+    Map<int, ir.DartType> neededPositionalChecks = {};
+    for (int i = 0; i < node.arguments.positional.length; i++) {
+      ir.DartType argumentType = argumentTypes.positional[i];
+      ir.DartType parameterType = parameterTypes.positionalParameters[i];
+      if (!typeEnvironment.isSubtypeOf(argumentType, parameterType)) {
+        neededPositionalChecks[i] = parameterType;
+      }
+    }
+    Map<int, ir.DartType> neededNamedChecks = {};
+    for (int argumentIndex = 0;
+        argumentIndex < node.arguments.named.length;
+        argumentIndex++) {
+      ir.NamedExpression namedArgument = node.arguments.named[argumentIndex];
+      ir.DartType argumentType = argumentTypes.named[argumentIndex];
+      ir.DartType parameterType = parameterTypes.namedParameters
+          .singleWhere((namedType) => namedType.name == namedArgument.name)
+          .type;
+      if (!typeEnvironment.isSubtypeOf(argumentType, parameterType)) {
+        neededNamedChecks[argumentIndex] = parameterType;
+      }
+    }
+    if (neededPositionalChecks.isEmpty && neededNamedChecks.isEmpty) {
+      // No implicit casts needed
+      return;
+    }
+
+    List<ir.VariableDeclaration> letVariables = [];
+
+    // Arguments need to be hoisted to an enclosing let expression in order
+    // to ensure that the arguments are evaluated before any implicit cast.
+
+    ir.Expression updateArgument(ir.Expression expression, ir.TreeNode parent,
+        ir.DartType argumentType, ir.DartType checkedParameterType) {
+      ir.VariableDeclaration variable =
+          new ir.VariableDeclaration.forValue(expression, type: argumentType);
+      // Visit the newly created variable declaration.
+      handleVariableDeclaration(variable);
+      letVariables.add(variable);
+      ir.VariableGet get = new ir.VariableGet(variable)..parent = parent;
+      // Visit the newly created variable get.
+      handleVariableGet(get, argumentType);
+      cachedStaticTypes[get] = argumentType;
+
+      if (checkedParameterType == null) {
+        return get;
+      }
+      // We need to insert an implicit cast to preserve the invariant that
+      // a method invocation with a known interface target is also
+      // statically checked.
+      ir.AsExpression implicitCast =
+          new ir.AsExpression(get, checkedParameterType)
+            ..isTypeError = true
+            ..parent = parent;
+      // Visit the newly created as expression; the original value has
+      // already been visited.
+      handleAsExpression(implicitCast, argumentType);
+      return implicitCast;
+    }
+
+    for (int index = 0; index < node.arguments.positional.length; index++) {
+      ir.DartType argumentType = argumentTypes.positional[index];
+      node.arguments.positional[index] = updateArgument(
+          node.arguments.positional[index],
+          node.arguments,
+          argumentType,
+          neededPositionalChecks[index]);
+    }
+    for (int argumentIndex = 0;
+        argumentIndex < node.arguments.named.length;
+        argumentIndex++) {
+      ir.NamedExpression namedArgument = node.arguments.named[argumentIndex];
+      ir.DartType argumentType = argumentTypes.named[argumentIndex];
+      namedArgument.value = updateArgument(namedArgument.value, namedArgument,
+          argumentType, neededNamedChecks[argumentIndex]);
+    }
+
+    ir.Expression dummy = new ir.NullLiteral();
+    node.replaceWith(dummy);
+    ir.Expression body = node;
+    for (ir.VariableDeclaration variable in letVariables.reversed) {
+      body = new ir.Let(variable, body);
+    }
+    dummy.replaceWith(body);
+  }
+
   /// Computes the result type of the method invocation [node] on a receiver of
   /// type [receiverType].
   ///
@@ -436,20 +561,17 @@
       ir.Member member =
           hierarchy.getInterfaceMember(receiverType.classNode, node.name);
       if (_isApplicable(node.arguments, member)) {
-        interfaceTarget = node.interfaceTarget = member;
+        interfaceTarget = member;
       }
     }
     if (interfaceTarget != null) {
-      if (isSpecialCasedBinaryOperator(interfaceTarget)) {
-        ir.DartType argumentType = argumentTypes.positional[0];
-        return typeEnvironment.getTypeOfOverloadedArithmetic(
-            receiverType, argumentType);
-      }
       ir.Class superclass = interfaceTarget.enclosingClass;
-      receiverType = getTypeAsInstanceOf(receiverType, superclass);
-      ir.DartType getterType = ir.Substitution.fromInterfaceType(receiverType)
-          .substituteType(interfaceTarget.getterType);
+      ir.Substitution receiverSubstitution = ir.Substitution.fromInterfaceType(
+          getTypeAsInstanceOf(receiverType, superclass));
+      ir.DartType getterType =
+          receiverSubstitution.substituteType(interfaceTarget.getterType);
       if (getterType is ir.FunctionType) {
+        ir.FunctionType functionType = getterType;
         List<ir.DartType> typeArguments = node.arguments.types;
         if (interfaceTarget is ir.Procedure &&
             interfaceTarget.function.typeParameters.isNotEmpty &&
@@ -457,15 +579,22 @@
           // If this was a dynamic call the invocation does not have the
           // inferred default type arguments so we need to create them here
           // to perform a valid substitution.
-          ir.Substitution substitution =
-              ir.Substitution.fromInterfaceType(receiverType);
           typeArguments = interfaceTarget.function.typeParameters
-              .map((t) => substitution.substituteType(t.defaultType))
+              .map((t) => receiverSubstitution.substituteType(t.defaultType))
               .toList();
         }
-        return ir.Substitution.fromPairs(
-                getterType.typeParameters, typeArguments)
-            .substituteType(getterType.returnType);
+        getterType = ir.Substitution.fromPairs(
+                functionType.typeParameters, typeArguments)
+            .substituteType(functionType.withoutTypeParameters);
+      }
+      _updateMethodInvocationTarget(
+          node, argumentTypes, getterType, interfaceTarget);
+      if (isSpecialCasedBinaryOperator(interfaceTarget)) {
+        ir.DartType argumentType = argumentTypes.positional[0];
+        return typeEnvironment.getTypeOfOverloadedArithmetic(
+            receiverType, argumentType);
+      } else if (getterType is ir.FunctionType) {
+        return getterType.returnType;
       } else {
         return const ir.DynamicType();
       }
@@ -823,6 +952,7 @@
     return type;
   }
 
+  @override
   ir.DartType visitExpressionStatement(ir.ExpressionStatement node) {
     visitNode(node.expression);
     return null;
@@ -1299,6 +1429,7 @@
     return candidate;
   }
 
+  @override
   int get hashCode {
     if (_hashCode == null) {
       _hashCode = Hashing.setHash(falseTypes,
@@ -1307,6 +1438,7 @@
     return _hashCode;
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     return other is TypeHolder &&
@@ -1332,6 +1464,7 @@
     sb.write('}');
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('TypeHolder(');
@@ -1569,6 +1702,7 @@
     sb.write(']');
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('TargetInfo(');
@@ -1713,6 +1847,7 @@
     return sb.toString();
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('TypeMap(');
diff --git a/pkg/compiler/lib/src/ir/static_type_base.dart b/pkg/compiler/lib/src/ir/static_type_base.dart
index 2ed1a24..272689a 100644
--- a/pkg/compiler/lib/src/ir/static_type_base.dart
+++ b/pkg/compiler/lib/src/ir/static_type_base.dart
@@ -14,6 +14,7 @@
 class DoesNotCompleteType extends ir.BottomType {
   const DoesNotCompleteType();
 
+  @override
   String toString() => 'DoesNotCompleteType()';
 }
 
@@ -27,6 +28,7 @@
       ? new ThisInterfaceType(type.classNode, type.typeArguments)
       : null;
 
+  @override
   String toString() => 'this:${super.toString()}';
 }
 
@@ -40,6 +42,7 @@
       ? new ExactInterfaceType(type.classNode, type.typeArguments)
       : null;
 
+  @override
   String toString() => 'exact:${super.toString()}';
 }
 
@@ -79,6 +82,7 @@
     }
   }
 
+  @override
   ir.DartType defaultExpression(ir.Expression node) {
     throw fail('Unhandled node $node (${node.runtimeType})');
   }
diff --git a/pkg/compiler/lib/src/ir/types.dart b/pkg/compiler/lib/src/ir/types.dart
index 6d0f40d..ec95dff 100644
--- a/pkg/compiler/lib/src/ir/types.dart
+++ b/pkg/compiler/lib/src/ir/types.dart
@@ -99,18 +99,22 @@
 
   KernelOrderedTypeSetBuilder(this.elementMap, ClassEntity cls) : super(cls);
 
+  @override
   InterfaceType getThisType(ClassEntity cls) {
     return elementMap.getThisType(cls);
   }
 
+  @override
   InterfaceType substByContext(InterfaceType type, InterfaceType context) {
     return elementMap.substByContext(type, context);
   }
 
+  @override
   int getHierarchyDepth(ClassEntity cls) {
     return elementMap.getHierarchyDepth(cls);
   }
 
+  @override
   OrderedTypeSet getOrderedTypeSet(ClassEntity cls) {
     return elementMap.getOrderedTypeSet(cls);
   }
@@ -141,6 +145,7 @@
 
 class KernelSubtypeVisitor extends SubtypeVisitor<DartType>
     with AbstractTypeRelationMixin {
+  @override
   final IrToElementMap elementMap;
 
   KernelSubtypeVisitor(this.elementMap);
@@ -148,6 +153,7 @@
 
 class _KernelPotentialSubtypeVisitor extends PotentialSubtypeVisitor<DartType>
     with AbstractTypeRelationMixin {
+  @override
   final IrToElementMap elementMap;
 
   _KernelPotentialSubtypeVisitor(this.elementMap);
diff --git a/pkg/compiler/lib/src/ir/util.dart b/pkg/compiler/lib/src/ir/util.dart
index 0a749db..2ce8d7d 100644
--- a/pkg/compiler/lib/src/ir/util.dart
+++ b/pkg/compiler/lib/src/ir/util.dart
@@ -91,6 +91,7 @@
 
   ir.Let get let => syntheticVariable.parent;
 
+  @override
   String toString() => let.toString();
 }
 
diff --git a/pkg/compiler/lib/src/ir/visitors.dart b/pkg/compiler/lib/src/ir/visitors.dart
index fabd55d..0b7e8e4 100644
--- a/pkg/compiler/lib/src/ir/visitors.dart
+++ b/pkg/compiler/lib/src/ir/visitors.dart
@@ -63,6 +63,7 @@
     return constant;
   }
 
+  @override
   ConstantExpression defaultExpression(ir.Expression node) {
     if (requireConstant) {
       failNode ??= node;
diff --git a/pkg/compiler/lib/src/js/js.dart b/pkg/compiler/lib/src/js/js.dart
index 523cd66..c62d6f3 100644
--- a/pkg/compiler/lib/src/js/js.dart
+++ b/pkg/compiler/lib/src/js/js.dart
@@ -134,6 +134,7 @@
   final bool _protectForEval;
   LiteralString _cachedLiteral;
 
+  @override
   Iterable<Node> get containedNodes => [tree];
 
   /// A [js.Literal] that represents the string result of unparsing [ast].
diff --git a/pkg/compiler/lib/src/js/js_debug.dart b/pkg/compiler/lib/src/js/js_debug.dart
index d191491..9eaca9f 100644
--- a/pkg/compiler/lib/src/js/js_debug.dart
+++ b/pkg/compiler/lib/src/js/js_debug.dart
@@ -24,6 +24,7 @@
 /// Visitor that creates an XML-like representation of the structure of a
 /// JavaScript [Node].
 class DebugPrinter extends BaseVisitor with Indentation, Tagging<Node> {
+  @override
   StringBuffer sb = new StringBuffer();
 
   void visitNodeWithChildren(Node node, String type, [Map params]) {
diff --git a/pkg/compiler/lib/src/js/js_source_mapping.dart b/pkg/compiler/lib/src/js/js_source_mapping.dart
index 13735ca..ff8a155 100644
--- a/pkg/compiler/lib/src/js/js_source_mapping.dart
+++ b/pkg/compiler/lib/src/js/js_source_mapping.dart
@@ -63,6 +63,7 @@
 
   SourceMapperProviderImpl(this.provider);
 
+  @override
   SourceMapper createSourceMapper(String name) {
     return new SourceLocationsMapper(provider.createSourceLocations(name));
   }
diff --git a/pkg/compiler/lib/src/js/placeholder_safety.dart b/pkg/compiler/lib/src/js/placeholder_safety.dart
index 48b71cc..72d1e8d 100644
--- a/pkg/compiler/lib/src/js/placeholder_safety.dart
+++ b/pkg/compiler/lib/src/js/placeholder_safety.dart
@@ -60,16 +60,19 @@
     return node.accept(this);
   }
 
+  @override
   int visitNode(js.Node node) {
     safe = false;
     super.visitNode(node);
     return UNKNOWN_VALUE;
   }
 
+  @override
   int visitLiteralNull(js.LiteralNull node) {
     return UNKNOWN_VALUE;
   }
 
+  @override
   int visitLiteral(js.Literal node) {
     return NONNULL_VALUE;
   }
@@ -81,26 +84,32 @@
     return position;
   }
 
+  @override
   int visitInterpolatedExpression(js.InterpolatedExpression node) {
     return handleInterpolatedNode(node);
   }
 
+  @override
   int visitInterpolatedLiteral(js.InterpolatedLiteral node) {
     return handleInterpolatedNode(node);
   }
 
+  @override
   int visitInterpolatedSelector(js.InterpolatedSelector node) {
     return handleInterpolatedNode(node);
   }
 
+  @override
   int visitInterpolatedStatement(js.InterpolatedStatement node) {
     return handleInterpolatedNode(node);
   }
 
+  @override
   int visitInterpolatedDeclaration(js.InterpolatedDeclaration node) {
     return handleInterpolatedNode(node);
   }
 
+  @override
   int visitObjectInitializer(js.ObjectInitializer node) {
     for (js.Property property in node.properties) {
       visit(property);
@@ -108,21 +117,25 @@
     return NONNULL_VALUE;
   }
 
+  @override
   int visitProperty(js.Property node) {
     visit(node.name);
     visit(node.value);
     return UNKNOWN_VALUE;
   }
 
+  @override
   int visitArrayInitializer(js.ArrayInitializer node) {
     node.elements.forEach(visit);
     return NONNULL_VALUE;
   }
 
+  @override
   int visitArrayHole(js.ArrayHole node) {
     return UNKNOWN_VALUE;
   }
 
+  @override
   int visitAccess(js.PropertyAccess node) {
     int first = visit(node.receiver);
     visit(node.selector);
@@ -131,6 +144,7 @@
     return UNKNOWN_VALUE;
   }
 
+  @override
   int visitAssignment(js.Assignment node) {
     js.Expression left = node.leftHandSide;
     js.Expression right = node.value;
@@ -172,6 +186,7 @@
     return leftToRight();
   }
 
+  @override
   int visitCall(js.Call node) {
     // TODO(sra): Recognize JavaScript built-ins like
     // 'Object.prototype.hasOwnProperty.call'.
@@ -180,12 +195,14 @@
     return unsafe(UNKNOWN_VALUE);
   }
 
+  @override
   int visitNew(js.New node) {
     visit(node.target);
     node.arguments.forEach(visit);
     return unsafe(NONNULL_VALUE);
   }
 
+  @override
   int visitBinary(js.Binary node) {
     switch (node.op) {
       // We make the non-conservative assumption that these operations are not
@@ -238,6 +255,7 @@
     }
   }
 
+  @override
   int visitConditional(js.Conditional node) {
     visit(node.condition);
     // TODO(sra): Might be safe, e.g.  "# ? 1 : 2".
@@ -247,11 +265,13 @@
     return UNKNOWN_VALUE;
   }
 
+  @override
   int visitThrow(js.Throw node) {
     visit(node.expression);
     return unsafe(UNKNOWN_VALUE);
   }
 
+  @override
   int visitPrefix(js.Prefix node) {
     if (node.op == 'typeof') {
       // "typeof a" first evaluates to a Reference. If the Reference is to a
@@ -287,12 +307,14 @@
     }
   }
 
+  @override
   int visitPostfix(js.Postfix node) {
     assert(node.op == '--' || node.op == '++');
     visit(node.argument);
     return NONNULL_VALUE; // Always a number, even for "(a=null, a++)".
   }
 
+  @override
   int visitVariableUse(js.VariableUse node) {
     // We could get a ReferenceError unless the variable is in scope.  For JS
     // fragments, the only use of VariableUse outside a `function(){...}` should
@@ -315,6 +337,7 @@
     }
   }
 
+  @override
   int visitFun(js.Fun node) {
     bool oldSafe = safe;
     int oldNextPosition = nextPosition;
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index 68fffe8..b3768c4 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -1510,6 +1510,7 @@
   }
 
   /// See the comments of [rewriteFunction] for more explanation.
+  @override
   void visitTry(js.Try node) {
     if (!shouldTransform(node)) {
       js.Block body = translateToBlock(node.body);
@@ -1721,6 +1722,7 @@
 }
 
 class AsyncRewriter extends AsyncRewriterBase {
+  @override
   bool get isAsync => true;
 
   /// The Completer that will finish an async function.
@@ -1787,6 +1789,7 @@
     reporter.internalError(spannable, "Yield in non-generating async function");
   }
 
+  @override
   void addErrorExit(SourceInformation sourceInformation) {
     if (!hasHandlerLabels) return; // rethrow handled in method boilerplate.
     beginLabel(rethrowLabel);
@@ -1803,6 +1806,7 @@
   /// Returning from an async method calls [asyncStarHelper] with the result.
   /// (the result might have been stored in [returnValue] by some finally
   /// block).
+  @override
   void addSuccessExit(SourceInformation sourceInformation) {
     if (analysis.hasExplicitReturns) {
       beginLabel(exitLabel);
@@ -1929,6 +1933,7 @@
 }
 
 class SyncStarRewriter extends AsyncRewriterBase {
+  @override
   bool get isSyncStar => true;
 
   /// Constructor creating the Iterable for a sync* method. Called with
@@ -2068,6 +2073,7 @@
     }).withSourceInformation(functionSourceInformation);
   }
 
+  @override
   void addErrorExit(SourceInformation sourceInformation) {
     hasHandlerLabels = true; // TODO(sra): Add short form error handler.
     beginLabel(rethrowLabel);
@@ -2080,6 +2086,7 @@
   }
 
   /// Returning from a sync* function returns an [endOfIteration] marker.
+  @override
   void addSuccessExit(SourceInformation sourceInformation) {
     if (analysis.hasExplicitReturns) {
       beginLabel(exitLabel);
@@ -2114,6 +2121,7 @@
 }
 
 class AsyncStarRewriter extends AsyncRewriterBase {
+  @override
   bool get isAsyncStar => true;
 
   /// The stack of labels of finally blocks to assign to [next] if the
diff --git a/pkg/compiler/lib/src/js_backend/annotations.dart b/pkg/compiler/lib/src/js_backend/annotations.dart
index f0c48f7..1464c0b 100644
--- a/pkg/compiler/lib/src/js_backend/annotations.dart
+++ b/pkg/compiler/lib/src/js_backend/annotations.dart
@@ -4,11 +4,16 @@
 
 library js_backend.backend.annotations;
 
+import 'package:kernel/ast.dart' as ir;
+
+import '../common.dart';
 import '../common_elements.dart' show KCommonElements, KElementEnvironment;
 import '../constants/values.dart';
 import '../diagnostics/diagnostic_listener.dart';
 import '../diagnostics/messages.dart';
 import '../elements/entities.dart';
+import '../ir/annotations.dart';
+import '../ir/util.dart';
 import '../kernel/dart2js_target.dart';
 import '../options.dart';
 import '../serialization/serialization.dart';
@@ -80,20 +85,11 @@
   ];
 }
 
-Set<PragmaAnnotation> processMemberAnnotations(
-    CompilerOptions options,
-    DiagnosticReporter reporter,
+List<PragmaAnnotationData> computePragmaAnnotationData(
     KCommonElements commonElements,
     KElementEnvironment elementEnvironment,
-    AnnotationsDataBuilder annotationsDataBuilder,
     MemberEntity element) {
-  EnumSet<PragmaAnnotation> values = new EnumSet<PragmaAnnotation>();
-
-  LibraryEntity library = element.library;
-  bool platformAnnotationsAllowed = options.testMode ||
-      library.canonicalUri.scheme == 'dart' ||
-      maybeEnableNative(library.canonicalUri);
-
+  List<PragmaAnnotationData> annotations = [];
   for (ConstantValue constantValue
       in elementEnvironment.getMemberMetadata(element)) {
     if (!constantValue.isConstructedObject) continue;
@@ -102,21 +98,9 @@
     assert(cls != null); // Unresolved classes null.
 
     if (cls == commonElements.metaNoInlineClass) {
-      values.add(PragmaAnnotation.noInline);
-      if (element is! FunctionEntity) {
-        reporter.internalError(
-            element,
-            "@pragma('dart2js:noInline') is only allowed in methods "
-            "and constructors.");
-      }
+      annotations.add(const PragmaAnnotationData('noInline'));
     } else if (cls == commonElements.metaTryInlineClass) {
-      values.add(PragmaAnnotation.tryInline);
-      if (element is! FunctionEntity) {
-        reporter.internalError(
-            element,
-            "@pragma('dart2js:tryInline') is only allowed in methods "
-            "and constructors.");
-      }
+      annotations.add(const PragmaAnnotationData('tryInline'));
     } else if (cls == commonElements.pragmaClass) {
       ConstantValue nameValue =
           value.fields[commonElements.pragmaClassNameField];
@@ -128,49 +112,78 @@
 
       ConstantValue optionsValue =
           value.fields[commonElements.pragmaClassOptionsField];
-      bool found = false;
-      for (PragmaAnnotation annotation in PragmaAnnotation.values) {
-        if (annotation.name == suffix) {
-          found = true;
-          values.add(annotation);
+      annotations.add(
+          new PragmaAnnotationData(suffix, hasOptions: !optionsValue.isNull));
+    }
+  }
+  return annotations;
+}
 
-          if (!optionsValue.isNull) {
-            reporter.reportErrorMessage(element, MessageKind.GENERIC,
-                {'text': "@pragma('$name') annotation does not take options"});
-          }
-          if (annotation.forFunctionsOnly) {
-            if (element is! FunctionEntity) {
-              reporter.reportErrorMessage(element, MessageKind.GENERIC, {
-                'text': "@pragma('$name') annotation is only supported "
-                    "for methods and constructors."
-              });
-            }
-          }
-          if (annotation.forFieldsOnly) {
-            if (element is! FieldEntity) {
-              reporter.reportErrorMessage(element, MessageKind.GENERIC, {
-                'text': "@pragma('$name') annotation is only supported "
-                    "for fields."
-              });
-            }
-          }
-          if (annotation.internalOnly && !platformAnnotationsAllowed) {
-            reporter.reportErrorMessage(element, MessageKind.GENERIC,
-                {'text': "Unrecognized dart2js pragma @pragma('$name')"});
-          }
-          break;
+EnumSet<PragmaAnnotation> processMemberAnnotations(
+    CompilerOptions options,
+    DiagnosticReporter reporter,
+    ir.Member member,
+    List<PragmaAnnotationData> pragmaAnnotationData) {
+  EnumSet<PragmaAnnotation> values = new EnumSet<PragmaAnnotation>();
+
+  Uri uri = member.enclosingLibrary.importUri;
+  bool platformAnnotationsAllowed =
+      options.testMode || uri.scheme == 'dart' || maybeEnableNative(uri);
+
+  for (PragmaAnnotationData data in pragmaAnnotationData) {
+    String name = data.name;
+    String suffix = data.suffix;
+    bool found = false;
+    for (PragmaAnnotation annotation in PragmaAnnotation.values) {
+      if (annotation.name == suffix) {
+        found = true;
+        values.add(annotation);
+
+        if (data.hasOptions) {
+          reporter.reportErrorMessage(
+              computeSourceSpanFromTreeNode(member),
+              MessageKind.GENERIC,
+              {'text': "@pragma('$name') annotation does not take options"});
         }
+        if (annotation.forFunctionsOnly) {
+          if (member is! ir.Procedure && member is! ir.Constructor) {
+            reporter.reportErrorMessage(
+                computeSourceSpanFromTreeNode(member), MessageKind.GENERIC, {
+              'text': "@pragma('$name') annotation is only supported "
+                  "for methods and constructors."
+            });
+          }
+        }
+        if (annotation.forFieldsOnly) {
+          if (member is! ir.Field) {
+            reporter.reportErrorMessage(
+                computeSourceSpanFromTreeNode(member), MessageKind.GENERIC, {
+              'text': "@pragma('$name') annotation is only supported "
+                  "for fields."
+            });
+          }
+        }
+        if (annotation.internalOnly && !platformAnnotationsAllowed) {
+          reporter.reportErrorMessage(
+              computeSourceSpanFromTreeNode(member),
+              MessageKind.GENERIC,
+              {'text': "Unrecognized dart2js pragma @pragma('$name')"});
+        }
+        break;
       }
-      if (!found) {
-        reporter.reportErrorMessage(element, MessageKind.GENERIC,
-            {'text': "Unknown dart2js pragma @pragma('$name')"});
-      }
+    }
+    if (!found) {
+      reporter.reportErrorMessage(
+          computeSourceSpanFromTreeNode(member),
+          MessageKind.GENERIC,
+          {'text': "Unknown dart2js pragma @pragma('$name')"});
     }
   }
 
   if (values.contains(PragmaAnnotation.tryInline) &&
       values.contains(PragmaAnnotation.noInline)) {
-    reporter.reportErrorMessage(element, MessageKind.GENERIC, {
+    reporter.reportErrorMessage(
+        computeSourceSpanFromTreeNode(member), MessageKind.GENERIC, {
       'text': "@pragma('dart2js:tryInline') must not be used with "
           "@pragma('dart2js:noInline')."
     });
@@ -179,20 +192,18 @@
   if (values.contains(PragmaAnnotation.noThrows) &&
       !values.contains(PragmaAnnotation.noInline)) {
     reporter.internalError(
-        element,
+        computeSourceSpanFromTreeNode(member),
         "@pragma('dart2js:noThrows') should always be combined with "
         "@pragma('dart2js:noInline').");
   }
   if (values.contains(PragmaAnnotation.noSideEffects) &&
       !values.contains(PragmaAnnotation.noInline)) {
     reporter.internalError(
-        element,
+        computeSourceSpanFromTreeNode(member),
         "@pragma('dart2js:noSideEffects') should always be combined with "
         "@pragma('dart2js:noInline').");
   }
-  annotationsDataBuilder.registerPragmaAnnotations(element, values);
-  return new Set<PragmaAnnotation>.from(
-      values.iterable(PragmaAnnotation.values));
+  return values;
 }
 
 abstract class AnnotationsData {
@@ -262,6 +273,7 @@
     return new AnnotationsDataImpl(pragmaAnnotations);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
     sink.writeMemberMap(pragmaAnnotations, (EnumSet<PragmaAnnotation> set) {
@@ -275,27 +287,35 @@
     return set != null && set.contains(annotation);
   }
 
+  @override
   bool hasAssumeDynamic(MemberEntity member) =>
       _hasPragma(member, PragmaAnnotation.assumeDynamic);
 
+  @override
   bool hasNoInline(MemberEntity member) =>
       _hasPragma(member, PragmaAnnotation.noInline);
 
+  @override
   bool hasTryInline(MemberEntity member) =>
       _hasPragma(member, PragmaAnnotation.tryInline);
 
+  @override
   bool hasDisableFinal(MemberEntity member) =>
       _hasPragma(member, PragmaAnnotation.disableFinal);
 
+  @override
   bool hasNoElision(MemberEntity member) =>
       _hasPragma(member, PragmaAnnotation.noElision);
 
+  @override
   bool hasNoThrows(MemberEntity member) =>
       _hasPragma(member, PragmaAnnotation.noThrows);
 
+  @override
   bool hasNoSideEffects(MemberEntity member) =>
       _hasPragma(member, PragmaAnnotation.noSideEffects);
 
+  @override
   void forEachNoInline(void f(FunctionEntity function)) {
     pragmaAnnotations
         .forEach((MemberEntity member, EnumSet<PragmaAnnotation> set) {
@@ -305,6 +325,7 @@
     });
   }
 
+  @override
   void forEachTryInline(void f(FunctionEntity function)) {
     pragmaAnnotations
         .forEach((MemberEntity member, EnumSet<PragmaAnnotation> set) {
@@ -314,6 +335,7 @@
     });
   }
 
+  @override
   void forEachNoThrows(void f(FunctionEntity function)) {
     pragmaAnnotations
         .forEach((MemberEntity member, EnumSet<PragmaAnnotation> set) {
@@ -323,6 +345,7 @@
     });
   }
 
+  @override
   void forEachNoSideEffects(void f(FunctionEntity function)) {
     pragmaAnnotations
         .forEach((MemberEntity member, EnumSet<PragmaAnnotation> set) {
diff --git a/pkg/compiler/lib/src/js_backend/backend_usage.dart b/pkg/compiler/lib/src/js_backend/backend_usage.dart
index ed86add..1dc5108 100644
--- a/pkg/compiler/lib/src/js_backend/backend_usage.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_usage.dart
@@ -114,12 +114,14 @@
   bool requiresPreamble = false;
 
   /// `true` if `Function.apply` is used.
+  @override
   bool isFunctionApplyUsed = false;
 
   /// `true` if 'dart:mirrors' features are used.
   bool isMirrorsUsed = false;
 
   /// `true` if `noSuchMethod` is used.
+  @override
   bool isNoSuchMethodUsed = false;
 
   BackendUsageBuilderImpl(this._frontendStrategy);
@@ -190,6 +192,7 @@
     }
   }
 
+  @override
   void processBackendImpact(BackendImpact backendImpact) {
     for (FunctionEntity staticUse in backendImpact.staticUses) {
       assert(staticUse != null);
@@ -223,6 +226,7 @@
     }
   }
 
+  @override
   void registerUsedMember(MemberEntity member) {
     if (member == _commonElements.getIsolateAffinityTagMarker) {
       _needToInitializeIsolateAffinityTag = true;
@@ -235,6 +239,7 @@
     }
   }
 
+  @override
   void registerGlobalFunctionDependency(FunctionEntity element) {
     assert(element != null);
     if (_globalFunctionDependencies == null) {
@@ -243,6 +248,7 @@
     _globalFunctionDependencies.add(element);
   }
 
+  @override
   void registerGlobalClassDependency(ClassEntity element) {
     assert(element != null);
     if (_globalClassDependencies == null) {
@@ -256,6 +262,7 @@
     _runtimeTypeUses.add(runtimeTypeUse);
   }
 
+  @override
   BackendUsage close() {
     return new BackendUsageImpl(
         globalFunctionDependencies: _globalFunctionDependencies,
@@ -289,19 +296,25 @@
 
   final Set<RuntimeTypeUse> _runtimeTypeUses;
 
+  @override
   bool needToInitializeIsolateAffinityTag;
+  @override
   bool needToInitializeDispatchProperty;
 
   /// `true` if a core-library function requires the preamble file to function.
+  @override
   final bool requiresPreamble;
 
   /// `true` if `Function.apply` is used.
+  @override
   final bool isFunctionApplyUsed;
 
   /// `true` if 'dart:mirrors' features are used.
+  @override
   final bool isMirrorsUsed;
 
   /// `true` if `noSuchMethod` is used.
+  @override
   final bool isNoSuchMethodUsed;
 
   BackendUsageImpl(
@@ -357,6 +370,7 @@
         isNoSuchMethodUsed: isNoSuchMethodUsed);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
     sink.writeMembers(_globalFunctionDependencies);
diff --git a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
index 71bb262..9682f5b 100644
--- a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
+++ b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
@@ -37,8 +37,10 @@
 class PropertyCheckedModeHelper extends CheckedModeHelper {
   const PropertyCheckedModeHelper(String name) : super(name);
 
+  @override
   CallStructure get callStructure => CallStructure.TWO_ARGS;
 
+  @override
   void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
       HTypeConversion node, List<jsAst.Expression> arguments) {
     DartType type = node.typeExpression;
@@ -50,8 +52,10 @@
 class TypeVariableCheckedModeHelper extends CheckedModeHelper {
   const TypeVariableCheckedModeHelper(String name) : super(name);
 
+  @override
   CallStructure get callStructure => CallStructure.TWO_ARGS;
 
+  @override
   void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
       HTypeConversion node, List<jsAst.Expression> arguments) {
     assert(node.typeExpression.isTypeVariable);
@@ -63,8 +67,10 @@
 class FunctionTypeRepresentationCheckedModeHelper extends CheckedModeHelper {
   const FunctionTypeRepresentationCheckedModeHelper(String name) : super(name);
 
+  @override
   CallStructure get callStructure => CallStructure.TWO_ARGS;
 
+  @override
   void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
       HTypeConversion node, List<jsAst.Expression> arguments) {
     assert(node.typeExpression.isFunctionType);
@@ -76,8 +82,10 @@
 class FutureOrRepresentationCheckedModeHelper extends CheckedModeHelper {
   const FutureOrRepresentationCheckedModeHelper(String name) : super(name);
 
+  @override
   CallStructure get callStructure => CallStructure.TWO_ARGS;
 
+  @override
   void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
       HTypeConversion node, List<jsAst.Expression> arguments) {
     assert(node.typeExpression.isFutureOr);
@@ -89,8 +97,10 @@
 class SubtypeCheckedModeHelper extends CheckedModeHelper {
   const SubtypeCheckedModeHelper(String name) : super(name);
 
+  @override
   CallStructure get callStructure => const CallStructure.unnamed(4);
 
+  @override
   void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
       HTypeConversion node, List<jsAst.Expression> arguments) {
     // TODO(sra): Move these calls into the SSA graph so that the arguments can
diff --git a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
index 1335b2e..2b65955 100644
--- a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
@@ -20,6 +20,7 @@
       : this.jsConstantCompiler = new JavaScriptConstantCompiler(),
         super(compiler.measurer);
 
+  @override
   String get name => 'ConstantHandler';
 }
 
diff --git a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
index a3c61f7..16be5f2 100644
--- a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
@@ -81,6 +81,7 @@
 }
 
 class CustomElementsResolutionAnalysis extends CustomElementsAnalysisBase {
+  @override
   final CustomElementsAnalysisJoin join;
 
   CustomElementsResolutionAnalysis(
@@ -117,6 +118,7 @@
 }
 
 class CustomElementsCodegenAnalysis extends CustomElementsAnalysisBase {
+  @override
   final CustomElementsAnalysisJoin join;
 
   CustomElementsCodegenAnalysis(CommonElements commonElements,
diff --git a/pkg/compiler/lib/src/js_backend/enqueuer.dart b/pkg/compiler/lib/src/js_backend/enqueuer.dart
index 72910ae..a0c3009 100644
--- a/pkg/compiler/lib/src/js_backend/enqueuer.dart
+++ b/pkg/compiler/lib/src/js_backend/enqueuer.dart
@@ -37,8 +37,11 @@
   final CodegenWorldBuilderImpl _worldBuilder;
   final WorkItemBuilder _workItemBuilder;
 
+  @override
   bool queueIsClosed = false;
+  @override
   final CompilerTask task;
+  @override
   final EnqueuerListener listener;
   final CompilerOptions _options;
 
@@ -62,8 +65,10 @@
     _impactVisitor = new EnqueuerImplImpactVisitor(this);
   }
 
+  @override
   CodegenWorldBuilder get worldBuilder => _worldBuilder;
 
+  @override
   bool get queueIsEmpty => _queue.isEmpty;
 
   @override
@@ -74,6 +79,7 @@
   }
 
   /// Returns [:true:] if this enqueuer is the resolution enqueuer.
+  @override
   bool get isResolutionQueue => false;
 
   /// Create a [WorkItem] for [entity] and add it to the work list if it has not
@@ -92,6 +98,7 @@
     _queue.add(workItem);
   }
 
+  @override
   void applyImpact(WorldImpact worldImpact, {var impactSource}) {
     if (worldImpact.isEmpty) return;
     impactStrategy.visitImpact(
@@ -106,11 +113,13 @@
     });
   }
 
+  @override
   bool checkNoEnqueuedInvokedInstanceMethods(
       ElementEnvironment elementEnvironment) {
     return checkEnqueuerConsistency(elementEnvironment);
   }
 
+  @override
   void checkClass(ClassEntity cls) {
     _worldBuilder.processClassMembers(cls, (MemberEntity member, useSet) {
       if (useSet.isNotEmpty) {
@@ -148,12 +157,14 @@
     }
   }
 
+  @override
   void processDynamicUse(DynamicUse dynamicUse) {
     task.measure(() {
       _worldBuilder.registerDynamicUse(dynamicUse, _applyMemberUse);
     });
   }
 
+  @override
   void processStaticUse(StaticUse staticUse) {
     _worldBuilder.registerStaticUse(staticUse, _applyMemberUse);
     switch (staticUse.kind) {
@@ -171,6 +182,7 @@
     }
   }
 
+  @override
   void processTypeUse(TypeUse typeUse) {
     DartType type = typeUse.type;
     switch (typeUse.kind) {
@@ -213,6 +225,7 @@
     }
   }
 
+  @override
   void processConstantUse(ConstantUse constantUse) {
     task.measure(() {
       if (_worldBuilder.registerConstantUse(constantUse)) {
@@ -252,6 +265,7 @@
         _queue.isNotEmpty || _recentClasses.isNotEmpty || _recentConstants);
   }
 
+  @override
   void forEach(void f(WorkItem work)) {
     _forEach(f);
     if (onEmptyForTesting != null) {
@@ -276,8 +290,10 @@
     listener.logSummary(log);
   }
 
+  @override
   String toString() => 'Enqueuer($name)';
 
+  @override
   ImpactUseCase get impactUse => IMPACT_USE;
 
   @override
diff --git a/pkg/compiler/lib/src/js_backend/field_analysis.dart b/pkg/compiler/lib/src/js_backend/field_analysis.dart
index 41477f0..915dd48 100644
--- a/pkg/compiler/lib/src/js_backend/field_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/field_analysis.dart
@@ -4,20 +4,20 @@
 
 import 'package:kernel/ast.dart' as ir;
 
+import '../common.dart';
 import '../constants/values.dart';
 import '../elements/entities.dart';
+import '../elements/entity_utils.dart';
 import '../ir/scope_visitor.dart';
 import '../js_model/elements.dart' show JField;
 import '../js_model/js_world_builder.dart';
 import '../kernel/element_map.dart';
 import '../kernel/kernel_strategy.dart';
 import '../kernel/kelements.dart' show KClass, KField, KConstructor;
+import '../kernel/kernel_world.dart';
 import '../options.dart';
 import '../serialization/serialization.dart';
 import '../universe/member_usage.dart';
-import '../world.dart';
-
-abstract class FieldAnalysis {}
 
 /// AllocatorAnalysis
 ///
@@ -35,7 +35,7 @@
 //
 //     this.x = this.z = null;
 //
-class KFieldAnalysis implements FieldAnalysis {
+class KFieldAnalysis {
   final KernelToElementMap _elementMap;
 
   final Map<KClass, ClassData> _classData = {};
@@ -154,6 +154,8 @@
   final InitializerComplexity complexity;
 
   StaticFieldData(this.initialValue, this.complexity);
+
+  bool get hasDependencies => complexity != null && complexity.fields != null;
 }
 
 class AllocatorData {
@@ -209,13 +211,14 @@
     throw new UnsupportedError('Unexpected kind $kind');
   }
 
+  @override
   String toString() => shortText;
 }
 
-class JFieldAnalysis implements FieldAnalysis {
+class JFieldAnalysis {
   /// Tag used for identifying serialized [JFieldAnalysis] objects in a
   /// debugging data stream.
-  static const String tag = 'allocator-analysis';
+  static const String tag = 'field-analysis';
 
   // --csp and --fast-startup have different constraints to the generated code.
 
@@ -241,8 +244,8 @@
     sink.end(tag);
   }
 
-  factory JFieldAnalysis.from(
-      KClosedWorld closedWorld, JsToFrontendMap map, CompilerOptions options) {
+  factory JFieldAnalysis.from(KClosedWorldImpl closedWorld, JsToFrontendMap map,
+      CompilerOptions options) {
     Map<FieldEntity, FieldAnalysisData> fieldData = {};
 
     bool canBeElided(FieldEntity field) {
@@ -355,33 +358,178 @@
       });
     });
 
+    List<KField> independentFields = [];
+    List<KField> dependentFields = [];
+
     closedWorld.liveMemberUsage
         .forEach((MemberEntity member, MemberUsage memberUsage) {
       if (member.isField && !member.isInstanceMember) {
-        JField jField = map.toBackendMember(member);
-        if (jField == null) return;
-
-        if (!memberUsage.hasRead && canBeElided(member)) {
-          fieldData[jField] = const FieldAnalysisData(isElided: true);
+        StaticFieldData staticFieldData =
+            closedWorld.fieldAnalysis._staticFieldData[member];
+        if (staticFieldData.hasDependencies) {
+          dependentFields.add(member);
         } else {
-          bool isEffectivelyFinal = !memberUsage.hasWrite;
-          StaticFieldData staticFieldData =
-              closedWorld.fieldAnalysis._staticFieldData[member];
-          ConstantValue value = map
-              .toBackendConstant(staticFieldData.initialValue, allowNull: true);
-          bool isElided =
-              isEffectivelyFinal && value != null && canBeElided(member);
-          // TODO(johnniwinther): Compute effective initializer complexity.
-          if (value != null || isEffectivelyFinal) {
-            fieldData[jField] = new FieldAnalysisData(
-                initialValue: value,
-                isEffectivelyFinal: isEffectivelyFinal,
-                isElided: isElided);
-          }
+          independentFields.add(member);
         }
       }
     });
 
+    // Fields already processed.
+    Set<KField> processedFields = {};
+
+    // Fields currently being processed. Use for detecting cyclic dependencies.
+    Set<KField> currentFields = {};
+
+    // Index ascribed to eager fields that depend on other fields. This is
+    // used to sort the field in emission to ensure that used fields have been
+    // initialized when read.
+    int eagerCreationIndex = 0;
+
+    /// Computes the [FieldAnalysisData] for the JField corresponding to
+    /// [kField].
+    ///
+    /// If the data is currently been computed, that is, [kField] has a
+    /// cyclic dependency, `null` is returned.
+    FieldAnalysisData processField(KField kField) {
+      JField jField = map.toBackendMember(kField);
+      // TODO(johnniwinther): Can we assert that [jField] exists?
+      if (jField == null) return null;
+
+      FieldAnalysisData data = fieldData[jField];
+      if (processedFields.contains(kField)) {
+        // We only store data for non-trivial [FieldAnalysisData].
+        return data ?? const FieldAnalysisData();
+      }
+      if (currentFields.contains(kField)) {
+        // Cyclic dependency.
+        return null;
+      }
+      currentFields.add(kField);
+      MemberUsage memberUsage = closedWorld.liveMemberUsage[kField];
+      if (!memberUsage.hasRead && canBeElided(kField)) {
+        data = fieldData[jField] = const FieldAnalysisData(isElided: true);
+      } else {
+        bool isEffectivelyFinal = !memberUsage.hasWrite;
+        StaticFieldData staticFieldData =
+            closedWorld.fieldAnalysis._staticFieldData[kField];
+        ConstantValue value = map
+            .toBackendConstant(staticFieldData.initialValue, allowNull: true);
+
+        // If the field is effectively final with a constant initializer we
+        // elide the field, if allowed, because it is effectively constant.
+        bool isElided =
+            isEffectivelyFinal && value != null && canBeElided(kField);
+
+        bool isEager;
+
+        // If the field is eager and dependent on other eager fields,
+        // [eagerFieldDependencies] holds these fields and [creationIndex] is
+        // given the creation order index used to ensure that all dependencies
+        // have been assigned their values before this field is initialized.
+        //
+        // Since we only need the values of [eagerFieldDependencies] for testing
+        // and only the non-emptiness for determining the need for creation
+        // order indices, [eagerFieldDependencies] is non-null if the field has
+        // dependencies but only hold these when [retainDataForTesting] is
+        // `true`.
+        List<FieldEntity> eagerFieldDependencies;
+        int creationIndex = null;
+
+        if (isElided) {
+          // If the field is elided it needs no initializer and is therefore
+          // not eager.
+          isEager = false;
+        } else {
+          // If the field has a constant initializer we know it can be
+          // initialized eagerly.
+          //
+          // Ideally this should be the same as
+          // `staticFieldData.complexity.isConstant` but currently the constant
+          // evaluator handles cases that the analysis doesn't, so we use the
+          // better result.
+          isEager = value != null;
+          if (!isEager) {
+            // The field might be eager depending on the initializer complexity
+            // and its dependencies.
+            InitializerComplexity complexity = staticFieldData.complexity;
+            isEager = complexity?.isEager ?? false;
+            if (isEager && complexity.fields != null) {
+              for (ir.Field node in complexity.fields) {
+                KField otherField = closedWorld.elementMap.getField(node);
+                FieldAnalysisData otherData = processField(otherField);
+                if (otherData == null) {
+                  // Cyclic dependency on [otherField].
+                  isEager = false;
+                  break;
+                }
+                if (otherData.isLazy) {
+                  // [otherField] needs lazy initialization.
+                  isEager = false;
+                  break;
+                }
+                if (!otherData.isEffectivelyFinal) {
+                  // [otherField] might not hold its initial value when this field
+                  // is accessed the first time, so we need to initialize this
+                  // field lazily.
+                  isEager = false;
+                  break;
+                }
+                if (!otherData.isEffectivelyConstant) {
+                  eagerFieldDependencies ??= [];
+                  if (retainDataForTesting) {
+                    eagerFieldDependencies.add(map.toBackendMember(otherField));
+                  }
+                }
+              }
+            }
+          }
+
+          if (isEager && eagerFieldDependencies != null) {
+            creationIndex = eagerCreationIndex++;
+            if (!retainDataForTesting) {
+              eagerFieldDependencies = null;
+            }
+          } else {
+            eagerFieldDependencies = null;
+          }
+        }
+
+        data = fieldData[jField] = new FieldAnalysisData(
+            initialValue: value,
+            isEffectivelyFinal: isEffectivelyFinal,
+            isElided: isElided,
+            isEager: isEager,
+            eagerCreationIndex: creationIndex,
+            eagerFieldDependenciesForTesting: eagerFieldDependencies);
+      }
+
+      currentFields.remove(kField);
+      processedFields.add(kField);
+      return data;
+    }
+
+    // Process independent fields in no particular order. The emitter sorts
+    // these later.
+    independentFields.forEach(processField);
+
+    // Process dependent fields in declaration order to make ascribed creation
+    // indices stable. The emitter uses the creation indices for sorting
+    // dependent fields.
+    dependentFields.sort((KField a, KField b) {
+      int result =
+          compareLibrariesUris(a.library.canonicalUri, b.library.canonicalUri);
+      if (result != 0) return result;
+      ir.Location aLocation = closedWorld.elementMap.getMemberNode(a).location;
+      ir.Location bLocation = closedWorld.elementMap.getMemberNode(b).location;
+      result = compareSourceUris(aLocation.file, bLocation.file);
+      if (result != 0) return result;
+      result = aLocation.line.compareTo(bLocation.line);
+      if (result != 0) return result;
+      return aLocation.column.compareTo(bLocation.column);
+    });
+
+    dependentFields.forEach(processField);
+
     return new JFieldAnalysis._(fieldData);
   }
 
@@ -402,11 +550,25 @@
   final bool isEffectivelyFinal;
   final bool isElided;
 
+  /// If `true` the field is not effectively constant but the initializer can be
+  /// generated eagerly without the need for lazy initialization wrapper.
+  final bool isEager;
+
+  /// Index ascribed to eager fields that depend on other fields. This is
+  /// used to sort the field in emission to ensure that used fields have been
+  /// initialized when read.
+  final int eagerCreationIndex;
+
+  final List<FieldEntity> eagerFieldDependenciesForTesting;
+
   const FieldAnalysisData(
       {this.initialValue,
       this.isInitializedInAllocator: false,
       this.isEffectivelyFinal: false,
-      this.isElided: false});
+      this.isElided: false,
+      this.isEager: false,
+      this.eagerCreationIndex: null,
+      this.eagerFieldDependenciesForTesting: null});
 
   factory FieldAnalysisData.fromDataSource(DataSource source) {
     source.begin(tag);
@@ -415,12 +577,19 @@
     bool isInitializedInAllocator = source.readBool();
     bool isEffectivelyFinal = source.readBool();
     bool isElided = source.readBool();
+    bool isEager = source.readBool();
+    int eagerCreationIndex = source.readIntOrNull();
+    List<FieldEntity> eagerFieldDependencies =
+        source.readMembers<FieldEntity>(emptyAsNull: true);
     source.end(tag);
     return new FieldAnalysisData(
         initialValue: initialValue,
         isInitializedInAllocator: isInitializedInAllocator,
         isEffectivelyFinal: isEffectivelyFinal,
-        isElided: isElided);
+        isElided: isElided,
+        isEager: isEager,
+        eagerCreationIndex: eagerCreationIndex,
+        eagerFieldDependenciesForTesting: eagerFieldDependencies);
   }
 
   void writeToDataSink(DataSink sink) {
@@ -429,16 +598,26 @@
     sink.writeBool(isInitializedInAllocator);
     sink.writeBool(isEffectivelyFinal);
     sink.writeBool(isElided);
+    sink.writeBool(isEager);
+    sink.writeIntOrNull(eagerCreationIndex);
+    sink.writeMembers(eagerFieldDependenciesForTesting, allowNull: true);
     sink.end(tag);
   }
 
+  /// If `true` the initializer for this field requires a lazy initialization
+  /// wrapper.
+  bool get isLazy => initialValue == null && !isEager;
+
   bool get isEffectivelyConstant =>
       isEffectivelyFinal && isElided && initialValue != null;
 
   ConstantValue get constantValue => isEffectivelyFinal ? initialValue : null;
 
+  @override
   String toString() =>
       'FieldAnalysisData(initialValue=${initialValue?.toStructuredText()},'
       'isInitializedInAllocator=$isInitializedInAllocator,'
-      'isEffectivelyFinal=$isEffectivelyFinal,isElided=$isElided)';
+      'isEffectivelyFinal=$isEffectivelyFinal,isElided=$isElided,'
+      'isEager=$isEager,eagerCreationIndex=$eagerCreationIndex,'
+      'eagerFieldDependencies=$eagerFieldDependenciesForTesting)';
 }
diff --git a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
index 828dd25..a0fb0b3 100644
--- a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
+++ b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
@@ -189,7 +189,9 @@
 /// as a separator between method names and argument counts and does not appear
 /// in generated names themselves.
 class _MixinFieldNamingScope extends _FieldNamingScope {
+  @override
   int get _localFieldNameCounter => registry.globalCount;
+  @override
   void set _localFieldNameCounter(int val) {
     registry.globalCount = val;
   }
@@ -204,6 +206,7 @@
       _FieldNamingScope superScope, _FieldNamingRegistry registry)
       : super.inherit(container, superScope, registry);
 
+  @override
   jsAst.Name _nextName() {
     jsAst.Name proposed = super._nextName();
     return new CompoundName([proposed, Namer._literalDollar]);
@@ -221,6 +224,7 @@
   @override
   bool containsField(_) => true;
 
+  @override
   jsAst.Name operator [](Entity field) {
     if (!names.containsKey(field)) add(field);
     return names[field];
diff --git a/pkg/compiler/lib/src/js_backend/frequency_namer.dart b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
index 781d1ef..36ff852 100644
--- a/pkg/compiler/lib/src/js_backend/frequency_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
@@ -7,6 +7,7 @@
 class FrequencyBasedNamer extends Namer
     with _MinifiedFieldNamer, _MinifiedOneShotInterceptorNamer
     implements jsAst.TokenFinalizer {
+  @override
   _FieldNamingRegistry fieldRegistry;
   List<TokenName> tokens = new List<TokenName>();
 
@@ -14,21 +15,35 @@
       new Maplet<NamingScope, TokenScope>();
 
   // Some basic settings for smaller names
+  @override
   String get isolateName => 'I';
+  @override
   String get isolatePropertiesName => 'p';
+  @override
   bool get shouldMinify => true;
 
+  @override
   final String getterPrefix = 'g';
+  @override
   final String setterPrefix = 's';
+  @override
   final String callPrefix = ''; // this will create function names $<n>
+  @override
   String get operatorIsPrefix => r'$i';
+  @override
   String get operatorAsPrefix => r'$a';
+  @override
   String get callCatchAllName => r'$C';
+  @override
   String get requiredParameterField => r'$R';
+  @override
   String get defaultValuesField => r'$D';
+  @override
   String get operatorSignature => r'$S';
+  @override
   String get genericInstantiationPrefix => r'$I';
 
+  @override
   jsAst.Name get staticsPropertyName =>
       _staticsPropertyName ??= getFreshName(instanceScope, 'static');
 
diff --git a/pkg/compiler/lib/src/js_backend/inferred_data.dart b/pkg/compiler/lib/src/js_backend/inferred_data.dart
index ad5be30..be9b3dc 100644
--- a/pkg/compiler/lib/src/js_backend/inferred_data.dart
+++ b/pkg/compiler/lib/src/js_backend/inferred_data.dart
@@ -121,6 +121,7 @@
         functionsThatMightBePassedToApply);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeBool(false); // Is _not_ trivial.
     sink.begin(tag);
@@ -235,6 +236,7 @@
   }
 
   /// Compute [SideEffects] for all registered [SideEffectBuilder]s.
+  @override
   InferredData close(JClosedWorld closedWorld) {
     assert(_sideEffectsBuilders != null,
         "Inferred data has already been computed.");
diff --git a/pkg/compiler/lib/src/js_backend/interceptor_data.dart b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
index 06c66ae..0a206a5 100644
--- a/pkg/compiler/lib/src/js_backend/interceptor_data.dart
+++ b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
@@ -72,6 +72,7 @@
   final Map<String, Set<MemberEntity>> interceptedMembers;
 
   /// Set of classes whose methods are intercepted.
+  @override
   final Set<ClassEntity> interceptedClasses;
 
   /// Set of classes used as mixins on intercepted (native and primitive)
@@ -125,6 +126,7 @@
         classesMixedIntoInterceptedClasses);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
     sink.writeInt(interceptedMembers.length);
@@ -137,6 +139,7 @@
     sink.end(tag);
   }
 
+  @override
   bool isInterceptedMethod(MemberEntity element) {
     if (!element.isInstanceMember) return false;
     // TODO(johnniwinther): Avoid this hack.
@@ -146,18 +149,22 @@
     return interceptedMembers[element.name] != null;
   }
 
+  @override
   bool fieldHasInterceptedGetter(FieldEntity element) {
     return interceptedMembers[element.name] != null;
   }
 
+  @override
   bool fieldHasInterceptedSetter(FieldEntity element) {
     return interceptedMembers[element.name] != null;
   }
 
+  @override
   bool isInterceptedName(String name) {
     return interceptedMembers[name] != null;
   }
 
+  @override
   bool isInterceptedSelector(Selector selector) {
     return interceptedMembers[selector.name] != null;
   }
@@ -165,6 +172,7 @@
   /// Returns `true` iff [selector] matches an element defined in a class mixed
   /// into an intercepted class.  These selectors are not eligible for the
   /// 'dummy explicit receiver' optimization.
+  @override
   bool isInterceptedMixinSelector(
       Selector selector, AbstractValue mask, JClosedWorld closedWorld) {
     Set<MemberEntity> elements =
@@ -203,6 +211,7 @@
   /// Returns a set of interceptor classes that contain a member named [name]
   ///
   /// Returns an empty set if there is no class. Do not modify the returned set.
+  @override
   Set<ClassEntity> getInterceptedClassesOn(
       String name, JClosedWorld closedWorld) {
     Set<MemberEntity> intercepted = interceptedMembers[name];
@@ -244,6 +253,7 @@
     return result;
   }
 
+  @override
   bool isInterceptedClass(ClassEntity element) {
     if (element == null) return false;
     if (_nativeData.isNativeOrExtendsNative(element)) return true;
@@ -252,9 +262,11 @@
     return false;
   }
 
+  @override
   bool isMixedIntoInterceptedClass(ClassEntity element) =>
       classesMixedIntoInterceptedClasses.contains(element);
 
+  @override
   bool mayGenerateInstanceofCheck(DartType type, JClosedWorld closedWorld) {
     // We can use an instanceof check for raw types that have no subclass that
     // is mixed-in or in an implements clause.
@@ -291,6 +303,7 @@
   InterceptorDataBuilderImpl(
       this._nativeData, this._elementEnvironment, this._commonElements);
 
+  @override
   InterceptorData close() {
     return new InterceptorDataImpl(
         _nativeData,
@@ -300,6 +313,7 @@
         _classesMixedIntoInterceptedClasses);
   }
 
+  @override
   void addInterceptorsForNativeClassMembers(ClassEntity cls) {
     _elementEnvironment.forEachClassMember(cls,
         (ClassEntity cls, MemberEntity member) {
@@ -317,6 +331,7 @@
     });
   }
 
+  @override
   void addInterceptors(ClassEntity cls) {
     if (_interceptedClasses.add(cls)) {
       _elementEnvironment.forEachClassMember(cls,
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index 2d772ff..3179a2f 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -16,21 +16,35 @@
     fieldRegistry = new _FieldNamingRegistry(this);
   }
 
+  @override
   _FieldNamingRegistry fieldRegistry;
 
+  @override
   String get isolateName => 'I';
+  @override
   String get isolatePropertiesName => 'p';
+  @override
   bool get shouldMinify => true;
 
+  @override
   final String getterPrefix = 'g';
+  @override
   final String setterPrefix = 's';
+  @override
   final String callPrefix = ''; // this will create function names $<n>
+  @override
   String get operatorIsPrefix => r'$i';
+  @override
   String get operatorAsPrefix => r'$a';
+  @override
   String get callCatchAllName => r'$C';
+  @override
   String get requiredParameterField => r'$R';
+  @override
   String get defaultValuesField => r'$D';
+  @override
   String get operatorSignature => r'$S';
+  @override
   String get genericInstantiationPrefix => r'$I';
 
   final ALPHABET_CHARACTERS = 52; // a-zA-Z.
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 3222b70..0648b9c 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -2291,24 +2291,30 @@
     return sb.toString();
   }
 
+  @override
   visit(DartType type, [_]) {
     type.accept(this, null);
   }
 
+  @override
   visitType(DartType type, _) {}
 
+  @override
   visitInterfaceType(InterfaceType type, _) {
     sb.write(type.element.name);
   }
 
+  @override
   visitTypedefType(TypedefType type, _) {
     sb.write(type.element.name);
   }
 
+  @override
   visitTypeVariableType(TypeVariableType type, _) {
     sb.write(type.element.name);
   }
 
+  @override
   visitFunctionType(FunctionType type, _) {
     if (rtiEncoder.isSimpleFunctionType(type)) {
       sb.write('args${type.parameterTypes.length}');
diff --git a/pkg/compiler/lib/src/js_backend/namer_names.dart b/pkg/compiler/lib/src/js_backend/namer_names.dart
index 9f351e3..db0819d 100644
--- a/pkg/compiler/lib/src/js_backend/namer_names.dart
+++ b/pkg/compiler/lib/src/js_backend/namer_names.dart
@@ -9,6 +9,7 @@
   int get _kind;
   _NamerName get _target => this;
 
+  @override
   String toString() {
     if (DEBUG_MODE) {
       return 'Name($key)';
@@ -21,21 +22,27 @@
 
 // ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class StringBackedName extends _NamerName {
+  @override
   final String name;
+  @override
   int get _kind => _NamerNameKinds.StringBacked.index;
 
   StringBackedName(this.name);
 
+  @override
   String get key => name;
 
+  @override
   operator ==(other) {
     if (other is _NameReference) other = other._target;
     if (identical(this, other)) return true;
     return (other is StringBackedName) && other.name == name;
   }
 
+  @override
   int get hashCode => name.hashCode;
 
+  @override
   int compareTo(covariant _NamerName other) {
     other = other._target;
     if (other._kind != _kind) return other._kind - _kind;
@@ -47,16 +54,21 @@
 abstract class _PrefixedName extends _NamerName implements jsAst.AstContainer {
   final jsAst.Name prefix;
   final jsAst.Name base;
+  @override
   int get _kind;
 
+  @override
   Iterable<jsAst.Node> get containedNodes => [prefix, base];
 
   _PrefixedName(this.prefix, this.base);
 
+  @override
   String get name => prefix.name + base.name;
 
+  @override
   String get key => prefix.key + base.key;
 
+  @override
   bool operator ==(other) {
     if (other is _NameReference) other = other._target;
     if (identical(this, other)) return true;
@@ -64,8 +76,10 @@
     return other.base == base && other.prefix == prefix;
   }
 
+  @override
   int get hashCode => base.hashCode * 13 + prefix.hashCode;
 
+  @override
   int compareTo(covariant _NamerName other) {
     other = other._target;
     if (other._kind != _kind) return other._kind - _kind;
@@ -83,6 +97,7 @@
 
 // ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class GetterName extends _PrefixedName {
+  @override
   int get _kind => _NamerNameKinds.Getter.index;
 
   GetterName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base);
@@ -90,6 +105,7 @@
 
 // ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class SetterName extends _PrefixedName {
+  @override
   int get _kind => _NamerNameKinds.Setter.index;
 
   SetterName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base);
@@ -97,6 +113,7 @@
 
 // ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class _AsyncName extends _PrefixedName {
+  @override
   int get _kind => _NamerNameKinds.Async.index;
 
   _AsyncName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base);
@@ -108,14 +125,17 @@
 // ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class CompoundName extends _NamerName implements jsAst.AstContainer {
   final List<_NamerName> _parts;
+  @override
   int get _kind => _NamerNameKinds.Compound.index;
   String _cachedName;
   int _cachedHashCode = -1;
 
+  @override
   Iterable<jsAst.Node> get containedNodes => _parts;
 
   CompoundName(this._parts);
 
+  @override
   String get name {
     if (_cachedName == null) {
       _cachedName = _parts.map((jsAst.Name name) => name.name).join();
@@ -123,8 +143,10 @@
     return _cachedName;
   }
 
+  @override
   String get key => _parts.map((_NamerName name) => name.key).join();
 
+  @override
   bool operator ==(other) {
     if (other is _NameReference) other = other._target;
     if (identical(this, other)) return true;
@@ -136,6 +158,7 @@
     return true;
   }
 
+  @override
   int get hashCode {
     if (_cachedHashCode < 0) {
       _cachedHashCode = 0;
@@ -146,6 +169,7 @@
     return _cachedHashCode;
   }
 
+  @override
   int compareTo(covariant _NamerName other) {
     other = other._target;
     if (other._kind != _kind) return other._kind - _kind;
@@ -163,8 +187,10 @@
 
 // ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class TokenName extends _NamerName implements jsAst.ReferenceCountedAstNode {
+  @override
   int get _kind => _NamerNameKinds.Token.index;
   String _name;
+  @override
   final String key;
   final TokenScope _scope;
   int _rc = 0;
@@ -173,6 +199,7 @@
 
   bool get isFinalized => _name != null;
 
+  @override
   String get name {
     assert(isFinalized);
     return _name;
@@ -186,6 +213,7 @@
     return key.compareTo(otherToken.key);
   }
 
+  @override
   markSeen(jsAst.TokenCounter counter) => _rc++;
 
   @override
@@ -209,15 +237,20 @@
 
 // ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
 class _NameReference extends _NamerName implements jsAst.AstContainer {
+  @override
   _NamerName _target;
 
+  @override
   int get _kind => _target._kind;
+  @override
   String get key => _target.key;
 
+  @override
   Iterable<jsAst.Node> get containedNodes => [_target];
 
   _NameReference(this._target);
 
+  @override
   String get name => _target.name;
 
   @override
diff --git a/pkg/compiler/lib/src/js_backend/native_data.dart b/pkg/compiler/lib/src/js_backend/native_data.dart
index a491286..7b31ddc 100644
--- a/pkg/compiler/lib/src/js_backend/native_data.dart
+++ b/pkg/compiler/lib/src/js_backend/native_data.dart
@@ -63,6 +63,7 @@
       NativeDataImpl.readFromDataSource;
 
   /// Serializes this [NativeData] to [sink].
+  @override
   void writeToDataSink(DataSink sink);
 
   /// Returns `true` if [element] corresponds to a native JavaScript member.
@@ -97,6 +98,7 @@
   String getFixedBackendMethodPath(FunctionEntity element);
 
   /// Returns `true` if [element] is a JsInterop method.
+  @override
   bool isJsInteropMember(MemberEntity element);
 
   /// Returns the explicit js interop name for library [element].
@@ -158,26 +160,10 @@
   /// Registers the [behavior] for writing to the native [field].
   void setNativeFieldStoreBehavior(FieldEntity field, NativeBehavior behavior);
 
-  /// Marks [element] as an explicit part of JsInterop. The js interop name is
-  /// expected to be computed later.
-  void markAsJsInteropMember(MemberEntity element);
-
   /// Sets the native [name] for the member [element]. This name is used for
   /// [element] in the generated JavaScript.
   void setNativeMemberName(MemberEntity element, String name);
 
-  /// Sets the explicit js interop [name] for the library [element].
-  void setJsInteropLibraryName(LibraryEntity element, String name);
-
-  /// Marks [element] as having an `@Anonymous` annotation.
-  void markJsInteropClassAsAnonymous(ClassEntity element);
-
-  /// Sets the explicit js interop [name] for the class [element].
-  void setJsInteropClassName(ClassEntity element, String name);
-
-  /// Sets the explicit js interop [name] for the member [element].
-  void setJsInteropMemberName(MemberEntity element, String name);
-
   /// Closes this builder and creates the resulting [NativeData] object.
   NativeData close();
 }
@@ -207,6 +193,7 @@
   /// The tag info string contains comma-separated 'words' which are either
   /// dispatch tags (having JavaScript identifier syntax) and directives that
   /// begin with `!`.
+  @override
   void setNativeClassTagInfo(ClassEntity cls, String tagText) {
     assert(
         !_closed,
@@ -267,6 +254,7 @@
     jsInteropMembers[element] = name;
   }
 
+  @override
   NativeBasicData close(ElementEnvironment environment) {
     _closed = true;
     return new NativeBasicDataImpl(
@@ -340,6 +328,7 @@
         jsInteropMembers);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
     sink.writeClassMap(nativeClassTagInfo, (NativeClassTag tag) {
@@ -438,29 +427,11 @@
   Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior =
       <FieldEntity, NativeBehavior>{};
 
-  /// The JavaScript names for libraries implemented via typed JavaScript
-  /// interop.
-  final Map<LibraryEntity, String> jsInteropLibraries;
-
-  /// JavaScript interop classes annotated with `@anonymous`
-  final Set<ClassEntity> anonymousJsInteropClasses;
-
-  /// The JavaScript names for classes implemented via typed JavaScript
-  /// interop.
-  final Map<ClassEntity, String> jsInteropClasses;
-
-  /// The JavaScript names for members implemented via typed JavaScript
-  /// interop.
-  final Map<MemberEntity, String> jsInteropMembers;
-
-  NativeDataBuilderImpl(this._nativeBasicData)
-      : jsInteropLibraries = _nativeBasicData.jsInteropLibraries,
-        jsInteropClasses = _nativeBasicData.jsInteropClasses,
-        anonymousJsInteropClasses = _nativeBasicData.anonymousJsInteropClasses,
-        jsInteropMembers = _nativeBasicData.jsInteropMembers;
+  NativeDataBuilderImpl(this._nativeBasicData);
 
   /// Sets the native [name] for the member [element]. This name is used for
   /// [element] in the generated JavaScript.
+  @override
   void setNativeMemberName(MemberEntity element, String name) {
     // TODO(johnniwinther): Avoid setting this more than once. The enqueuer
     // might enqueue [element] several times (before processing it) and computes
@@ -476,68 +447,26 @@
   }
 
   /// Registers the [behavior] for calling the native [method].
+  @override
   void setNativeMethodBehavior(FunctionEntity method, NativeBehavior behavior) {
     nativeMethodBehavior[method] = behavior;
   }
 
   /// Registers the [behavior] for reading from the native [field].
+  @override
   void setNativeFieldLoadBehavior(FieldEntity field, NativeBehavior behavior) {
     nativeFieldLoadBehavior[field] = behavior;
   }
 
   /// Registers the [behavior] for writing to the native [field].
+  @override
   void setNativeFieldStoreBehavior(FieldEntity field, NativeBehavior behavior) {
     nativeFieldStoreBehavior[field] = behavior;
   }
 
-  /// Sets the explicit js interop [name] for the library [element].
-  void setJsInteropLibraryName(LibraryEntity element, String name) {
-    assert(
-        _nativeBasicData.isJsInteropLibrary(element),
-        failedAt(element,
-            'Library $element is not js interop but given a js interop name.'));
-    jsInteropLibraries[element] = name;
-  }
-
   @override
-  void markJsInteropClassAsAnonymous(ClassEntity element) {
-    anonymousJsInteropClasses.add(element);
-  }
-
-  /// Sets the explicit js interop [name] for the class [element].
-  void setJsInteropClassName(ClassEntity element, String name) {
-    assert(
-        _nativeBasicData.isJsInteropClass(element),
-        failedAt(element,
-            'Class $element is not js interop but given a js interop name.'));
-    jsInteropClasses[element] = name;
-  }
-
-  @override
-  void markAsJsInteropMember(MemberEntity element) {
-    jsInteropMembers[element] = null;
-  }
-
-  /// Sets the explicit js interop [name] for the member [element].
-  void setJsInteropMemberName(MemberEntity element, String name) {
-    assert(
-        jsInteropMembers.containsKey(element),
-        failedAt(element,
-            'Member $element is not js interop but given a js interop name.'));
-    jsInteropMembers[element] = name;
-  }
-
-  @override
-  NativeData close() => new NativeDataImpl(
-      _nativeBasicData,
-      nativeMemberName,
-      nativeMethodBehavior,
-      nativeFieldLoadBehavior,
-      nativeFieldStoreBehavior,
-      jsInteropLibraries,
-      anonymousJsInteropClasses,
-      jsInteropClasses,
-      jsInteropMembers);
+  NativeData close() => new NativeDataImpl(_nativeBasicData, nativeMemberName,
+      nativeMethodBehavior, nativeFieldLoadBehavior, nativeFieldStoreBehavior);
 }
 
 // TODO(johnniwinther): Remove fields that overlap with [NativeBasicData], like
@@ -565,31 +494,12 @@
   /// Cache for [NativeBehavior]s for writing to native fields.
   final Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior;
 
-  /// The JavaScript names for libraries implemented via typed JavaScript
-  /// interop.
-  final Map<LibraryEntity, String> jsInteropLibraries;
-
-  /// JavaScript interop classes annotated with `@anonymous`
-  final Set<ClassEntity> anonymousJsInteropClasses;
-
-  /// The JavaScript names for classes implemented via typed JavaScript
-  /// interop.
-  final Map<ClassEntity, String> jsInteropClasses;
-
-  /// The JavaScript names for members implemented via typed JavaScript
-  /// interop.
-  final Map<MemberEntity, String> jsInteropMembers;
-
   NativeDataImpl(
       this._nativeBasicData,
       this.nativeMemberName,
       this.nativeMethodBehavior,
       this.nativeFieldLoadBehavior,
-      this.nativeFieldStoreBehavior,
-      this.jsInteropLibraries,
-      this.anonymousJsInteropClasses,
-      this.jsInteropClasses,
-      this.jsInteropMembers);
+      this.nativeFieldStoreBehavior);
 
   factory NativeDataImpl.readFromDataSource(
       DataSource source, ElementEnvironment elementEnvironment) {
@@ -604,26 +514,16 @@
         .readMemberMap(() => new NativeBehavior.readFromDataSource(source));
     Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior = source
         .readMemberMap(() => new NativeBehavior.readFromDataSource(source));
-    Map<LibraryEntity, String> jsInteropLibraries =
-        source.readLibraryMap(source.readString);
-    Set<ClassEntity> anonymousJsInteropClasses = source.readClasses().toSet();
-    Map<ClassEntity, String> jsInteropClasses =
-        source.readClassMap(source.readString);
-    Map<MemberEntity, String> jsInteropMembers =
-        source.readMemberMap(source.readString);
     source.end(tag);
     return new NativeDataImpl(
         nativeBasicData,
         nativeMemberName,
         nativeMethodBehavior,
         nativeFieldLoadBehavior,
-        nativeFieldStoreBehavior,
-        jsInteropLibraries,
-        anonymousJsInteropClasses,
-        jsInteropClasses,
-        jsInteropMembers);
+        nativeFieldStoreBehavior);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
     _nativeBasicData.writeToDataSink(sink);
@@ -641,65 +541,96 @@
       behavior.writeToDataSink(sink);
     });
 
-    sink.writeLibraryMap(jsInteropLibraries, sink.writeString);
-    sink.writeClasses(anonymousJsInteropClasses);
-    sink.writeClassMap(jsInteropClasses, sink.writeString);
-    sink.writeMemberMap(jsInteropMembers, sink.writeString);
     sink.end(tag);
   }
 
+  /// The JavaScript names for libraries implemented via typed JavaScript
+  /// interop.
+  @override
+  Map<LibraryEntity, String> get jsInteropLibraries =>
+      _nativeBasicData.jsInteropLibraries;
+
+  /// JavaScript interop classes annotated with `@anonymous`
+  @override
+  Set<ClassEntity> get anonymousJsInteropClasses =>
+      _nativeBasicData.anonymousJsInteropClasses;
+
+  /// The JavaScript names for classes implemented via typed JavaScript
+  /// interop.
+  @override
+  Map<ClassEntity, String> get jsInteropClasses =>
+      _nativeBasicData.jsInteropClasses;
+
+  /// The JavaScript names for members implemented via typed JavaScript
+  /// interop.
+  @override
+  Map<MemberEntity, String> get jsInteropMembers =>
+      _nativeBasicData.jsInteropMembers;
+
   @override
   bool isAnonymousJsInteropClass(ClassEntity element) {
     return anonymousJsInteropClasses.contains(element);
   }
 
   /// Returns `true` if [cls] is a native class.
+  @override
   bool isNativeClass(ClassEntity element) =>
       _nativeBasicData.isNativeClass(element);
 
   /// Returns the list of non-directive native tag words for [cls].
+  @override
   List<String> getNativeTagsOfClass(ClassEntity cls) =>
       _nativeBasicData.getNativeTagsOfClass(cls);
 
   /// Returns `true` if [cls] has a `!nonleaf` tag word.
+  @override
   bool hasNativeTagsForcedNonLeaf(ClassEntity cls) =>
       _nativeBasicData.hasNativeTagsForcedNonLeaf(cls);
 
+  @override
   bool get isJsInteropUsed => _nativeBasicData.isJsInteropUsed;
 
   /// Returns `true` if [element] is a JsInterop library.
+  @override
   bool isJsInteropLibrary(LibraryEntity element) =>
       _nativeBasicData.isJsInteropLibrary(element);
 
   /// Returns `true` if [element] is a JsInterop class.
+  @override
   bool isJsInteropClass(ClassEntity element) =>
       _nativeBasicData.isJsInteropClass(element);
 
   /// Returns `true` if [element] or any of its superclasses is native.
+  @override
   bool isNativeOrExtendsNative(ClassEntity element) =>
       _nativeBasicData.isNativeOrExtendsNative(element);
 
   /// Returns the explicit js interop name for library [element].
+  @override
   String getJsInteropLibraryName(LibraryEntity element) {
     return jsInteropLibraries[element];
   }
 
   /// Returns the explicit js interop name for class [element].
+  @override
   String getJsInteropClassName(ClassEntity element) {
     return jsInteropClasses[element];
   }
 
   /// Returns the explicit js interop name for member [element].
+  @override
   String getJsInteropMemberName(MemberEntity element) {
     return jsInteropMembers[element];
   }
 
   /// Returns `true` if [element] is explicitly marked as part of JsInterop.
+  @override
   bool _isJsInteropMember(MemberEntity element) {
     return jsInteropMembers.containsKey(element);
   }
 
   /// Returns `true` if [element] is a JsInterop method.
+  @override
   bool isJsInteropMember(MemberEntity element) {
     if (element.isFunction ||
         element.isConstructor ||
@@ -723,12 +654,14 @@
 
   /// Returns `true` if the name of [element] is fixed for the generated
   /// JavaScript.
+  @override
   bool hasFixedBackendName(MemberEntity element) {
     return isJsInteropMember(element) || nativeMemberName.containsKey(element);
   }
 
   /// Computes the name for [element] to use in the generated JavaScript. This
   /// is either given through a native annotation or a js interop annotation.
+  @override
   String getFixedBackendName(MemberEntity element) {
     String name = nativeMemberName[element];
     if (name == null && isJsInteropMember(element)) {
@@ -774,6 +707,7 @@
   /// For example: fixedBackendPath for the static method createMap in the
   /// Map class of the goog.map JavaScript library would have path
   /// "goog.maps.Map".
+  @override
   String getFixedBackendMethodPath(FunctionEntity element) {
     if (!isJsInteropMember(element)) return null;
     if (element.isInstanceMember) return 'this';
@@ -794,12 +728,14 @@
   }
 
   /// Returns `true` if [element] is a native member of a native class.
+  @override
   bool isNativeMember(MemberEntity element) {
     if (isJsInteropMember(element)) return true;
     return nativeMemberName.containsKey(element);
   }
 
   /// Returns the [NativeBehavior] for calling the native [method].
+  @override
   NativeBehavior getNativeMethodBehavior(FunctionEntity method) {
     assert(
         nativeMethodBehavior.containsKey(method),
@@ -809,6 +745,7 @@
   }
 
   /// Returns the [NativeBehavior] for reading from the native [field].
+  @override
   NativeBehavior getNativeFieldLoadBehavior(FieldEntity field) {
     assert(
         nativeFieldLoadBehavior.containsKey(field),
@@ -820,6 +757,7 @@
   }
 
   /// Returns the [NativeBehavior] for writing to the native [field].
+  @override
   NativeBehavior getNativeFieldStoreBehavior(FieldEntity field) {
     assert(
         nativeFieldStoreBehavior.containsKey(field),
@@ -830,6 +768,7 @@
 
   /// Apply JS$ escaping scheme to convert possible escaped Dart names into
   /// JS names.
+  @override
   String computeUnescapedJSInteropName(String name) {
     return name.startsWith(_jsInteropEscapePrefix)
         ? name.substring(_jsInteropEscapePrefix.length)
@@ -869,13 +808,16 @@
     return sb.toString();
   }
 
+  @override
   int get hashCode => Hashing.listHash(names, isNonLeaf.hashCode);
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! NativeClassTag) return false;
     return equalElements(names, other.names) && isNonLeaf == other.isNonLeaf;
   }
 
+  @override
   String toString() => text;
 }
diff --git a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
index 3dc3075..b579c07 100644
--- a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
+++ b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
@@ -94,13 +94,17 @@
 
   NoSuchMethodResolver get internalResolverForTesting => _resolver;
 
+  @override
   bool get hasThrowingNoSuchMethod => throwingImpls.isNotEmpty;
+  @override
   bool get hasComplexNoSuchMethod => otherImpls.isNotEmpty;
 
+  @override
   void registerNoSuchMethod(FunctionEntity noSuchMethodElement) {
     _uncategorizedImpls.add(noSuchMethodElement);
   }
 
+  @override
   void onQueueEmpty() {
     _uncategorizedImpls.forEach(_categorizeImpl);
     _uncategorizedImpls.clear();
@@ -161,6 +165,7 @@
     }
   }
 
+  @override
   NoSuchMethodData close() {
     return new NoSuchMethodDataImpl(
         throwingImpls, otherImpls, forwardingSyntaxImpls);
@@ -234,6 +239,7 @@
       ..complexReturningImpls.addAll(complexReturningImpls);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
     sink.writeMembers(throwingImpls);
@@ -247,6 +253,7 @@
   /// Now that type inference is complete, split category D into two
   /// subcategories: D1, those that have no return type, and D2, those
   /// that have a return type.
+  @override
   void categorizeComplexImplementations(GlobalTypeInferenceResults results) {
     otherImpls.forEach((FunctionEntity element) {
       if (results.resultOfMember(element).throwsAlways) {
@@ -258,6 +265,7 @@
   }
 
   /// Emits a diagnostic
+  @override
   void emitDiagnostic(DiagnosticReporter reporter) {
     throwingImpls.forEach((e) {
       if (!forwardingSyntaxImpls.contains(e)) {
@@ -279,6 +287,7 @@
   /// Returns [true] if the given element is a complex [noSuchMethod]
   /// implementation. An implementation is complex if it falls into
   /// category D, as described above.
+  @override
   bool isComplex(FunctionEntity element) {
     assert(element.name == Identifiers.noSuchMethod_);
     return otherImpls.contains(element);
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 382475a..e5132c6 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -124,6 +124,7 @@
 class TrivialRuntimeTypesNeed implements RuntimeTypesNeed {
   const TrivialRuntimeTypesNeed();
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeBool(true); // Is trivial.
   }
@@ -244,6 +245,7 @@
 class TrivialRuntimeTypesChecksBuilder implements RuntimeTypesChecksBuilder {
   final JClosedWorld _closedWorld;
   final TrivialRuntimeTypesSubstitutions _substitutions;
+  @override
   bool rtiChecksBuilderClosed = false;
 
   TrivialRuntimeTypesChecksBuilder(this._closedWorld, this._substitutions);
@@ -299,6 +301,7 @@
 
   ClassCollector(this._elementEnvironment);
 
+  @override
   void addClass(ClassEntity cls) {
     if (classes.add(cls)) {
       _elementEnvironment.forEachSupertype(cls, (InterfaceType type) {
@@ -633,7 +636,9 @@
 }
 
 class TrivialRuntimeTypesSubstitutions extends RuntimeTypesSubstitutionsMixin {
+  @override
   final JClosedWorld _closedWorld;
+  @override
   TypeChecks _requiredChecks;
 
   TrivialRuntimeTypesSubstitutions(this._closedWorld);
@@ -786,6 +791,7 @@
         instantiationsNeedingTypeArguments);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeBool(false); // Is _not_ trivial.
     sink.begin(tag);
@@ -802,16 +808,19 @@
 
   bool checkClass(covariant ClassEntity cls) => true;
 
+  @override
   bool classNeedsTypeArguments(ClassEntity cls) {
     assert(checkClass(cls));
     if (!_elementEnvironment.isGenericClass(cls)) return false;
     return classesNeedingTypeArguments.contains(cls);
   }
 
+  @override
   bool methodNeedsSignature(FunctionEntity function) {
     return methodsNeedingSignature.contains(function);
   }
 
+  @override
   bool methodNeedsTypeArguments(FunctionEntity function) {
     return methodsNeedingTypeArguments.contains(function);
   }
@@ -1398,6 +1407,7 @@
 
   String get kind;
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write(kind);
@@ -1412,8 +1422,10 @@
 
   ClassNode(this.cls);
 
+  @override
   Entity get entity => cls;
 
+  @override
   String get kind => 'class';
 }
 
@@ -1427,6 +1439,7 @@
   MethodNode(this.function, this.parameterStructure,
       {this.isCallTarget, this.instanceName, this.isNoSuchMethod: false});
 
+  @override
   Entity get entity => function;
 
   bool selectorApplies(Selector selector) {
@@ -1436,8 +1449,10 @@
         selector.callStructure.signatureApplies(parameterStructure);
   }
 
+  @override
   String get kind => 'method';
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('MethodNode(');
@@ -1892,6 +1907,7 @@
 
 class _RuntimeTypesChecks implements RuntimeTypesChecks {
   final RuntimeTypesSubstitutions _substitutions;
+  @override
   final TypeChecks requiredChecks;
   final Iterable<ClassEntity> _typeLiterals;
   final Iterable<ClassEntity> _typeArguments;
@@ -1920,6 +1936,7 @@
 class RuntimeTypesImpl extends _RuntimeTypesBase
     with RuntimeTypesSubstitutionsMixin
     implements RuntimeTypesChecksBuilder {
+  @override
   final JClosedWorld _closedWorld;
 
   // The set of type arguments tested against type variable bounds.
@@ -1929,13 +1946,16 @@
 
   TypeChecks cachedRequiredChecks;
 
+  @override
   bool rtiChecksBuilderClosed = false;
 
   RuntimeTypesImpl(this._closedWorld) : super(_closedWorld.dartTypes);
 
   JCommonElements get _commonElements => _closedWorld.commonElements;
+  @override
   JElementEnvironment get _elementEnvironment =>
       _closedWorld.elementEnvironment;
+  @override
   RuntimeTypesNeed get _rtiNeed => _closedWorld.rtiNeed;
 
   @override
@@ -1958,6 +1978,7 @@
     _genericInstantiations.add(instantiation);
   }
 
+  @override
   RuntimeTypesChecks computeRequiredChecks(
       CodegenWorldBuilder codegenWorldBuilder, CompilerOptions options) {
     TypeVariableTests typeVariableTests = new TypeVariableTests(
@@ -1979,14 +2000,32 @@
     Set<ClassEntity> typeLiterals = new Set<ClassEntity>();
     Set<ClassEntity> typeArguments = new Set<ClassEntity>();
 
+    // The [liveTypeVisitor] is used to register class use in the type of
+    // instantiated objects like `new T` and the function types of
+    // tear offs and closures.
+    //
+    // A type found in a covariant position of such types is considered live
+    // whereas a type found in a contravariant position of such types is
+    // considered tested.
+    //
+    // For instance
+    //
+    //    new A<B Function(C)>();
+    //
+    // makes A and B live but C tested.
     TypeVisitor liveTypeVisitor =
         new TypeVisitor(onClass: (ClassEntity cls, {TypeVisitorState state}) {
       ClassUse classUse = classUseMap.putIfAbsent(cls, () => new ClassUse());
       switch (state) {
-        case TypeVisitorState.typeArgument:
+        case TypeVisitorState.covariantTypeArgument:
           classUse.typeArgument = true;
           typeArguments.add(cls);
           break;
+        case TypeVisitorState.contravariantTypeArgument:
+          classUse.typeArgument = true;
+          classUse.checkedTypeArgument = true;
+          typeArguments.add(cls);
+          break;
         case TypeVisitorState.typeLiteral:
           classUse.typeLiteral = true;
           typeLiterals.add(cls);
@@ -1996,15 +2035,31 @@
       }
     });
 
+    // The [testedTypeVisitor] is used to register class use in type tests like
+    // `o is T` and `o as T` (both implicit and explicit).
+    //
+    // A type found in a covariant position of such types is considered tested
+    // whereas a type found in a contravariant position of such types is
+    // considered live.
+    //
+    // For instance
+    //
+    //    o is A<B Function(C)>;
+    //
+    // makes A and B tested but C live.
     TypeVisitor testedTypeVisitor =
         new TypeVisitor(onClass: (ClassEntity cls, {TypeVisitorState state}) {
       ClassUse classUse = classUseMap.putIfAbsent(cls, () => new ClassUse());
       switch (state) {
-        case TypeVisitorState.typeArgument:
+        case TypeVisitorState.covariantTypeArgument:
           classUse.typeArgument = true;
           classUse.checkedTypeArgument = true;
           typeArguments.add(cls);
           break;
+        case TypeVisitorState.contravariantTypeArgument:
+          classUse.typeArgument = true;
+          typeArguments.add(cls);
+          break;
         case TypeVisitorState.typeLiteral:
           break;
         case TypeVisitorState.direct:
@@ -2025,31 +2080,32 @@
       classUse.directInstance = true;
       FunctionType callType = _types.getCallType(type);
       if (callType != null) {
-        testedTypeVisitor.visitType(callType, TypeVisitorState.direct);
+        liveTypeVisitor.visitType(callType, TypeVisitorState.direct);
       }
     });
 
     for (FunctionEntity element
         in codegenWorldBuilder.staticFunctionsNeedingGetter) {
       FunctionType functionType = _elementEnvironment.getFunctionType(element);
-      testedTypeVisitor.visitType(functionType, TypeVisitorState.direct);
+      liveTypeVisitor.visitType(functionType, TypeVisitorState.direct);
     }
 
     for (FunctionEntity element in codegenWorldBuilder.closurizedMembers) {
       FunctionType functionType = _elementEnvironment.getFunctionType(element);
-      testedTypeVisitor.visitType(functionType, TypeVisitorState.direct);
+      liveTypeVisitor.visitType(functionType, TypeVisitorState.direct);
     }
 
     void processMethodTypeArguments(_, Set<DartType> typeArguments) {
       for (DartType typeArgument in typeArguments) {
-        liveTypeVisitor.visit(typeArgument, TypeVisitorState.typeArgument);
+        liveTypeVisitor.visit(
+            typeArgument, TypeVisitorState.covariantTypeArgument);
       }
     }
 
     codegenWorldBuilder.forEachStaticTypeArgument(processMethodTypeArguments);
     codegenWorldBuilder.forEachDynamicTypeArgument(processMethodTypeArguments);
     codegenWorldBuilder.liveTypeArguments.forEach((DartType type) {
-      liveTypeVisitor.visitType(type, TypeVisitorState.typeArgument);
+      liveTypeVisitor.visitType(type, TypeVisitorState.covariantTypeArgument);
     });
     codegenWorldBuilder.constTypeLiterals.forEach((DartType type) {
       liveTypeVisitor.visitType(type, TypeVisitorState.typeLiteral);
@@ -2102,7 +2158,8 @@
             DartType bound =
                 _elementEnvironment.getTypeVariableBound(typeVariable.element);
             processCheckedType(bound);
-            liveTypeVisitor.visit(bound, TypeVisitorState.typeArgument);
+            liveTypeVisitor.visit(
+                bound, TypeVisitorState.covariantTypeArgument);
           }
         }
       }
@@ -2412,6 +2469,7 @@
   jsAst.Expression visit(DartType type, Emitter emitter) =>
       type.accept(this, emitter);
 
+  @override
   jsAst.Expression visitTypeVariableType(
       TypeVariableType type, Emitter emitter) {
     if (typedefBindings != null) {
@@ -2421,6 +2479,7 @@
     return onVariable(type);
   }
 
+  @override
   jsAst.Expression visitFunctionTypeVariable(
       FunctionTypeVariable type, Emitter emitter) {
     int position = functionTypeVariables.indexOf(type);
@@ -2428,6 +2487,7 @@
     return js.number(functionTypeVariables.length - position - 1);
   }
 
+  @override
   jsAst.Expression visitDynamicType(DynamicType type, Emitter emitter) {
     return getDynamicValue();
   }
@@ -2444,6 +2504,7 @@
     return new jsAst.ArrayInitializer(elements);
   }
 
+  @override
   jsAst.Expression visitInterfaceType(InterfaceType type, Emitter emitter) {
     jsAst.Expression name = getJavaScriptClassName(type.element, emitter);
     jsAst.Expression result;
@@ -2508,6 +2569,7 @@
     return jsAst.js.expressionTemplateFor("# === -2");
   }
 
+  @override
   jsAst.Expression visitFunctionType(FunctionType type, Emitter emitter) {
     List<jsAst.Property> properties = <jsAst.Property>[];
 
@@ -2566,10 +2628,12 @@
     return new jsAst.ObjectInitializer(properties);
   }
 
+  @override
   jsAst.Expression visitVoidType(VoidType type, Emitter emitter) {
     return getVoidValue();
   }
 
+  @override
   jsAst.Expression visitTypedefType(TypedefType type, Emitter emitter) {
     bool shouldEncode = shouldEncodeTypedef(type);
     DartType unaliasedType = type.unaliased;
@@ -2646,6 +2710,7 @@
 class TypeCheckMapping implements TypeChecks {
   final Map<ClassEntity, ClassChecks> map = new Map<ClassEntity, ClassChecks>();
 
+  @override
   ClassChecks operator [](ClassEntity element) {
     ClassChecks result = map[element];
     return result != null ? result : const ClassChecks.empty();
@@ -2655,8 +2720,10 @@
     map[element] = checks;
   }
 
+  @override
   Iterable<ClassEntity> get classes => map.keys;
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     for (ClassEntity holder in classes) {
@@ -2687,15 +2754,18 @@
     }
   }
 
+  @override
   visitTypedefType(TypedefType type, bool isTypeArgument) {
     collect(type.unaliased, isTypeArgument: isTypeArgument);
   }
 
+  @override
   visitInterfaceType(InterfaceType type, bool isTypeArgument) {
     if (isTypeArgument) addClass(type.element);
     collectAll(type.typeArguments, isTypeArgument: true);
   }
 
+  @override
   visitFunctionType(FunctionType type, _) {
     collect(type.returnType, isTypeArgument: true);
     collectAll(type.parameterTypes, isTypeArgument: true);
@@ -2719,10 +2789,12 @@
     }
   }
 
+  @override
   visitTypedefType(TypedefType type, bool inFunctionType) {
     collect(type.unaliased, inFunctionType: inFunctionType);
   }
 
+  @override
   visitInterfaceType(InterfaceType type, bool inFunctionType) {
     if (inFunctionType) {
       classes.add(type.element);
@@ -2730,6 +2802,7 @@
     collectAll(type.typeArguments, inFunctionType: inFunctionType);
   }
 
+  @override
   visitFunctionType(FunctionType type, _) {
     collect(type.returnType, inFunctionType: true);
     collectAll(type.parameterTypes, inFunctionType: true);
@@ -2780,6 +2853,7 @@
 
   bool get isJsInterop => length != null;
 
+  @override
   String toString() => 'Substitution(isTrivial=$isTrivial,'
       'isFunction=$isFunction,isJsInterop=$isJsInterop,arguments=$arguments,'
       'parameters=$parameters,length=$length)';
@@ -2791,16 +2865,23 @@
   final ClassEntity cls;
   final bool needsIs;
   final Substitution substitution;
+  @override
   final int hashCode = _nextHash = (_nextHash + 100003).toUnsigned(30);
   static int _nextHash = 0;
 
   TypeCheck(this.cls, this.substitution, {this.needsIs: true});
 
+  @override
   String toString() =>
       'TypeCheck(cls=$cls,needsIs=$needsIs,substitution=$substitution)';
 }
 
-enum TypeVisitorState { direct, typeArgument, typeLiteral }
+enum TypeVisitorState {
+  direct,
+  covariantTypeArgument,
+  contravariantTypeArgument,
+  typeLiteral,
+}
 
 class TypeVisitor extends DartTypeVisitor<void, TypeVisitorState> {
   Set<FunctionTypeVariable> _visitedFunctionTypeVariables =
@@ -2816,6 +2897,34 @@
 
   visitType(DartType type, TypeVisitorState state) => type.accept(this, state);
 
+  TypeVisitorState covariantArgument(TypeVisitorState state) {
+    switch (state) {
+      case TypeVisitorState.direct:
+        return TypeVisitorState.covariantTypeArgument;
+      case TypeVisitorState.covariantTypeArgument:
+        return TypeVisitorState.covariantTypeArgument;
+      case TypeVisitorState.contravariantTypeArgument:
+        return TypeVisitorState.contravariantTypeArgument;
+      case TypeVisitorState.typeLiteral:
+        return TypeVisitorState.typeLiteral;
+    }
+    throw new UnsupportedError("Unexpected TypeVisitorState $state");
+  }
+
+  TypeVisitorState contravariantArgument(TypeVisitorState state) {
+    switch (state) {
+      case TypeVisitorState.direct:
+        return TypeVisitorState.contravariantTypeArgument;
+      case TypeVisitorState.covariantTypeArgument:
+        return TypeVisitorState.contravariantTypeArgument;
+      case TypeVisitorState.contravariantTypeArgument:
+        return TypeVisitorState.covariantTypeArgument;
+      case TypeVisitorState.typeLiteral:
+        return TypeVisitorState.typeLiteral;
+    }
+    throw new UnsupportedError("Unexpected TypeVisitorState $state");
+  }
+
   visitTypes(List<DartType> types, TypeVisitorState state) {
     for (DartType type in types) {
       visitType(type, state);
@@ -2834,11 +2943,7 @@
     if (onClass != null) {
       onClass(type.element, state: state);
     }
-    visitTypes(
-        type.typeArguments,
-        state == TypeVisitorState.typeLiteral
-            ? state
-            : TypeVisitorState.typeArgument);
+    visitTypes(type.typeArguments, covariantArgument(state));
   }
 
   @override
@@ -2848,13 +2953,10 @@
     }
     // Visit all nested types as type arguments; these types are not runtime
     // instances but runtime type representations.
-    state = state == TypeVisitorState.typeLiteral
-        ? state
-        : TypeVisitorState.typeArgument;
-    visitType(type.returnType, state);
-    visitTypes(type.parameterTypes, state);
-    visitTypes(type.optionalParameterTypes, state);
-    visitTypes(type.namedParameterTypes, state);
+    visitType(type.returnType, covariantArgument(state));
+    visitTypes(type.parameterTypes, contravariantArgument(state));
+    visitTypes(type.optionalParameterTypes, contravariantArgument(state));
+    visitTypes(type.namedParameterTypes, contravariantArgument(state));
     _visitedFunctionTypeVariables.removeAll(type.typeVariables);
   }
 
@@ -2891,6 +2993,7 @@
 
   Iterable<TypeCheck> get checks => _map.values;
 
+  @override
   String toString() {
     return 'ClassChecks($checks)';
   }
@@ -2985,6 +3088,7 @@
   /// type arguments.
   bool get isLive => directInstance || typeArgument;
 
+  @override
   String toString() {
     List<String> properties = <String>[];
     if (instance) {
diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
index fb31e92..81b9f9e 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -9,6 +9,7 @@
 import '../elements/entities.dart';
 import '../js/js.dart' as jsAst;
 import '../js/js.dart' show js;
+import '../js_backend/field_analysis.dart';
 import '../js_backend/namer.dart' show Namer;
 import '../js_backend/interceptor_data.dart' show InterceptorData;
 import '../options.dart';
@@ -108,8 +109,14 @@
         }
         return js('#.#()', [receiver, getterName]);
       } else {
-        jsAst.Name fieldName = _namer.instanceFieldPropertyName(member);
-        return js('#.#', [receiver, fieldName]);
+        FieldAnalysisData fieldData =
+            _closedWorld.fieldAnalysis.getFieldData(member);
+        if (fieldData.isEffectivelyConstant) {
+          return _emitter.constantReference(fieldData.constantValue);
+        } else {
+          jsAst.Name fieldName = _namer.instanceFieldPropertyName(member);
+          return js('#.#', [receiver, fieldName]);
+        }
       }
     }
 
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index 987d957..0320701 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -67,6 +67,7 @@
     return _emitter;
   }
 
+  @override
   String get name => 'Code emitter';
 
   /// Returns true, if the emitter supports reflection.
@@ -268,6 +269,7 @@
 }
 
 abstract class EmitterBase implements Emitter {
+  @override
   Program programForTesting;
   Namer get namer;
 
diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
index 9b4aed2..9306361 100644
--- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
+++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
@@ -27,6 +27,7 @@
     _dartTypeOrdering = new _DartTypeOrdering(this);
   }
 
+  @override
   int compare(ConstantValue a, ConstantValue b) => compareValues(a, b);
 
   int compareValues(ConstantValue a, ConstantValue b) {
@@ -75,38 +76,46 @@
     return _dartTypeOrdering.compare(a, b);
   }
 
+  @override
   int visitFunction(FunctionConstantValue a, FunctionConstantValue b) {
     return compareMembers(a.element, b.element);
   }
 
+  @override
   int visitNull(NullConstantValue a, NullConstantValue b) {
     return 0;
   }
 
+  @override
   int visitNonConstant(NonConstantValue a, NonConstantValue b) {
     return 0;
   }
 
+  @override
   int visitInt(IntConstantValue a, IntConstantValue b) {
     return a.intValue.compareTo(b.intValue);
   }
 
+  @override
   int visitDouble(DoubleConstantValue a, DoubleConstantValue b) {
     return a.doubleValue.compareTo(b.doubleValue);
   }
 
+  @override
   int visitBool(BoolConstantValue a, BoolConstantValue b) {
     int aInt = a.boolValue ? 1 : 0;
     int bInt = b.boolValue ? 1 : 0;
     return aInt.compareTo(bInt);
   }
 
+  @override
   int visitString(StringConstantValue a, StringConstantValue b) {
     String aString = a.stringValue;
     String bString = b.stringValue;
     return aString.compareTo(bString);
   }
 
+  @override
   int visitList(ListConstantValue a, ListConstantValue b) {
     int r = compareLists(compareValues, a.entries, b.entries);
     if (r != 0) return r;
@@ -120,6 +129,7 @@
     return compareDartTypes(a.type, b.type);
   }
 
+  @override
   int visitMap(MapConstantValue a, MapConstantValue b) {
     int r = compareLists(compareValues, a.keys, b.keys);
     if (r != 0) return r;
@@ -128,6 +138,7 @@
     return compareDartTypes(a.type, b.type);
   }
 
+  @override
   int visitConstructed(ConstructedConstantValue a, ConstructedConstantValue b) {
     int r = compareDartTypes(a.type, b.type);
     if (r != 0) return r;
@@ -145,16 +156,19 @@
         aFields.map((field) => b.fields[field]).toList());
   }
 
+  @override
   int visitType(TypeConstantValue a, TypeConstantValue b) {
     int r = compareDartTypes(a.representedType, b.representedType);
     if (r != 0) return r;
     return compareDartTypes(a.type, b.type);
   }
 
+  @override
   int visitInterceptor(InterceptorConstantValue a, InterceptorConstantValue b) {
     return compareClasses(a.cls, b.cls);
   }
 
+  @override
   int visitSynthetic(SyntheticConstantValue a, SyntheticConstantValue b) {
     // [SyntheticConstantValue]s have abstract fields that are set only by
     // convention.  Lucky for us, they do not occur as top level constant, only
@@ -183,6 +197,7 @@
     }
   }
 
+  @override
   int visitDeferredGlobal(
       DeferredGlobalConstantValue a, DeferredGlobalConstantValue b) {
     int r = compareValues(a.referenced, b.referenced);
@@ -190,6 +205,7 @@
     return a.unit.compareTo(b.unit);
   }
 
+  @override
   int visitInstantiation(
       InstantiationConstantValue a, InstantiationConstantValue b) {
     int r = compareValues(a.function, b.function);
@@ -221,21 +237,37 @@
   static int kind(ConstantValue constant) =>
       constant.accept(const _KindVisitor(), null);
 
+  @override
   int visitFunction(FunctionConstantValue a, _) => FUNCTION;
+  @override
   int visitNull(NullConstantValue a, _) => NULL;
+  @override
   int visitNonConstant(NonConstantValue a, _) => NONCONSTANT;
+  @override
   int visitInt(IntConstantValue a, _) => INT;
+  @override
   int visitDouble(DoubleConstantValue a, _) => DOUBLE;
+  @override
   int visitBool(BoolConstantValue a, _) => BOOL;
+  @override
   int visitString(StringConstantValue a, _) => STRING;
+  @override
   int visitList(ListConstantValue a, _) => LIST;
+  @override
   int visitSet(SetConstantValue a, _) => SET;
+  @override
   int visitMap(MapConstantValue a, _) => MAP;
+  @override
   int visitConstructed(ConstructedConstantValue a, _) => CONSTRUCTED;
+  @override
   int visitType(TypeConstantValue a, _) => TYPE;
+  @override
   int visitInterceptor(InterceptorConstantValue a, _) => INTERCEPTOR;
+  @override
   int visitSynthetic(SyntheticConstantValue a, _) => SYNTHETIC;
+  @override
   int visitDeferredGlobal(DeferredGlobalConstantValue a, _) => DEFERRED_GLOBAL;
+  @override
   int visitInstantiation(InstantiationConstantValue a, _) => INSTANTIATION;
 }
 
@@ -247,11 +279,17 @@
     return type.accept(const _DartTypeKindVisitor(), null);
   }
 
+  @override
   int visitVoidType(covariant VoidType type, _) => 6;
+  @override
   int visitTypeVariableType(covariant TypeVariableType type, _) => 3;
+  @override
   int visitFunctionType(covariant FunctionType type, _) => 0;
+  @override
   int visitInterfaceType(covariant InterfaceType type, _) => 1;
+  @override
   int visitTypedefType(covariant TypedefType type, _) => 2;
+  @override
   int visitDynamicType(covariant DynamicType type, _) => 5;
 }
 
@@ -271,16 +309,19 @@
     return r;
   }
 
+  @override
   int visitVoidType(covariant VoidType type, covariant VoidType other) {
     throw new UnsupportedError('Unreachable');
   }
 
+  @override
   int visitTypeVariableType(
       covariant TypeVariableType type, covariant TypeVariableType other) {
     throw new UnsupportedError(
         "Type variables are not expected in constants: '$type' in '$_root'");
   }
 
+  @override
   int visitFunctionType(
       covariant FunctionType type, covariant FunctionType other) {
     int r = _compareTypeArguments(type.parameterTypes, other.parameterTypes);
@@ -297,6 +338,7 @@
     return compare(type.returnType, other.returnType);
   }
 
+  @override
   int visitInterfaceType(
       covariant InterfaceType type, covariant InterfaceType other) {
     int r = _constantOrdering.compareClasses(type.element, other.element);
@@ -304,6 +346,7 @@
     return _compareTypeArguments(type.typeArguments, other.typeArguments);
   }
 
+  @override
   int visitTypedefType(
       covariant TypedefType type, covariant TypedefType other) {
     int r = _constantOrdering.compareTypedefs(type.element, other.element);
@@ -311,6 +354,7 @@
     return _compareTypeArguments(type.typeArguments, other.typeArguments);
   }
 
+  @override
   int visitDynamicType(
       covariant DynamicType type, covariant DynamicType other) {
     throw new UnsupportedError('Unreachable');
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index db2d3c0..39b2574 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -29,18 +29,22 @@
 abstract class _MetadataEntry extends jsAst.DeferredNumber
     implements Comparable, jsAst.ReferenceCountedAstNode {
   jsAst.Expression get entry;
+  @override
   int get value;
   int get _rc;
 
   // Mark this entry as seen. On the first time this is seen, the visitor
   // will be applied to the [entry] to also mark potential [_MetadataEntry]
   // instances in the [entry] as seen.
+  @override
   markSeen(jsAst.TokenCounter visitor);
 }
 
 class _BoundMetadataEntry extends _MetadataEntry {
   int _value = -1;
+  @override
   int _rc = 0;
+  @override
   final jsAst.Expression entry;
 
   _BoundMetadataEntry(this.entry);
@@ -52,6 +56,7 @@
     _value = value;
   }
 
+  @override
   int get value {
     assert(isFinalized);
     return _value;
@@ -59,13 +64,16 @@
 
   bool get isUsed => _rc > 0;
 
+  @override
   markSeen(jsAst.BaseVisitor visitor) {
     _rc++;
     if (_rc == 1) entry.accept(visitor);
   }
 
+  @override
   int compareTo(covariant _MetadataEntry other) => other._rc - this._rc;
 
+  @override
   String toString() => '_BoundMetadataEntry($hashCode,rc=$_rc,_value=$_value)';
 }
 
@@ -78,11 +86,13 @@
     _value = value;
   }
 
+  @override
   jsAst.Expression get value {
     assert(_value != null);
     return _value;
   }
 
+  @override
   int get precedenceLevel => js_precedence.PRIMARY;
 }
 
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index 6f7b580..247a1ef 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -83,6 +83,7 @@
   Holder(this.name, this.index,
       {this.isStaticStateHolder: false, this.isConstantsHolder: false});
 
+  @override
   String toString() {
     return 'Holder(name=${name})';
   }
@@ -136,8 +137,10 @@
       : super(outputUnit, outputFileName, libraries, staticNonFinalFields,
             staticLazilyInitializedFields, constants);
 
+  @override
   bool get isMainFragment => true;
 
+  @override
   String toString() {
     return 'MainFragment()';
   }
@@ -158,8 +161,10 @@
       : super(outputUnit, outputFileName, libraries, staticNonFinalFields,
             staticLazilyInitializedFields, constants);
 
+  @override
   bool get isMainFragment => false;
 
+  @override
   String toString() {
     return 'DeferredFragment(name=${name})';
   }
@@ -172,6 +177,7 @@
 
   Constant(this.name, this.holder, this.value);
 
+  @override
   String toString() {
     return 'Constant(name=${name.key},value=${value.toStructuredText()})';
   }
@@ -190,11 +196,13 @@
   final List<StaticMethod> statics;
   final List<Class> classes;
 
+  @override
   final List<Field> staticFieldsForReflection;
 
   Library(this.element, this.uri, this.statics, this.classes,
       this.staticFieldsForReflection);
 
+  @override
   String toString() {
     return 'Library(uri=${uri},element=${element})';
   }
@@ -213,10 +221,12 @@
   final js.Expression code;
   final bool isFinal;
   final bool isLazy;
+  final bool isInitializedByConstant;
 
   StaticField(this.element, this.name, this.getterName, this.holder, this.code,
-      this.isFinal, this.isLazy);
+      {this.isFinal, this.isLazy, this.isInitializedByConstant: false});
 
+  @override
   String toString() {
     return 'StaticField(name=${name.key},element=${element})';
   }
@@ -241,6 +251,7 @@
 
   /// noSuchMethod stubs in the special case that the class is Object.
   final List<StubMethod> noSuchMethodStubs;
+  @override
   final List<Field> staticFieldsForReflection;
   final bool hasRtiField; // Per-instance runtime type information pseudo-field.
   final bool onlyForRti;
@@ -315,6 +326,7 @@
   int get superclassHolderIndex =>
       (superclass == null) ? 0 : superclass.holder.index;
 
+  @override
   String toString() => 'Class(name=${name.key},element=$element)';
 }
 
@@ -351,8 +363,10 @@
             isClosureBaseClass: false,
             isSuperMixinApplication: false);
 
+  @override
   bool get isSimpleMixinApplication => true;
 
+  @override
   String toString() => 'Mixin(name=${name.key},element=$element)';
 }
 
@@ -412,6 +426,7 @@
   bool get needsInterceptedGetterOnThis => getterFlags == 3;
   bool get needsInterceptedSetterOnThis => setterFlags == 3;
 
+  @override
   String toString() {
     return 'Field(name=${name.key},element=${element})';
   }
@@ -519,8 +534,10 @@
     assert(isClosureCallMethod != null);
   }
 
+  @override
   bool get isStatic => false;
 
+  @override
   String toString() {
     return 'InstanceMethod(name=${name.key},element=${element}'
         ',code=${js.nodeToString(code)})';
@@ -534,6 +551,7 @@
   StubMethod(js.Name name, js.Expression code, {MemberEntity element})
       : super(element, name, code);
 
+  @override
   String toString() {
     return 'StubMethod(name=${name.key},element=${element}'
         ',code=${js.nodeToString(code)})';
@@ -561,6 +579,7 @@
       {MemberEntity element})
       : super(name, code, element: element);
 
+  @override
   String toString() {
     return 'ParameterStubMethod(name=${name.key}, callName=${callName?.key}'
         ', element=${element}'
@@ -573,6 +592,7 @@
 }
 
 class StaticDartMethod extends DartMethod implements StaticMethod {
+  @override
   final Holder holder;
 
   StaticDartMethod(
@@ -598,8 +618,10 @@
             functionType: functionType,
             applyIndex: applyIndex);
 
+  @override
   bool get isStatic => true;
 
+  @override
   String toString() {
     return 'StaticDartMethod(name=${name.key},element=${element}'
         ',code=${js.nodeToString(code)})';
@@ -607,10 +629,12 @@
 }
 
 class StaticStubMethod extends StubMethod implements StaticMethod {
+  @override
   Holder holder;
   StaticStubMethod(js.Name name, this.holder, js.Expression code)
       : super(name, code);
 
+  @override
   String toString() {
     return 'StaticStubMethod(name=${name.key},element=${element}}'
         ',code=${js.nodeToString(code)})';
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
index d74d9c7..d0e09c8 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
@@ -263,22 +263,36 @@
   void computeNeededStaticNonFinalFields() {
     addToOutputUnit(FieldEntity element) {
       List<FieldEntity> list = outputStaticNonFinalFieldLists.putIfAbsent(
-          // ignore: UNNECESSARY_CAST
-          _outputUnitData.outputUnitForMember(element as MemberEntity),
+          _outputUnitData.outputUnitForMember(element),
           () => new List<FieldEntity>());
       list.add(element);
     }
 
-    Iterable<FieldEntity> fields =
+    List<FieldEntity> fields =
         // TODO(johnniwinther): This should be accessed from a codegen closed
         // world.
         _worldBuilder.allReferencedStaticFields.where((FieldEntity field) {
-      FieldAnalysisData fieldData =
-          _closedWorld.fieldAnalysis.getFieldData(field);
-      return !fieldData.isEffectivelyFinal && fieldData.initialValue != null;
-    });
+      return _closedWorld.fieldAnalysis.getFieldData(field).isEager;
+    }).toList();
 
-    _sorter.sortMembers(fields).forEach((MemberEntity e) => addToOutputUnit(e));
+    fields.sort((FieldEntity a, FieldEntity b) {
+      FieldAnalysisData aFieldData = _closedWorld.fieldAnalysis.getFieldData(a);
+      FieldAnalysisData bFieldData = _closedWorld.fieldAnalysis.getFieldData(b);
+      int aIndex = aFieldData.eagerCreationIndex;
+      int bIndex = bFieldData.eagerCreationIndex;
+      if (aIndex != null && bIndex != null) {
+        return aIndex.compareTo(bIndex);
+      } else if (aIndex != null) {
+        // Sort [b] before [a].
+        return 1;
+      } else if (bIndex != null) {
+        // Sort [a] before [b].
+        return -1;
+      } else {
+        return _sorter.compareMembersByLocation(a, b);
+      }
+    });
+    fields.forEach(addToOutputUnit);
   }
 
   void computeNeededLibraries() {
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 efd77cd..bbf43e4 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
@@ -409,21 +409,28 @@
   StaticField _buildStaticField(FieldEntity element) {
     FieldAnalysisData fieldData = _fieldAnalysis.getFieldData(element);
     ConstantValue initialValue = fieldData.initialValue;
-    // TODO(zarah): The holder should not be registered during building of
-    // a static field.
-    _registry.registerHolder(_namer.globalObjectForConstant(initialValue),
-        isConstantsHolder: true);
-    js.Expression code = _task.emitter.constantReference(initialValue);
+    js.Expression code;
+    if (initialValue != null) {
+      // TODO(zarah): The holder should not be registered during building of
+      // a static field.
+      _registry.registerHolder(_namer.globalObjectForConstant(initialValue),
+          isConstantsHolder: true);
+      code = _task.emitter.constantReference(initialValue);
+    } else {
+      assert(fieldData.isEager);
+      code = _generatedCode[element];
+    }
     js.Name name = _namer.globalPropertyNameForMember(element);
-    bool isFinal = false;
-    bool isLazy = false;
 
     // TODO(floitsch): we shouldn't update the registry in the middle of
     // building a static field. (Note that the static-state holder was
     // already registered earlier, and that we just call the register to get
     // the holder-instance.
-    return new StaticField(element, name, null, _registerStaticStateHolder(),
-        code, isFinal, isLazy);
+    return new StaticField(
+        element, name, null, _registerStaticStateHolder(), code,
+        isFinal: false,
+        isLazy: false,
+        isInitializedByConstant: initialValue != null);
   }
 
   List<StaticField> _buildStaticLazilyInitializedFields(
@@ -449,14 +456,13 @@
 
     js.Name name = _namer.globalPropertyNameForMember(element);
     js.Name getterName = _namer.lazyInitializerName(element);
-    bool isFinal = !element.isAssignable;
-    bool isLazy = true;
     // TODO(floitsch): we shouldn't update the registry in the middle of
     // building a static field. (Note that the static-state holder was
     // already registered earlier, and that we just call the register to get
     // the holder-instance.
-    return new StaticField(element, name, getterName,
-        _registerStaticStateHolder(), code, isFinal, isLazy);
+    return new StaticField(
+        element, name, getterName, _registerStaticStateHolder(), code,
+        isFinal: !element.isAssignable, isLazy: true);
   }
 
   List<Library> _buildLibraries(LibrariesMap librariesMap) {
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
index f6be1c1..75acab7 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -41,6 +41,7 @@
 class Emitter extends emitterTask.EmitterBase {
   final Compiler _compiler;
   final JClosedWorld _closedWorld;
+  @override
   final Namer namer;
   final ModelEmitter _emitter;
 
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index e47c77a..a1ba755 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -434,14 +434,16 @@
 
 // Instantiates all constants.
 #constants;
+
+// Emits the embedded globals. Due to type checks in eager initializers this is
+// needed before static non-final fields initializers.
+#embeddedGlobals;
+
 // Initializes the static non-final fields (with their constant values).
 #staticNonFinalFields;
 // Creates lazy getters for statics that must run initializers on first access.
 #lazyStatics;
 
-// Emits the embedded globals.
-#embeddedGlobals;
-
 // Sets up the native support.
 // Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
 #nativeSupport;
@@ -1605,8 +1607,43 @@
     //
     Iterable<js.Statement> statements = fields.map((StaticField field) {
       assert(field.holder.isStaticStateHolder);
-      js.Statement statement = js.js
-          .statement("#.# = #;", [field.holder.name, field.name, field.code]);
+      js.Statement statement;
+      if (field.isInitializedByConstant) {
+        statement = js.js
+            .statement("#.# = #;", [field.holder.name, field.name, field.code]);
+      } else {
+        // This is a bit of a hack. Field initializers are generated as a
+        // function ending with a return statement. We replace the function
+        // with the body block and replace the return statement with an
+        // assignment to the field.
+        //
+        // Since unneeded blocks are not generated in the output,
+        // the statement(s) of the initializes are inlined in the emitted code.
+        //
+        // This is a cheap way of supporting eager fields (as opposed to
+        // generating one SSA graph for all eager fields) though it does not
+        // avoid redundant declaration of local variable, for instance for
+        // type arguments.
+        js.Fun code = field.code;
+        if (code.params.isEmpty &&
+            code.body.statements.length == 1 &&
+            code.body.statements.last is js.Return) {
+          // For now we only support initializers of the form
+          //
+          //   function() { return e; }
+          //
+          // To avoid unforeseen consequences of having parameters and locals
+          // in the initializer code.
+          js.Return last = code.body.statements.last;
+          statement = js.js.statement(
+              "#.# = #;", [field.holder.name, field.name, last.value]);
+        } else {
+          // Safe fallback in the event of a field initializer with no return
+          // statement as the last statement.
+          statement = js.js
+              .statement("#.# = #();", [field.holder.name, field.name, code]);
+        }
+      }
       registerEntityAst(field.element, statement,
           library: field.element.library);
       return statement;
@@ -1957,10 +1994,12 @@
     _value = value;
   }
 
+  @override
   js.Expression get value {
     assert(_value != null);
     return _value;
   }
 
+  @override
   int get precedenceLevel => js_precedence.PRIMARY;
 }
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index 5582d45..d3295fe 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -64,6 +64,7 @@
   }
 
   /// Serializes this [ClosureData] to [sink].
+  @override
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
     sink.writeMemberMap(
@@ -430,6 +431,7 @@
   static const String tag = 'scope-info';
 
   final Iterable<Local> localsUsedInTryOrSync;
+  @override
   final Local thisLocal;
   final Map<Local, JRecordField> boxedVariables;
 
@@ -455,15 +457,18 @@
     }
   }
 
+  @override
   void forEachBoxedVariable(f(Local local, FieldEntity field)) {
     boxedVariables.forEach((Local l, JRecordField box) {
       f(l, box);
     });
   }
 
+  @override
   bool localIsUsedInTryOrSync(Local variable) =>
       localsUsedInTryOrSync.contains(variable);
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('this=$thisLocal,');
@@ -471,6 +476,7 @@
     return sb.toString();
   }
 
+  @override
   bool isBoxedVariable(Local variable) => boxedVariables.containsKey(variable);
 
   factory JsScopeInfo.readFromDataSource(DataSource source) {
@@ -502,6 +508,7 @@
   /// debugging data stream.
   static const String tag = 'captured-scope';
 
+  @override
   final Local context;
 
   JsCapturedScope.internal(
@@ -522,6 +529,7 @@
             boxedVariables.isNotEmpty ? boxedVariables.values.first.box : null,
         super.from(boxedVariables, capturedScope, localsMap, elementMap);
 
+  @override
   bool get requiresContextBox => boxedVariables.isNotEmpty;
 
   factory JsCapturedScope.readFromDataSource(DataSource source) {
@@ -555,6 +563,7 @@
   /// debugging data stream.
   static const String tag = 'captured-loop-scope';
 
+  @override
   final List<Local> boxedLoopVariables;
 
   JsCapturedLoopScope.internal(
@@ -577,6 +586,7 @@
             .toList(),
         super.from(boxedVariables, capturedScope, localsMap, elementMap);
 
+  @override
   bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty;
 
   factory JsCapturedLoopScope.readFromDataSource(DataSource source) {
@@ -615,10 +625,14 @@
   /// debugging data stream.
   static const String tag = 'closure-representation-info';
 
+  @override
   JFunction callMethod;
   JSignatureMethod signatureMethod;
+  @override
   final Local closureEntity;
+  @override
   final Local thisLocal;
+  @override
   final JClass closureClassEntity;
 
   final Map<Local, JField> localToFieldMap;
@@ -674,6 +688,7 @@
         localToFieldMap);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(ScopeInfoKind.closureRepresentationInfo);
     sink.begin(tag);
@@ -689,6 +704,7 @@
     sink.end(tag);
   }
 
+  @override
   List<Local> get createdFieldEntities => localToFieldMap.keys.toList();
 
   @override
@@ -702,13 +718,16 @@
     return null;
   }
 
+  @override
   FieldEntity get thisFieldEntity => localToFieldMap[thisLocal];
 
+  @override
   void forEachFreeVariable(f(Local variable, JField field)) {
     localToFieldMap.forEach(f);
     boxedVariables.forEach(f);
   }
 
+  @override
   bool get isClosure => true;
 }
 
@@ -728,6 +747,7 @@
     return new JClosureClass(library, name);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(JClassKind.closure);
     sink.begin(tag);
@@ -739,6 +759,7 @@
   @override
   bool get isClosure => true;
 
+  @override
   String toString() => '${jsElementPrefix}closure_class($name)';
 }
 
@@ -747,16 +768,20 @@
 
   AnonymousClosureLocal(this.closureClass);
 
+  @override
   String get name => '';
 
+  @override
   int get hashCode => closureClass.hashCode * 13;
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! AnonymousClosureLocal) return false;
     return closureClass == other.closureClass;
   }
 
+  @override
   String toString() =>
       '${jsElementPrefix}anonymous_closure_local(${closureClass.name})';
 }
@@ -766,6 +791,7 @@
   /// debugging data stream.
   static const String tag = 'closure-field';
 
+  @override
   final String declaredName;
 
   JClosureField(
@@ -894,6 +920,7 @@
     return new JRecord(library, name);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(JClassKind.record);
     sink.begin(tag);
@@ -902,8 +929,10 @@
     sink.end(tag);
   }
 
+  @override
   bool get isClosure => false;
 
+  @override
   String toString() => '${jsElementPrefix}record_container($name)';
 }
 
@@ -991,6 +1020,7 @@
   /// debugging data stream.
   static const String tag = 'closure-class-definition';
 
+  @override
   final SourceSpan location;
 
   ClosureClassDefinition(this.location);
@@ -1010,20 +1040,25 @@
     sink.end(tag);
   }
 
+  @override
   ClassKind get kind => ClassKind.closure;
 
+  @override
   ir.Node get node =>
       throw new UnsupportedError('ClosureClassDefinition.node for $location');
 
+  @override
   String toString() => 'ClosureClassDefinition(kind:$kind,location:$location)';
 }
 
 abstract class ClosureMemberData implements JMemberData {
+  @override
   final MemberDefinition definition;
   final InterfaceType memberThisType;
 
   ClosureMemberData(this.definition, this.memberThisType);
 
+  @override
   Map<ir.Expression, ir.DartType> get staticTypes {
     // The cached types are stored in the data for enclosing member.
     throw new UnsupportedError("ClosureMemberData.staticTypes");
@@ -1043,7 +1078,9 @@
   static const String tag = 'closure-function-data';
 
   final FunctionType functionType;
+  @override
   final ir.FunctionNode functionNode;
+  @override
   final ClassTypeVariableAccess classTypeVariableAccess;
 
   ClosureFunctionData(
@@ -1068,6 +1105,7 @@
         functionNode, classTypeVariableAccess);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(JMemberDataKind.closureFunction);
     sink.begin(tag);
@@ -1104,6 +1142,7 @@
     return new ClosureFieldData(definition, memberThisType);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(JMemberDataKind.closureField);
     sink.begin(tag);
@@ -1157,8 +1196,11 @@
   /// debugging data stream.
   static const String tag = 'closure-member-definition';
 
+  @override
   final SourceSpan location;
+  @override
   final MemberKind kind;
+  @override
   final ir.TreeNode node;
 
   ClosureMemberDefinition(this.location, this.kind, this.node)
@@ -1174,6 +1216,7 @@
     return new ClosureMemberDefinition(location, kind, node);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(kind);
     sink.begin(tag);
@@ -1182,6 +1225,7 @@
     sink.end(tag);
   }
 
+  @override
   String toString() => 'ClosureMemberDefinition(kind:$kind,location:$location)';
 }
 
@@ -1190,6 +1234,7 @@
   /// a debugging data stream.
   static const String tag = 'record-definition';
 
+  @override
   final SourceSpan location;
 
   RecordContainerDefinition(this.location);
@@ -1209,11 +1254,14 @@
     sink.end(tag);
   }
 
+  @override
   ClassKind get kind => ClassKind.record;
 
+  @override
   ir.Node get node => throw new UnsupportedError(
       'RecordContainerDefinition.node for $location');
 
+  @override
   String toString() =>
       'RecordContainerDefinition(kind:$kind,location:$location)';
 }
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index 9371d5c..2afbce4 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -384,6 +384,7 @@
   /// debugging data stream.
   static const String tag = 'regular-member-definition';
 
+  @override
   final ir.Member node;
 
   RegularMemberDefinition(this.node);
@@ -403,10 +404,13 @@
     sink.end(tag);
   }
 
+  @override
   SourceSpan get location => computeSourceSpanFromTreeNode(node);
 
+  @override
   MemberKind get kind => MemberKind.regular;
 
+  @override
   String toString() => 'RegularMemberDefinition(kind:$kind,'
       'node:$node,location:$location)';
 }
@@ -417,7 +421,9 @@
   /// debugging data stream.
   static const String tag = 'special-member-definition';
 
+  @override
   final ir.TreeNode node;
+  @override
   final MemberKind kind;
 
   SpecialMemberDefinition(this.node, this.kind);
@@ -438,8 +444,10 @@
     sink.end(tag);
   }
 
+  @override
   SourceSpan get location => computeSourceSpanFromTreeNode(node);
 
+  @override
   String toString() => 'SpecialMemberDefinition(kind:$kind,'
       'node:$node,location:$location)';
 }
@@ -480,6 +488,7 @@
   /// debugging data stream.
   static const String tag = 'regular-class-definition';
 
+  @override
   final ir.Class node;
 
   RegularClassDefinition(this.node);
@@ -491,6 +500,7 @@
     return new RegularClassDefinition(node);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(kind);
     sink.begin(tag);
@@ -498,10 +508,13 @@
     sink.end(tag);
   }
 
+  @override
   SourceSpan get location => computeSourceSpanFromTreeNode(node);
 
+  @override
   ClassKind get kind => ClassKind.regular;
 
+  @override
   String toString() => 'RegularClassDefinition(kind:$kind,'
       'node:$node,location:$location)';
 }
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 31e729e..10db057 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -88,6 +88,7 @@
   static const String nestedClosuresTag = 'nested-closures';
 
   final CompilerOptions options;
+  @override
   final DiagnosticReporter reporter;
   CommonElementsImpl _commonElements;
   JsElementEnvironment _elementEnvironment;
@@ -483,8 +484,10 @@
     sink.end(tag);
   }
 
+  @override
   DartTypes get types => _types;
 
+  @override
   JsElementEnvironment get elementEnvironment => _elementEnvironment;
 
   @override
@@ -597,11 +600,13 @@
     return new InterfaceType(getClass(cls), getDartTypes(typeArguments));
   }
 
+  @override
   LibraryEntity getLibrary(ir.Library node) => getLibraryInternal(node);
 
   @override
   ClassEntity getClass(ir.Class node) => getClassInternal(node);
 
+  @override
   InterfaceType getSuperType(IndexedClass cls) {
     assert(checkFamily(cls));
     JClassData data = classes.getData(cls);
@@ -632,6 +637,7 @@
     }
   }
 
+  @override
   TypeVariableEntity getTypeVariable(ir.TypeParameter node) =>
       getTypeVariableInternal(node);
 
@@ -732,6 +738,7 @@
     throw new UnsupportedError("Unexpected member: $node");
   }
 
+  @override
   MemberEntity getSuperMember(MemberEntity context, ir.Name name,
       {bool setter: false}) {
     // We can no longer trust the interface target of the super access since it
@@ -788,9 +795,11 @@
   @override
   DartType getDartType(ir.DartType type) => _typeConverter.convert(type);
 
+  @override
   TypeVariableType getTypeVariableType(ir.TypeParameterType type) =>
       getDartType(type);
 
+  @override
   List<DartType> getDartTypes(List<ir.DartType> types) {
     List<DartType> list = <DartType>[];
     types.forEach((ir.DartType type) {
@@ -799,6 +808,7 @@
     return list;
   }
 
+  @override
   InterfaceType getInterfaceType(ir.InterfaceType type) =>
       _typeConverter.convert(type);
 
@@ -876,6 +886,7 @@
         constantRequired: requireConstant);
   }
 
+  @override
   DartType substByContext(DartType type, InterfaceType context) {
     return type.subst(
         context.typeArguments, getThisType(context.element).typeArguments);
@@ -886,6 +897,7 @@
   /// If [type] doesn't have a `call` member `null` is returned. If [type] has
   /// an invalid `call` member (non-method or a synthesized method with both
   /// optional and named parameters) a [DynamicType] is returned.
+  @override
   DartType getCallType(InterfaceType type) {
     IndexedClass cls = type.element;
     assert(checkFamily(cls));
@@ -896,6 +908,7 @@
     return null;
   }
 
+  @override
   InterfaceType getThisType(IndexedClass cls) {
     assert(checkFamily(cls));
     JClassData data = classes.getData(cls);
@@ -928,6 +941,7 @@
     return data.getFieldType(this);
   }
 
+  @override
   DartType getTypeVariableBound(IndexedTypeVariable typeVariable) {
     assert(checkFamily(typeVariable));
     JTypeVariableData data = typeVariables.getData(typeVariable);
@@ -1013,6 +1027,7 @@
     return data.getFieldConstantExpression(this);
   }
 
+  @override
   InterfaceType asInstanceOf(InterfaceType type, ClassEntity cls) {
     assert(checkFamily(cls));
     OrderedTypeSet orderedTypeSet = getOrderedTypeSet(type.element);
@@ -1024,6 +1039,7 @@
     return supertype;
   }
 
+  @override
   OrderedTypeSet getOrderedTypeSet(IndexedClass cls) {
     assert(checkFamily(cls));
     JClassData data = classes.getData(cls);
@@ -1031,6 +1047,7 @@
     return data.orderedTypeSet;
   }
 
+  @override
   int getHierarchyDepth(IndexedClass cls) {
     assert(checkFamily(cls));
     JClassData data = classes.getData(cls);
@@ -1038,6 +1055,7 @@
     return data.orderedTypeSet.maxDepth;
   }
 
+  @override
   Iterable<InterfaceType> getInterfaces(IndexedClass cls) {
     assert(checkFamily(cls));
     JClassData data = classes.getData(cls);
@@ -1055,6 +1073,7 @@
     return classes.getData(cls).definition;
   }
 
+  @override
   ImportEntity getImport(ir.LibraryDependency node) {
     ir.Library library = node.parent;
     JLibraryData data = libraries.getData(getLibraryInternal(library));
@@ -1076,6 +1095,7 @@
     return _classHierarchy;
   }
 
+  @override
   StaticTypeProvider getStaticTypeProvider(MemberEntity member) {
     MemberDefinition memberDefinition = members.getData(member).definition;
     Map<ir.Expression, ir.DartType> cachedStaticTypes;
@@ -1112,11 +1132,13 @@
         new ThisInterfaceType.from(thisType));
   }
 
+  @override
   Name getName(ir.Name name) {
     return new Name(
         name.name, name.isPrivate ? getLibrary(name.library) : null);
   }
 
+  @override
   CallStructure getCallStructure(ir.Arguments arguments) {
     int argumentCount = arguments.positional.length + arguments.named.length;
     List<String> namedArguments = arguments.named.map((e) => e.name).toList();
@@ -1124,6 +1146,7 @@
         argumentCount, namedArguments, arguments.types.length);
   }
 
+  @override
   Selector getSelector(ir.Expression node) {
     // TODO(efortuna): This is screaming for a common interface between
     // PropertyGet and SuperPropertyGet (and same for *Get). Talk to kernel
@@ -1258,6 +1281,7 @@
 
   /// Computes the [native.NativeBehavior] for a call to the [JS] function.
   // TODO(johnniwinther): Cache this for later use.
+  @override
   NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) {
     if (node.arguments.positional.length < 2 ||
         node.arguments.named.isNotEmpty) {
@@ -1291,6 +1315,7 @@
   /// Computes the [NativeBehavior] for a call to the [JS_BUILTIN]
   /// function.
   // TODO(johnniwinther): Cache this for later use.
+  @override
   NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node) {
     if (node.arguments.positional.length < 1) {
       reporter.internalError(
@@ -1319,6 +1344,7 @@
   /// Computes the [NativeBehavior] for a call to the
   /// [JS_EMBEDDED_GLOBAL] function.
   // TODO(johnniwinther): Cache this for later use.
+  @override
   NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
       ir.StaticInvocation node) {
     if (node.arguments.positional.length < 1) {
@@ -1351,6 +1377,7 @@
         commonElements);
   }
 
+  @override
   js.Name getNameForJsGetName(ConstantValue constant, Namer namer) {
     int index = extractEnumIndexFromConstantValue(
         constant, commonElements.jsGetNameEnum);
@@ -1373,6 +1400,7 @@
     return null;
   }
 
+  @override
   ConstantValue getConstantValue(ir.Expression node,
       {bool requireConstant: true, bool implicitNull: false}) {
     if (node is ir.ConstantExpression) {
@@ -1416,6 +1444,7 @@
     return metadata;
   }
 
+  @override
   FunctionEntity getSuperNoSuchMethod(ClassEntity cls) {
     while (cls != null) {
       cls = elementEnvironment.getSuperClass(cls);
@@ -2454,9 +2483,13 @@
 
 /// [BehaviorBuilder] for kernel based elements.
 class JsBehaviorBuilder extends BehaviorBuilder {
+  @override
   final ElementEnvironment elementEnvironment;
+  @override
   final CommonElements commonElements;
+  @override
   final DiagnosticReporter reporter;
+  @override
   final NativeBasicData nativeBasicData;
   final CompilerOptions _options;
 
diff --git a/pkg/compiler/lib/src/js_model/elements.dart b/pkg/compiler/lib/src/js_model/elements.dart
index 4afe45a..2818e69 100644
--- a/pkg/compiler/lib/src/js_model/elements.dart
+++ b/pkg/compiler/lib/src/js_model/elements.dart
@@ -20,7 +20,9 @@
   /// debugging data stream.
   static const String tag = 'library';
 
+  @override
   final String name;
+  @override
   final Uri canonicalUri;
 
   JLibrary(this.name, this.canonicalUri);
@@ -42,6 +44,7 @@
     sink.end(tag);
   }
 
+  @override
   String toString() => '${jsElementPrefix}library($name)';
 }
 
@@ -53,9 +56,12 @@
   /// debugging data stream.
   static const String tag = 'class';
 
+  @override
   final JLibrary library;
 
+  @override
   final String name;
+  @override
   final bool isAbstract;
 
   JClass(this.library, this.name, {this.isAbstract});
@@ -92,6 +98,7 @@
   @override
   bool get isClosure => false;
 
+  @override
   String toString() => '${jsElementPrefix}class($name)';
 }
 
@@ -100,8 +107,10 @@
   /// debugging data stream.
   static const String tag = 'typedef';
 
+  @override
   final JLibrary library;
 
+  @override
   final String name;
 
   JTypedef(this.library, this.name);
@@ -123,6 +132,7 @@
     sink.end(tag);
   }
 
+  @override
   String toString() => '${jsElementPrefix}typedef($name)';
 }
 
@@ -143,7 +153,9 @@
 }
 
 abstract class JMember extends IndexedMember {
+  @override
   final JLibrary library;
+  @override
   final JClass enclosingClass;
   final Name _name;
   final bool _isStatic;
@@ -186,8 +198,10 @@
   /// Serializes this [JMember] to [sink].
   void writeToDataSink(DataSink sink);
 
+  @override
   String get name => _name.text;
 
+  @override
   Name get memberName => _name;
 
   @override
@@ -225,14 +239,18 @@
 
   String get _kind;
 
+  @override
   String toString() => '${jsElementPrefix}$_kind'
       '(${enclosingClass != null ? '${enclosingClass.name}.' : ''}$name)';
 }
 
 abstract class JFunction extends JMember
     implements FunctionEntity, IndexedFunction {
+  @override
   final ParameterStructure parameterStructure;
+  @override
   final bool isExternal;
+  @override
   final AsyncMarker asyncMarker;
 
   JFunction(JLibrary library, JClass enclosingClass, Name name,
@@ -243,6 +261,7 @@
 
 abstract class JConstructor extends JFunction
     implements ConstructorEntity, IndexedConstructor {
+  @override
   final bool isConst;
 
   JConstructor(
@@ -267,6 +286,7 @@
   @override
   bool get isFromEnvironmentConstructor => false;
 
+  @override
   String get _kind => 'constructor';
 }
 
@@ -370,6 +390,7 @@
   /// debugging data stream.
   static const String tag = 'constructor-body';
 
+  @override
   final JConstructor constructor;
 
   JConstructorBody(this.constructor, ParameterStructure parameterStructure)
@@ -395,6 +416,7 @@
     sink.end(tag);
   }
 
+  @override
   String get _kind => 'constructor_body';
 }
 
@@ -403,6 +425,7 @@
   /// debugging data stream.
   static const String tag = 'method';
 
+  @override
   final bool isAbstract;
 
   JMethod(JLibrary library, JClass enclosingClass, Name name,
@@ -461,6 +484,7 @@
   @override
   bool get isFunction => true;
 
+  @override
   String get _kind => 'method';
 }
 
@@ -471,6 +495,7 @@
 
   final JFunction function;
   final DartType elementType;
+  @override
   final int hashCode;
 
   JGeneratorBody(this.function, this.elementType)
@@ -496,6 +521,7 @@
     sink.end(tag);
   }
 
+  @override
   String get _kind => 'generator_body';
 }
 
@@ -504,6 +530,7 @@
   /// debugging data stream.
   static const String tag = 'getter';
 
+  @override
   final bool isAbstract;
 
   JGetter(JLibrary library, JClass enclosingClass, Name name,
@@ -560,6 +587,7 @@
   @override
   bool get isGetter => true;
 
+  @override
   String get _kind => 'getter';
 }
 
@@ -568,6 +596,7 @@
   /// debugging data stream.
   static const String tag = 'setter';
 
+  @override
   final bool isAbstract;
 
   JSetter(JLibrary library, JClass enclosingClass, Name name,
@@ -624,6 +653,7 @@
   @override
   bool get isSetter => true;
 
+  @override
   String get _kind => 'setter';
 }
 
@@ -632,7 +662,9 @@
   /// debugging data stream.
   static const String tag = 'field';
 
+  @override
   final bool isAssignable;
+  @override
   final bool isConst;
 
   JField(JLibrary library, JClass enclosingClass, Name name,
@@ -683,6 +715,7 @@
   @override
   bool get isField => true;
 
+  @override
   String get _kind => 'field';
 }
 
@@ -718,6 +751,7 @@
     sink.end(tag);
   }
 
+  @override
   String get _kind => 'closure_call';
 }
 
@@ -740,6 +774,7 @@
     return new JSignatureMethod(cls);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(JMemberKind.signatureMethod);
     sink.begin(tag);
@@ -747,6 +782,7 @@
     sink.end(tag);
   }
 
+  @override
   String get _kind => 'signature';
 }
 
@@ -758,8 +794,11 @@
   /// debugging data stream.
   static const String tag = 'type-variable';
 
+  @override
   final Entity typeDeclaration;
+  @override
   final String name;
+  @override
   final int index;
 
   JTypeVariable(this.typeDeclaration, this.name, this.index);
@@ -818,6 +857,7 @@
     sink.end(tag);
   }
 
+  @override
   String toString() =>
       '${jsElementPrefix}type_variable(${typeDeclaration.name}.$name)';
 }
diff --git a/pkg/compiler/lib/src/js_model/env.dart b/pkg/compiler/lib/src/js_model/env.dart
index 1e72ff3..9fb97dc 100644
--- a/pkg/compiler/lib/src/js_model/env.dart
+++ b/pkg/compiler/lib/src/js_model/env.dart
@@ -230,11 +230,13 @@
   /// debugging data stream.
   static const String tag = 'class-env';
 
+  @override
   final ir.Class cls;
   final Map<String, ir.Member> _constructorMap;
   final Map<String, ir.Member> _memberMap;
   final Map<String, ir.Member> _setterMap;
   final List<ir.Member> _members; // in declaration order.
+  @override
   final bool isSuperMixinApplication;
 
   /// Constructor bodies created for this class.
@@ -272,11 +274,13 @@
     sink.end(tag);
   }
 
+  @override
   bool get isUnnamedMixinApplication => cls.isAnonymousMixin;
 
   /// Return the [MemberEntity] for the member [name] in [cls]. If [setter] is
   /// `true`, the setter or assignable field corresponding to [name] is
   /// returned.
+  @override
   MemberEntity lookupMember(IrToElementMap elementMap, String name,
       {bool setter: false}) {
     ir.Member member = setter ? _setterMap[name] : _memberMap[name];
@@ -284,6 +288,7 @@
   }
 
   /// Calls [f] for each member of [cls].
+  @override
   void forEachMember(IrToElementMap elementMap, void f(MemberEntity member)) {
     _members.forEach((ir.Member member) {
       f(elementMap.getMember(member));
@@ -291,12 +296,14 @@
   }
 
   /// Return the [ConstructorEntity] for the constructor [name] in [cls].
+  @override
   ConstructorEntity lookupConstructor(IrToElementMap elementMap, String name) {
     ir.Member constructor = _constructorMap[name];
     return constructor != null ? elementMap.getConstructor(constructor) : null;
   }
 
   /// Calls [f] for each constructor of [cls].
+  @override
   void forEachConstructor(
       IrToElementMap elementMap, void f(ConstructorEntity constructor)) {
     _constructorMap.values.forEach((ir.Member constructor) {
@@ -309,6 +316,7 @@
     _constructorBodyList.add(constructorBody);
   }
 
+  @override
   void forEachConstructorBody(void f(ConstructorBodyEntity constructor)) {
     _constructorBodyList?.forEach(f);
   }
@@ -454,15 +462,23 @@
   static const String tag = 'class-data';
 
   final ir.Class cls;
+  @override
   final ClassDefinition definition;
+  @override
   bool isMixinApplication;
   bool isCallTypeComputed = false;
 
+  @override
   InterfaceType thisType;
+  @override
   InterfaceType rawType;
+  @override
   InterfaceType supertype;
+  @override
   InterfaceType mixedInType;
+  @override
   List<InterfaceType> interfaces;
+  @override
   OrderedTypeSet orderedTypeSet;
 
   JClassDataImpl(this.cls, this.definition);
@@ -484,8 +500,10 @@
     sink.end(tag);
   }
 
+  @override
   bool get isEnumClass => cls != null && cls.isEnum;
 
+  @override
   DartType get callType => null;
 }
 
@@ -543,12 +561,15 @@
 abstract class JMemberDataImpl implements JMemberData {
   final ir.Member node;
 
+  @override
   final MemberDefinition definition;
 
+  @override
   final Map<ir.Expression, ir.DartType> staticTypes;
 
   JMemberDataImpl(this.node, this.definition, this.staticTypes);
 
+  @override
   InterfaceType getMemberThisType(JsToElementMap elementMap) {
     MemberEntity member = elementMap.getMember(node);
     ClassEntity cls = member.enclosingClass;
@@ -575,6 +596,7 @@
   ir.FunctionNode get functionNode;
   List<TypeVariableType> _typeVariables;
 
+  @override
   List<TypeVariableType> getFunctionTypeVariables(
       covariant JsKernelToElementMap elementMap) {
     if (_typeVariables == null) {
@@ -602,6 +624,7 @@
 abstract class FunctionDataForEachParameterMixin implements FunctionData {
   ir.FunctionNode get functionNode;
 
+  @override
   void forEachParameter(
       JsToElementMap elementMap,
       ParameterStructure parameterStructure,
@@ -637,6 +660,7 @@
   /// debugging data stream.
   static const String tag = 'function-data';
 
+  @override
   final ir.FunctionNode functionNode;
   FunctionType _type;
 
@@ -664,6 +688,7 @@
     return new FunctionDataImpl(node, functionNode, definition, staticTypes);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(JMemberDataKind.function);
     sink.begin(tag);
@@ -673,6 +698,7 @@
     sink.end(tag);
   }
 
+  @override
   FunctionType getFunctionType(covariant JsKernelToElementMap elementMap) {
     return _type ??= elementMap.getFunctionType(functionNode);
   }
@@ -689,8 +715,10 @@
   /// debugging data stream.
   static const String tag = 'signature-function-data';
 
+  @override
   final MemberDefinition definition;
   final InterfaceType memberThisType;
+  @override
   final ClassTypeVariableAccess classTypeVariableAccess;
   final List<ir.TypeParameter> typeParameters;
 
@@ -710,6 +738,7 @@
         definition, memberThisType, typeParameters, classTypeVariableAccess);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(JMemberDataKind.signature);
     sink.begin(tag);
@@ -723,10 +752,12 @@
   @override
   Map<ir.Expression, ir.DartType> get staticTypes => const {};
 
+  @override
   FunctionType getFunctionType(covariant JsKernelToElementMap elementMap) {
     throw new UnsupportedError("SignatureFunctionData.getFunctionType");
   }
 
+  @override
   List<TypeVariableType> getFunctionTypeVariables(IrToElementMap elementMap) {
     return typeParameters
         .map<TypeVariableType>((ir.TypeParameter typeParameter) {
@@ -734,6 +765,7 @@
     }).toList();
   }
 
+  @override
   void forEachParameter(
       JsToElementMap elementMap,
       ParameterStructure parameterStructure,
@@ -742,6 +774,7 @@
     throw new UnimplementedError('SignatureData.forEachParameter');
   }
 
+  @override
   InterfaceType getMemberThisType(JsToElementMap elementMap) {
     return memberThisType;
   }
@@ -752,14 +785,17 @@
 
   DelegatedFunctionData(this.baseData);
 
+  @override
   FunctionType getFunctionType(covariant JsKernelToElementMap elementMap) {
     return baseData.getFunctionType(elementMap);
   }
 
+  @override
   List<TypeVariableType> getFunctionTypeVariables(IrToElementMap elementMap) {
     return baseData.getFunctionTypeVariables(elementMap);
   }
 
+  @override
   void forEachParameter(
       JsToElementMap elementMap,
       ParameterStructure parameterStructure,
@@ -769,10 +805,12 @@
         isNative: isNative);
   }
 
+  @override
   InterfaceType getMemberThisType(JsToElementMap elementMap) {
     return baseData.getMemberThisType(elementMap);
   }
 
+  @override
   ClassTypeVariableAccess get classTypeVariableAccess =>
       baseData.classTypeVariableAccess;
 }
@@ -782,6 +820,7 @@
   /// a debugging data stream.
   static const String tag = 'generator-body-data';
 
+  @override
   final MemberDefinition definition;
 
   GeneratorBodyFunctionData(FunctionData baseData, this.definition)
@@ -797,6 +836,7 @@
     return new GeneratorBodyFunctionData(baseData, definition);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(JMemberDataKind.generatorBody);
     sink.begin(tag);
@@ -848,6 +888,7 @@
         node, functionNode, definition, staticTypes);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(JMemberDataKind.constructor);
     sink.begin(tag);
@@ -858,6 +899,7 @@
     sink.end(tag);
   }
 
+  @override
   ConstantConstructor getConstructorConstant(
       JsKernelToElementMap elementMap, ConstructorEntity constructor) {
     if (_constantConstructor == null) {
@@ -909,6 +951,7 @@
         node, functionNode, definition, staticTypes);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(JMemberDataKind.constructorBody);
     sink.begin(tag);
@@ -955,6 +998,7 @@
     return new JFieldDataImpl(node, definition, staticTypes);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.writeEnum(JMemberDataKind.field);
     sink.begin(tag);
@@ -964,12 +1008,15 @@
     sink.end(tag);
   }
 
+  @override
   ir.Field get node => super.node;
 
+  @override
   DartType getFieldType(covariant JsKernelToElementMap elementMap) {
     return _type ??= elementMap.getDartType(node.type);
   }
 
+  @override
   ConstantExpression getFieldConstantExpression(
       JsKernelToElementMap elementMap) {
     if (_constantExpression == null) {
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index e605804..2090143 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -26,7 +26,6 @@
 import '../js_backend/native_data.dart';
 import '../kernel/kernel_strategy.dart';
 import '../native/behavior.dart';
-import '../options.dart';
 import '../ssa/builder_kernel.dart';
 import '../ssa/nodes.dart';
 import '../ssa/ssa.dart';
@@ -138,21 +137,9 @@
   KernelCodegenWorkItemBuilder(
       this._backend, this._closedWorld, this._globalInferenceResults);
 
-  CompilerOptions get _options => _backend.compiler.options;
-
   @override
   CodegenWorkItem createWorkItem(MemberEntity entity) {
     if (entity.isAbstract) return null;
-
-    // Codegen inlines field initializers. It only needs to generate
-    // code for checked setters.
-    if (entity.isField && entity.isInstanceMember) {
-      if (!_options.parameterCheckPolicy.isEmitted ||
-          entity.enclosingClass.isClosure) {
-        return null;
-      }
-    }
-
     return new KernelCodegenWorkItem(
         _backend, _closedWorld, _globalInferenceResults, entity);
   }
@@ -161,7 +148,9 @@
 class KernelCodegenWorkItem extends CodegenWorkItem {
   final JavaScriptBackend _backend;
   final JClosedWorld _closedWorld;
+  @override
   final MemberEntity element;
+  @override
   final CodegenRegistry registry;
   final GlobalTypeInferenceResults _globalInferenceResults;
 
@@ -220,73 +209,88 @@
       _globalInferenceResults
           .resultOfMember(e is ConstructorBodyEntity ? e.constructor : e);
 
+  @override
   AbstractValue getReturnTypeOf(FunctionEntity function) {
     return AbstractValueFactory.inferredReturnTypeForElement(
         function, _globalInferenceResults);
   }
 
+  @override
   AbstractValue receiverTypeOfInvocation(
       ir.MethodInvocation node, AbstractValueDomain abstractValueDomain) {
     return _targetResults.typeOfSend(node);
   }
 
+  @override
   AbstractValue receiverTypeOfGet(ir.PropertyGet node) {
     return _targetResults.typeOfSend(node);
   }
 
+  @override
   AbstractValue receiverTypeOfDirectGet(ir.DirectPropertyGet node) {
     return _targetResults.typeOfSend(node);
   }
 
+  @override
   AbstractValue receiverTypeOfSet(
       ir.PropertySet node, AbstractValueDomain abstractValueDomain) {
     return _targetResults.typeOfSend(node);
   }
 
+  @override
   AbstractValue typeOfListLiteral(
       ir.ListLiteral listLiteral, AbstractValueDomain abstractValueDomain) {
     return _globalInferenceResults.typeOfListLiteral(listLiteral) ??
         abstractValueDomain.dynamicType;
   }
 
+  @override
   AbstractValue typeOfIterator(ir.ForInStatement node) {
     return _targetResults.typeOfIterator(node);
   }
 
+  @override
   AbstractValue typeOfIteratorCurrent(ir.ForInStatement node) {
     return _targetResults.typeOfIteratorCurrent(node);
   }
 
+  @override
   AbstractValue typeOfIteratorMoveNext(ir.ForInStatement node) {
     return _targetResults.typeOfIteratorMoveNext(node);
   }
 
+  @override
   bool isJsIndexableIterator(
       ir.ForInStatement node, AbstractValueDomain abstractValueDomain) {
     AbstractValue mask = typeOfIterator(node);
     return abstractValueDomain.isJsIndexableAndIterable(mask).isDefinitelyTrue;
   }
 
+  @override
   AbstractValue inferredIndexType(ir.ForInStatement node) {
     return AbstractValueFactory.inferredTypeForSelector(
         new Selector.index(), typeOfIterator(node), _globalInferenceResults);
   }
 
+  @override
   AbstractValue getInferredTypeOf(MemberEntity member) {
     return AbstractValueFactory.inferredTypeForMember(
         member, _globalInferenceResults);
   }
 
+  @override
   AbstractValue getInferredTypeOfParameter(Local parameter) {
     return AbstractValueFactory.inferredTypeForParameter(
         parameter, _globalInferenceResults);
   }
 
+  @override
   AbstractValue selectorTypeOf(Selector selector, AbstractValue mask) {
     return AbstractValueFactory.inferredTypeForSelector(
         selector, mask, _globalInferenceResults);
   }
 
+  @override
   AbstractValue typeFromNativeBehavior(
       NativeBehavior nativeBehavior, JClosedWorld closedWorld) {
     return AbstractValueFactory.fromNativeBehavior(nativeBehavior, closedWorld);
diff --git a/pkg/compiler/lib/src/js_model/js_world.dart b/pkg/compiler/lib/src/js_model/js_world.dart
index 024408f..fdf9a69 100644
--- a/pkg/compiler/lib/src/js_model/js_world.dart
+++ b/pkg/compiler/lib/src/js_model/js_world.dart
@@ -41,9 +41,13 @@
 class JsClosedWorld implements JClosedWorld {
   static const String tag = 'closed-world';
 
+  @override
   final NativeData nativeData;
+  @override
   final InterceptorData interceptorData;
+  @override
   final BackendUsage backendUsage;
+  @override
   final NoSuchMethodData noSuchMethodData;
 
   FunctionSet _allFunctions;
@@ -64,19 +68,28 @@
   /// Members that are written either directly or through a setter selector.
   final Set<MemberEntity> assignedInstanceMembers;
 
+  @override
   final Set<ClassEntity> liveNativeClasses;
 
+  @override
   final Set<MemberEntity> processedMembers;
 
+  @override
   final ClassHierarchy classHierarchy;
 
   final JsKernelToElementMap elementMap;
+  @override
   final RuntimeTypesNeed rtiNeed;
   AbstractValueDomain _abstractValueDomain;
+  @override
   final JFieldAnalysis fieldAnalysis;
+  @override
   final AnnotationsData annotationsData;
+  @override
   final GlobalLocalsMap globalLocalsMap;
+  @override
   final ClosureData closureDataLookup;
+  @override
   final OutputUnitData outputUnitData;
   Sorter _sorter;
 
@@ -207,13 +220,17 @@
     sink.end(tag);
   }
 
+  @override
   JElementEnvironment get elementEnvironment => elementMap.elementEnvironment;
 
+  @override
   JCommonElements get commonElements => elementMap.commonElements;
 
+  @override
   DartTypes get dartTypes => elementMap.types;
 
   /// Returns `true` if [cls] is implemented by an instantiated class.
+  @override
   bool isImplemented(ClassEntity cls) {
     return implementedClasses.contains(cls);
   }
@@ -239,11 +256,13 @@
   }
 
   /// Returns `true` if [cls] is mixed into a live class.
+  @override
   bool isUsedAsMixin(ClassEntity cls) {
     return !mixinUsesOf(cls).isEmpty;
   }
 
   /// Returns `true` if any live class that mixes in [cls] implements [type].
+  @override
   bool hasAnySubclassOfMixinUseThatImplements(
       ClassEntity cls, ClassEntity type) {
     return mixinUsesOf(cls)
@@ -252,6 +271,7 @@
 
   /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass
   /// of a mixin application of [y].
+  @override
   bool everySubtypeIsSubclassOfOrMixinUseOf(ClassEntity x, ClassEntity y) {
     Map<ClassEntity, bool> secondMap =
         _subtypeCoveredByCache[x] ??= <ClassEntity, bool>{};
@@ -262,6 +282,7 @@
   }
 
   /// Returns `true` if any subclass of [superclass] implements [type].
+  @override
   bool hasAnySubclassThatImplements(ClassEntity superclass, ClassEntity type) {
     Set<ClassEntity> subclasses = typesImplementedBySubclasses[superclass];
     if (subclasses == null) return false;
@@ -320,6 +341,7 @@
   }
 
   /// Returns an iterable over the common supertypes of the [classes].
+  @override
   Iterable<ClassEntity> commonSupertypesOf(Iterable<ClassEntity> classes) {
     Iterator<ClassEntity> iterator = classes.iterator;
     if (!iterator.moveNext()) return const <ClassEntity>[];
@@ -360,6 +382,7 @@
   }
 
   /// Returns an iterable over the live mixin applications that mixin [cls].
+  @override
   Iterable<ClassEntity> mixinUsesOf(ClassEntity cls) {
     if (_liveMixinUses == null) {
       _liveMixinUses = new Map<ClassEntity, List<ClassEntity>>();
@@ -389,6 +412,7 @@
 
   /// Returns `true` if any live class that mixes in [mixin] is also a subclass
   /// of [superclass].
+  @override
   bool hasAnySubclassThatMixes(ClassEntity superclass, ClassEntity mixin) {
     return mixinUsesOf(mixin).any((ClassEntity each) {
       return classHierarchy.isSubclassOf(each, superclass);
@@ -396,6 +420,7 @@
   }
 
   /// Returns `true` if [cls] or any superclass mixes in [mixin].
+  @override
   bool isSubclassOfMixinUseOf(ClassEntity cls, ClassEntity mixin) {
     if (isUsedAsMixin(mixin)) {
       ClassEntity current = cls;
@@ -422,6 +447,7 @@
   /// Every implementation of `Closure` has a 'call' method with its own
   /// signature so it cannot be modelled by a [FunctionEntity]. Also,
   /// call-methods for tear-off are not part of the element model.
+  @override
   bool includesClosureCall(Selector selector, AbstractValue receiver) {
     return selector.name == Identifiers.call &&
         (receiver == null ||
@@ -431,6 +457,7 @@
                 .isPotentiallyTrue);
   }
 
+  @override
   AbstractValue computeReceiverType(Selector selector, AbstractValue receiver) {
     _ensureFunctionSet();
     if (includesClosureCall(selector, receiver)) {
@@ -439,6 +466,7 @@
     return _allFunctions.receiverType(selector, receiver, abstractValueDomain);
   }
 
+  @override
   Iterable<MemberEntity> locateMembers(
       Selector selector, AbstractValue receiver) {
     _ensureFunctionSet();
@@ -452,6 +480,7 @@
         .any((each) => each.isGetter);
   }
 
+  @override
   MemberEntity locateSingleMember(Selector selector, AbstractValue receiver) {
     if (includesClosureCall(selector, receiver)) {
       return null;
@@ -460,6 +489,7 @@
     return abstractValueDomain.locateSingleMember(receiver, selector);
   }
 
+  @override
   bool fieldNeverChanges(MemberEntity element) {
     if (!element.isField) return false;
     if (nativeData.isNativeMember(element)) {
diff --git a/pkg/compiler/lib/src/js_model/js_world_builder.dart b/pkg/compiler/lib/src/js_model/js_world_builder.dart
index baff70c..c8210a9 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -340,25 +340,12 @@
     Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior =
         map.toBackendMemberMap(
             nativeData.nativeFieldStoreBehavior, convertNativeBehavior);
-    Map<LibraryEntity, String> jsInteropLibraryNames =
-        map.toBackendLibraryMap(nativeData.jsInteropLibraries, identity);
-    Set<ClassEntity> anonymousJsInteropClasses =
-        map.toBackendClassSet(nativeData.anonymousJsInteropClasses);
-    Map<ClassEntity, String> jsInteropClassNames =
-        map.toBackendClassMap(nativeData.jsInteropClasses, identity);
-    Map<MemberEntity, String> jsInteropMemberNames =
-        map.toBackendMemberMap(nativeData.jsInteropMembers, identity);
-
     return new NativeDataImpl(
         nativeBasicData,
         nativeMemberName,
         nativeMethodBehavior,
         nativeFieldLoadBehavior,
-        nativeFieldStoreBehavior,
-        jsInteropLibraryNames,
-        anonymousJsInteropClasses,
-        jsInteropClassNames,
-        jsInteropMemberNames);
+        nativeFieldStoreBehavior);
   }
 
   InterceptorData _convertInterceptorData(JsToFrontendMap map,
@@ -673,6 +660,7 @@
 
   JsToFrontendMapImpl(this._backend);
 
+  @override
   DartType toBackendType(DartType type, {bool allowFreeVariables: false}) =>
       type == null
           ? null
@@ -690,14 +678,17 @@
     return toBackendLibrary(entity);
   }
 
+  @override
   LibraryEntity toBackendLibrary(covariant IndexedLibrary library) {
     return _backend.libraries.getEntity(library.libraryIndex);
   }
 
+  @override
   ClassEntity toBackendClass(covariant IndexedClass cls) {
     return _backend.classes.getEntity(cls.classIndex);
   }
 
+  @override
   MemberEntity toBackendMember(covariant IndexedMember member) {
     return _backend.members.getEntity(member.memberIndex);
   }
@@ -716,6 +707,7 @@
         .getEntity(indexedTypeVariable.typeVariableIndex);
   }
 
+  @override
   ConstantValue toBackendConstant(ConstantValue constant,
       {bool allowNull: false}) {
     if (constant == null) {
@@ -835,19 +827,28 @@
   _ConstantConverter(this.toBackendEntity)
       : typeConverter = new _TypeConverter();
 
+  @override
   ConstantValue visitNull(NullConstantValue constant, _) => constant;
+  @override
   ConstantValue visitInt(IntConstantValue constant, _) => constant;
+  @override
   ConstantValue visitDouble(DoubleConstantValue constant, _) => constant;
+  @override
   ConstantValue visitBool(BoolConstantValue constant, _) => constant;
+  @override
   ConstantValue visitString(StringConstantValue constant, _) => constant;
+  @override
   ConstantValue visitSynthetic(SyntheticConstantValue constant, _) => constant;
+  @override
   ConstantValue visitNonConstant(NonConstantValue constant, _) => constant;
 
+  @override
   ConstantValue visitFunction(FunctionConstantValue constant, _) {
     return new FunctionConstantValue(toBackendEntity(constant.element),
         typeConverter.visit(constant.type, toBackendEntity));
   }
 
+  @override
   ConstantValue visitList(ListConstantValue constant, _) {
     DartType type = typeConverter.visit(constant.type, toBackendEntity);
     List<ConstantValue> entries = _handleValues(constant.entries);
@@ -868,6 +869,7 @@
     return new constant_system.JavaScriptSetConstant(type, entries);
   }
 
+  @override
   ConstantValue visitMap(
       covariant constant_system.JavaScriptMapConstant constant, _) {
     DartType type = typeConverter.visit(constant.type, toBackendEntity);
@@ -884,6 +886,7 @@
         type, keys, values, protoValue, constant.onlyStringKeys);
   }
 
+  @override
   ConstantValue visitConstructed(ConstructedConstantValue constant, _) {
     DartType type = typeConverter.visit(constant.type, toBackendEntity);
     Map<FieldEntity, ConstantValue> fields = {};
@@ -895,6 +898,7 @@
     return new ConstructedConstantValue(type, fields);
   }
 
+  @override
   ConstantValue visitType(TypeConstantValue constant, _) {
     DartType type = typeConverter.visit(constant.type, toBackendEntity);
     DartType representedType =
@@ -905,18 +909,21 @@
     return new TypeConstantValue(representedType, type);
   }
 
+  @override
   ConstantValue visitInterceptor(InterceptorConstantValue constant, _) {
     // Interceptor constants are only created in the SSA graph builder.
     throw new UnsupportedError(
         "Unexpected visitInterceptor ${constant.toStructuredText()}");
   }
 
+  @override
   ConstantValue visitDeferredGlobal(DeferredGlobalConstantValue constant, _) {
     // Deferred global constants are only created in the SSA graph builder.
     throw new UnsupportedError(
         "Unexpected DeferredGlobalConstantValue ${constant.toStructuredText()}");
   }
 
+  @override
   ConstantValue visitInstantiation(InstantiationConstantValue constant, _) {
     ConstantValue function = constant.function.accept(this, null);
     List<DartType> typeArguments =
diff --git a/pkg/compiler/lib/src/js_model/locals.dart b/pkg/compiler/lib/src/js_model/locals.dart
index 2281cd9..d6666c0 100644
--- a/pkg/compiler/lib/src/js_model/locals.dart
+++ b/pkg/compiler/lib/src/js_model/locals.dart
@@ -138,6 +138,7 @@
   }
 
   /// Serializes this [KernelToLocalsMapImpl] to [sink].
+  @override
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
     sink.writeMember(currentMember);
@@ -187,6 +188,7 @@
     }
   }
 
+  @override
   MemberEntity get currentMember => _currentMember;
 
   Local getLocalByIndex(int index) {
@@ -451,11 +453,16 @@
   static const String tag = 'jump-target';
 
   final MemberEntity memberContext;
+  @override
   final int nestingLevel;
   List<LabelDefinition> _labels;
+  @override
   final bool isSwitch;
+  @override
   final bool isSwitchCase;
+  @override
   bool isBreakTarget;
+  @override
   bool isContinueTarget;
 
   JJumpTarget(this.memberContext, this.nestingLevel,
@@ -527,6 +534,7 @@
     return _labels ?? const <LabelDefinition>[];
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('JJumpTarget(');
@@ -548,9 +556,13 @@
 }
 
 class JLabelDefinition extends LabelDefinition {
+  @override
   final JumpTarget target;
+  @override
   final String labelName;
+  @override
   bool isBreakTarget;
+  @override
   bool isContinueTarget;
 
   JLabelDefinition(this.target, this.labelName,
@@ -558,6 +570,7 @@
 
   @override
   String get name => labelName;
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('JLabelDefinition(');
@@ -573,6 +586,7 @@
 }
 
 class JLocal extends IndexedLocal {
+  @override
   final String name;
   final MemberEntity memberContext;
 
@@ -585,6 +599,7 @@
 
   String get _kind => 'local';
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('$_kind(');
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index 38c496d..cc810d1 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -45,14 +45,18 @@
 /// A kernel [Target] to configure the Dart Front End for dart2js.
 class Dart2jsTarget extends Target {
   final TargetFlags flags;
+  @override
   final String name;
 
   Dart2jsTarget(this.name, this.flags);
 
+  @override
   bool get legacyMode => flags.legacyMode;
 
+  @override
   bool get enableNoSuchMethodForwarders => !flags.legacyMode;
 
+  @override
   List<String> get extraRequiredLibraries => _requiredLibraries[name];
 
   @override
diff --git a/pkg/compiler/lib/src/kernel/element_map.dart b/pkg/compiler/lib/src/kernel/element_map.dart
index 3a22be9..d69ff52 100644
--- a/pkg/compiler/lib/src/kernel/element_map.dart
+++ b/pkg/compiler/lib/src/kernel/element_map.dart
@@ -147,6 +147,7 @@
 
   /// Computes the native behavior for reading the native [field].
   NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field,
+      Iterable<String> createsAnnotations, Iterable<String> returnsAnnotations,
       {bool isJsInterop});
 
   /// Computes the native behavior for writing to the native [field].
@@ -155,6 +156,7 @@
   /// Computes the native behavior for calling the function or constructor
   /// [member].
   NativeBehavior getNativeBehaviorForMethod(ir.Member member,
+      Iterable<String> createsAnnotations, Iterable<String> returnsAnnotations,
       {bool isJsInterop});
 
   /// Compute the kind of foreign helper function called by [node], if any.
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index db56ed7..6f2491d 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -61,15 +61,11 @@
 part 'native_basic_data.dart';
 part 'no_such_method_resolver.dart';
 
-/// If `true` kernel impacts are computed as [ImpactData] directly on kernel
-/// and converted to the K model afterwards. This is a pre-step to modularizing
-/// the world impact computation.
-bool useImpactDataForTesting = false;
-
 /// Implementation of [KernelToElementMap] that only supports world
 /// impact computation.
 class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
   final CompilerOptions options;
+  @override
   final DiagnosticReporter reporter;
   CommonElementsImpl _commonElements;
   KernelElementEnvironment _elementEnvironment;
@@ -128,8 +124,10 @@
     _types = new KernelDartTypes(this);
   }
 
+  @override
   DartTypes get types => _types;
 
+  @override
   KernelElementEnvironment get elementEnvironment => _elementEnvironment;
 
   @override
@@ -251,6 +249,7 @@
   @override
   ClassEntity getClass(ir.Class node) => getClassInternal(node);
 
+  @override
   InterfaceType getSuperType(IndexedClass cls) {
     assert(checkFamily(cls));
     KClassData data = classes.getData(cls);
@@ -281,6 +280,7 @@
     }
   }
 
+  @override
   TypeVariableEntity getTypeVariable(ir.TypeParameter node) =>
       getTypeVariableInternal(node);
 
@@ -381,6 +381,7 @@
     throw new UnsupportedError("Unexpected member: $node");
   }
 
+  @override
   MemberEntity getSuperMember(MemberEntity context, ir.Name name,
       {bool setter: false}) {
     // We can no longer trust the interface target of the super access since it
@@ -410,6 +411,7 @@
   ConstructorEntity getConstructor(ir.Member node) =>
       getConstructorInternal(node);
 
+  @override
   ConstructorEntity getSuperConstructor(
       ir.Constructor sourceNode, ir.Member targetNode) {
     ConstructorEntity source = getConstructor(sourceNode);
@@ -440,6 +442,7 @@
   @override
   DartType getDartType(ir.DartType type) => _typeConverter.convert(type);
 
+  @override
   TypeVariableType getTypeVariableType(ir.TypeParameterType type) =>
       getDartType(type);
 
@@ -451,6 +454,7 @@
     return list;
   }
 
+  @override
   InterfaceType getInterfaceType(ir.InterfaceType type) =>
       _typeConverter.convert(type);
 
@@ -528,6 +532,7 @@
         constantRequired: requireConstant, checkCasts: checkCasts);
   }
 
+  @override
   DartType substByContext(DartType type, InterfaceType context) {
     return type.subst(
         context.typeArguments, getThisType(context.element).typeArguments);
@@ -538,6 +543,7 @@
   /// If [type] doesn't have a `call` member `null` is returned. If [type] has
   /// an invalid `call` member (non-method or a synthesized method with both
   /// optional and named parameters) a [DynamicType] is returned.
+  @override
   DartType getCallType(InterfaceType type) {
     IndexedClass cls = type.element;
     assert(checkFamily(cls));
@@ -548,6 +554,7 @@
     return null;
   }
 
+  @override
   InterfaceType getThisType(IndexedClass cls) {
     assert(checkFamily(cls));
     KClassData data = classes.getData(cls);
@@ -580,6 +587,7 @@
     return data.getFunctionTypeVariables(this);
   }
 
+  @override
   DartType getTypeVariableBound(IndexedTypeVariable typeVariable) {
     assert(checkFamily(typeVariable));
     KTypeVariableData data = typeVariables.getData(typeVariable);
@@ -672,6 +680,7 @@
     return data.getFieldConstantExpression(this);
   }
 
+  @override
   InterfaceType asInstanceOf(InterfaceType type, ClassEntity cls) {
     assert(checkFamily(cls));
     OrderedTypeSet orderedTypeSet = getOrderedTypeSet(type.element);
@@ -683,6 +692,7 @@
     return supertype;
   }
 
+  @override
   OrderedTypeSet getOrderedTypeSet(IndexedClass cls) {
     assert(checkFamily(cls));
     KClassData data = classes.getData(cls);
@@ -690,6 +700,7 @@
     return data.orderedTypeSet;
   }
 
+  @override
   int getHierarchyDepth(IndexedClass cls) {
     assert(checkFamily(cls));
     KClassData data = classes.getData(cls);
@@ -697,6 +708,7 @@
     return data.orderedTypeSet.maxDepth;
   }
 
+  @override
   Iterable<InterfaceType> getInterfaces(IndexedClass cls) {
     assert(checkFamily(cls));
     KClassData data = classes.getData(cls);
@@ -704,11 +716,13 @@
     return data.interfaces;
   }
 
+  @override
   ir.Member getMemberNode(covariant IndexedMember member) {
     assert(checkFamily(member));
     return members.getData(member).node;
   }
 
+  @override
   ir.Class getClassNode(covariant IndexedClass cls) {
     assert(checkFamily(cls));
     return classes.getData(cls).node;
@@ -718,6 +732,7 @@
     return typedefs.getData(typedef).node;
   }
 
+  @override
   ImportEntity getImport(ir.LibraryDependency node) {
     if (node == null) return null;
     ir.Library library = node.parent;
@@ -725,6 +740,7 @@
     return data.imports[node];
   }
 
+  @override
   ir.TypeEnvironment get typeEnvironment {
     if (_typeEnvironment == null) {
       _typeEnvironment ??= new ir.TypeEnvironment(
@@ -733,6 +749,7 @@
     return _typeEnvironment;
   }
 
+  @override
   ir.ClassHierarchy get classHierarchy {
     if (_classHierarchy == null) {
       _classHierarchy ??= new ir.ClassHierarchy(env.mainComponent);
@@ -740,11 +757,13 @@
     return _classHierarchy;
   }
 
+  @override
   Name getName(ir.Name name) {
     return new Name(
         name.name, name.isPrivate ? getLibrary(name.library) : null);
   }
 
+  @override
   CallStructure getCallStructure(ir.Arguments arguments) {
     int argumentCount = arguments.positional.length + arguments.named.length;
     List<String> namedArguments = arguments.named.map((e) => e.name).toList();
@@ -766,6 +785,7 @@
         namedParameters, includeTypeParameters ? typeParameters : 0);
   }
 
+  @override
   Selector getInvocationSelector(ir.Name irName, int positionalArguments,
       List<String> namedArguments, int typeArguments) {
     Name name = getName(irName);
@@ -876,6 +896,7 @@
 
   /// Computes the [NativeBehavior] for a call to the [JS] function.
   // TODO(johnniwinther): Cache this for later use.
+  @override
   NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) {
     if (node.arguments.positional.length < 2 ||
         node.arguments.named.isNotEmpty) {
@@ -909,6 +930,7 @@
   /// Computes the [NativeBehavior] for a call to the [JS_BUILTIN]
   /// function.
   // TODO(johnniwinther): Cache this for later use.
+  @override
   NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node) {
     if (node.arguments.positional.length < 1) {
       reporter.internalError(
@@ -937,6 +959,7 @@
   /// Computes the [NativeBehavior] for a call to the
   /// [JS_EMBEDDED_GLOBAL] function.
   // TODO(johnniwinther): Cache this for later use.
+  @override
   NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
       ir.StaticInvocation node) {
     if (node.arguments.positional.length < 1) {
@@ -969,6 +992,7 @@
         commonElements);
   }
 
+  @override
   js.Name getNameForJsGetName(ConstantValue constant, Namer namer) {
     int index = extractEnumIndexFromConstantValue(
         constant, commonElements.jsGetNameEnum);
@@ -991,6 +1015,7 @@
     return null;
   }
 
+  @override
   ConstantValue getConstantValue(ir.Expression node,
       {bool requireConstant: true,
       bool implicitNull: false,
@@ -1038,6 +1063,7 @@
     return metadata;
   }
 
+  @override
   FunctionEntity getSuperNoSuchMethod(ClassEntity cls) {
     while (cls != null) {
       cls = elementEnvironment.getSuperClass(cls);
@@ -1308,12 +1334,14 @@
   }
 
   /// NativeBasicData is need for computation of the default super class.
+  @override
   NativeBasicData get nativeBasicData => _frontendStrategy.nativeBasicData;
 
   /// Adds libraries in [component] to the set of libraries.
   ///
   /// The main method of the first component is used as the main method for the
   /// compilation.
+  @override
   void addComponent(ir.Component component) {
     env.addComponent(component);
   }
@@ -1322,26 +1350,19 @@
       _nativeBehaviorBuilder ??= new KernelBehaviorBuilder(elementEnvironment,
           commonElements, nativeBasicData, reporter, options);
 
-  ResolutionImpact computeWorldImpact(
-      KMember member,
-      VariableScopeModel variableScopeModel,
-      Set<PragmaAnnotation> annotations) {
+  ResolutionImpact computeWorldImpact(KMember member,
+      VariableScopeModel variableScopeModel, Set<PragmaAnnotation> annotations,
+      {ImpactBuilderData impactBuilderData}) {
     KMemberData memberData = members.getData(member);
     ir.Member node = memberData.node;
 
-    if (useImpactDataForTesting) {
-      ImpactBuilder builder = new ImpactBuilder(
-          typeEnvironment, classHierarchy, variableScopeModel,
-          useAsserts: options.enableUserAssertions,
-          inferEffectivelyFinalVariableTypes:
-              !annotations.contains(PragmaAnnotation.disableFinal));
-      if (retainDataForTesting) {
+    if (impactBuilderData != null) {
+      if (impactBuilderData.typeMapsForTesting != null) {
         typeMapsForTesting ??= {};
-        typeMapsForTesting[member] = builder.typeMapsForTesting = {};
+        typeMapsForTesting[member] = impactBuilderData.typeMapsForTesting;
       }
-      node.accept(builder);
-      ImpactData impactData = builder.impactData;
-      memberData.staticTypes = builder.cachedStaticTypes;
+      ImpactData impactData = impactBuilderData.impactData;
+      memberData.staticTypes = impactBuilderData.cachedStaticTypes;
       KernelImpactConverter converter =
           new KernelImpactConverter(this, member, reporter, options);
       return converter.convert(impactData);
@@ -1358,11 +1379,6 @@
     }
   }
 
-  ScopeModel computeScopeModel(KMember member) {
-    ir.Member node = members.getData(member).node;
-    return ScopeModel.computeScopeModel(node);
-  }
-
   Map<ir.Expression, ir.DartType> getCachedStaticTypes(KMember member) {
     Map<ir.Expression, ir.DartType> staticTypes =
         members.getData(member).staticTypes;
@@ -1458,6 +1474,7 @@
 
   /// Returns `true` is [node] has a `@Native(...)` annotation.
   // TODO(johnniwinther): Cache this for later use.
+  @override
   bool isNativeClass(ir.Class node) {
     for (ir.Expression annotation in node.annotations) {
       if (annotation is ir.ConstructorInvocation) {
@@ -1471,6 +1488,7 @@
   }
 
   /// Compute the kind of foreign helper function called by [node], if any.
+  @override
   ForeignKind getForeignKind(ir.StaticInvocation node) {
     if (commonElements.isForeignHelper(getMember(node.target))) {
       switch (node.target.name.name) {
@@ -1489,6 +1507,7 @@
 
   /// Computes the [InterfaceType] referenced by a call to the
   /// [JS_INTERCEPTOR_CONSTANT] function, if any.
+  @override
   InterfaceType getInterfaceTypeForJsInterceptorCall(ir.StaticInvocation node) {
     if (node.arguments.positional.length != 1 ||
         node.arguments.named.isNotEmpty) {
@@ -1504,17 +1523,19 @@
 
   /// Computes the native behavior for reading the native [field].
   // TODO(johnniwinther): Cache this for later use.
+  @override
   NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field,
+      Iterable<String> createsAnnotations, Iterable<String> returnsAnnotations,
       {bool isJsInterop}) {
     DartType type = getDartType(field.type);
-    List<ConstantValue> metadata = getMetadata(field.annotations);
-    return nativeBehaviorBuilder.buildFieldLoadBehavior(
-        type, metadata, typeLookup(resolveAsRaw: false),
+    return nativeBehaviorBuilder.buildFieldLoadBehavior(type,
+        createsAnnotations, returnsAnnotations, typeLookup(resolveAsRaw: false),
         isJsInterop: isJsInterop);
   }
 
   /// Computes the native behavior for writing to the native [field].
   // TODO(johnniwinther): Cache this for later use.
+  @override
   NativeBehavior getNativeBehaviorForFieldStore(ir.Field field) {
     DartType type = getDartType(field.type);
     return nativeBehaviorBuilder.buildFieldStoreBehavior(type);
@@ -1522,7 +1543,9 @@
 
   /// Computes the native behavior for calling [member].
   // TODO(johnniwinther): Cache this for later use.
+  @override
   NativeBehavior getNativeBehaviorForMethod(ir.Member member,
+      Iterable<String> createsAnnotations, Iterable<String> returnsAnnotations,
       {bool isJsInterop}) {
     DartType type;
     if (member is ir.Procedure) {
@@ -1532,9 +1555,8 @@
     } else {
       failedAt(CURRENT_ELEMENT_SPANNABLE, "Unexpected method node $member.");
     }
-    List<ConstantValue> metadata = getMetadata(member.annotations);
-    return nativeBehaviorBuilder.buildMethodBehavior(
-        type, metadata, typeLookup(resolveAsRaw: false),
+    return nativeBehaviorBuilder.buildMethodBehavior(type, createsAnnotations,
+        returnsAnnotations, typeLookup(resolveAsRaw: false),
         isJsInterop: isJsInterop);
   }
 
@@ -1852,9 +1874,13 @@
 
 /// [BehaviorBuilder] for kernel based elements.
 class KernelBehaviorBuilder extends BehaviorBuilder {
+  @override
   final ElementEnvironment elementEnvironment;
+  @override
   final CommonElements commonElements;
+  @override
   final DiagnosticReporter reporter;
+  @override
   final NativeBasicData nativeBasicData;
   final CompilerOptions _options;
 
@@ -1893,6 +1919,7 @@
 class KernelEvaluationEnvironment extends EvaluationEnvironmentBase {
   final KernelToElementMapImpl _elementMap;
   final Environment _environment;
+  @override
   final bool checkCasts;
 
   KernelEvaluationEnvironment(
@@ -1941,7 +1968,7 @@
 class KernelNativeMemberResolver implements NativeMemberResolver {
   static final RegExp _identifier = new RegExp(r'^[a-zA-Z_$][a-zA-Z0-9_$]*$');
 
-  final KernelToElementMap _elementMap;
+  final KernelToElementMapImpl _elementMap;
   final NativeBasicData _nativeBasicData;
   final NativeDataBuilder _nativeDataBuilder;
 
@@ -1953,25 +1980,28 @@
   CommonElements get _commonElements => _elementMap.commonElements;
 
   @override
-  void resolveNativeMember(MemberEntity element) {
+  void resolveNativeMember(
+      MemberEntity element, IrAnnotationData annotationData) {
     bool isJsInterop = _isJsInteropMember(element);
     if (element.isFunction ||
         element.isConstructor ||
         element.isGetter ||
         element.isSetter) {
       FunctionEntity method = element;
-      bool isNative = _processMethodAnnotations(method);
+      bool isNative = _processMethodAnnotations(method, annotationData);
       if (isNative || isJsInterop) {
-        NativeBehavior behavior =
-            _computeNativeMethodBehavior(method, isJsInterop: isJsInterop);
+        NativeBehavior behavior = _computeNativeMethodBehavior(
+            method, annotationData,
+            isJsInterop: isJsInterop);
         _nativeDataBuilder.setNativeMethodBehavior(method, behavior);
       }
     } else if (element.isField) {
       FieldEntity field = element;
-      bool isNative = _processFieldAnnotations(field);
+      bool isNative = _processFieldAnnotations(field, annotationData);
       if (isNative || isJsInterop) {
-        NativeBehavior fieldLoadBehavior =
-            _computeNativeFieldLoadBehavior(field, isJsInterop: isJsInterop);
+        NativeBehavior fieldLoadBehavior = _computeNativeFieldLoadBehavior(
+            field, annotationData,
+            isJsInterop: isJsInterop);
         NativeBehavior fieldStoreBehavior =
             _computeNativeFieldStoreBehavior(field);
         _nativeDataBuilder.setNativeFieldLoadBehavior(field, fieldLoadBehavior);
@@ -1983,17 +2013,18 @@
 
   /// Process the potentially native [field]. Adds information from metadata
   /// attributes. Returns `true` of [method] is native.
-  bool _processFieldAnnotations(covariant FieldEntity element) {
+  bool _processFieldAnnotations(
+      FieldEntity element, IrAnnotationData annotationData) {
     if (element.isInstanceMember &&
         _nativeBasicData.isNativeClass(element.enclosingClass)) {
       // Exclude non-instance (static) fields - they are not really native and
       // are compiled as isolate globals.  Access of a property of a constructor
       // function or a non-method property in the prototype chain, must be coded
       // using a JS-call.
-      _setNativeName(element);
+      _setNativeName(element, annotationData);
       return true;
     } else {
-      String name = _findJsNameFromAnnotation(element);
+      String name = _findJsNameFromAnnotation(element, annotationData);
       if (name != null) {
         failedAt(
             element,
@@ -2006,12 +2037,13 @@
 
   /// Process the potentially native [method]. Adds information from metadata
   /// attributes. Returns `true` of [method] is native.
-  bool _processMethodAnnotations(covariant FunctionEntity method) {
-    if (_isNativeMethod(method)) {
+  bool _processMethodAnnotations(
+      FunctionEntity method, IrAnnotationData annotationData) {
+    if (_isNativeMethod(method, annotationData)) {
       if (method.isStatic) {
-        _setNativeNameForStaticMethod(method);
+        _setNativeNameForStaticMethod(method, annotationData);
       } else {
-        _setNativeName(method);
+        _setNativeName(method, annotationData);
       }
       return true;
     }
@@ -2020,9 +2052,9 @@
 
   /// Sets the native name of [element], either from an annotation, or
   /// defaulting to the Dart name.
-  void _setNativeName(MemberEntity element) {
-    String name = _findJsNameFromAnnotation(element);
-    if (name == null) name = element.name;
+  void _setNativeName(MemberEntity element, IrAnnotationData annotationData) {
+    String name = _findJsNameFromAnnotation(element, annotationData);
+    name ??= element.name;
     _nativeDataBuilder.setNativeMemberName(element, name);
   }
 
@@ -2034,9 +2066,10 @@
   ///    use the declared @JSName as the expression
   /// 3. If [element] does not have a @JSName annotation, qualify the name of
   ///    the method with the @Native name of the enclosing class.
-  void _setNativeNameForStaticMethod(FunctionEntity element) {
-    String name = _findJsNameFromAnnotation(element);
-    if (name == null) name = element.name;
+  void _setNativeNameForStaticMethod(
+      FunctionEntity element, IrAnnotationData annotationData) {
+    String name = _findJsNameFromAnnotation(element, annotationData);
+    name ??= element.name;
     if (_isIdentifier(name)) {
       List<String> nativeNames =
           _nativeBasicData.getNativeTagsOfClass(element.enclosingClass);
@@ -2057,16 +2090,23 @@
 
   /// Returns the JSName annotation string or `null` if no JSName annotation is
   /// present.
-  String _findJsNameFromAnnotation(MemberEntity element) {
-    String jsName = null;
-    for (ConstantValue value
-        in _elementEnvironment.getMemberMetadata(element)) {
-      String name = readAnnotationName(
-          element, value, _commonElements.annotationJSNameClass);
-      if (jsName == null) {
-        jsName = name;
-      } else if (name != null) {
-        failedAt(element, 'Too many JSName annotations: ${value.toDartText()}');
+  String _findJsNameFromAnnotation(
+      MemberEntity element, IrAnnotationData annotationData) {
+    String jsName;
+    if (annotationData != null) {
+      jsName = annotationData
+          .getNativeMemberName(_elementMap.getMemberNode(element));
+    } else {
+      for (ConstantValue value
+          in _elementEnvironment.getMemberMetadata(element)) {
+        String name = readAnnotationName(
+            element, value, _commonElements.annotationJSNameClass);
+        if (jsName == null) {
+          jsName = name;
+        } else if (name != null) {
+          failedAt(
+              element, 'Too many JSName annotations: ${value.toDartText()}');
+        }
       }
     }
     return jsName;
@@ -2077,28 +2117,63 @@
     return _elementMap.getNativeBehaviorForFieldStore(node);
   }
 
-  NativeBehavior _computeNativeFieldLoadBehavior(covariant KField field,
+  NativeBehavior _computeNativeFieldLoadBehavior(
+      KField field, IrAnnotationData annotationData,
       {bool isJsInterop}) {
     ir.Field node = _elementMap.getMemberNode(field);
-    return _elementMap.getNativeBehaviorForFieldLoad(node,
+    Iterable<String> createsAnnotations;
+    Iterable<String> returnsAnnotations;
+    if (annotationData != null) {
+      createsAnnotations = annotationData.getCreatesAnnotations(node);
+      returnsAnnotations = annotationData.getReturnsAnnotations(node);
+    } else {
+      List<ConstantValue> metadata =
+          _elementEnvironment.getMemberMetadata(field);
+      createsAnnotations = getCreatesAnnotations(
+          _elementMap.reporter, _elementMap.commonElements, metadata);
+      returnsAnnotations = getReturnsAnnotations(
+          _elementMap.reporter, _elementMap.commonElements, metadata);
+    }
+    return _elementMap.getNativeBehaviorForFieldLoad(
+        node, createsAnnotations, returnsAnnotations,
         isJsInterop: isJsInterop);
   }
 
-  NativeBehavior _computeNativeMethodBehavior(covariant KFunction function,
+  NativeBehavior _computeNativeMethodBehavior(
+      KFunction function, IrAnnotationData annotationData,
       {bool isJsInterop}) {
     ir.Member node = _elementMap.getMemberNode(function);
-    return _elementMap.getNativeBehaviorForMethod(node,
+    Iterable<String> createsAnnotations;
+    Iterable<String> returnsAnnotations;
+    if (annotationData != null) {
+      createsAnnotations = annotationData.getCreatesAnnotations(node);
+      returnsAnnotations = annotationData.getReturnsAnnotations(node);
+    } else {
+      List<ConstantValue> metadata =
+          _elementEnvironment.getMemberMetadata(function);
+      createsAnnotations = getCreatesAnnotations(
+          _elementMap.reporter, _elementMap.commonElements, metadata);
+      returnsAnnotations = getReturnsAnnotations(
+          _elementMap.reporter, _elementMap.commonElements, metadata);
+    }
+    return _elementMap.getNativeBehaviorForMethod(
+        node, createsAnnotations, returnsAnnotations,
         isJsInterop: isJsInterop);
   }
 
-  bool _isNativeMethod(covariant KFunction function) {
+  bool _isNativeMethod(
+      covariant KFunction function, IrAnnotationData annotationData) {
     if (!maybeEnableNative(function.library.canonicalUri)) return false;
     ir.Member node = _elementMap.getMemberNode(function);
-    return node.annotations.any((ir.Expression expression) {
-      return expression is ir.ConstructorInvocation &&
-          _elementMap.getInterfaceType(expression.constructedType) ==
-              _commonElements.externalNameType;
-    });
+    if (annotationData != null) {
+      return annotationData.hasNativeBody(node);
+    } else {
+      return node.annotations.any((ir.Expression expression) {
+        return expression is ir.ConstructorInvocation &&
+            _elementMap.getInterfaceType(expression.constructedType) ==
+                _commonElements.externalNameType;
+      });
+    }
   }
 
   bool _isJsInteropMember(MemberEntity element) {
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index a721968..b7c9246 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -285,6 +285,7 @@
 
 /// Environment for fast lookup of class members.
 class KClassEnvImpl implements KClassEnv {
+  @override
   final ir.Class cls;
 
   Map<String, ir.Member> _constructorMap;
@@ -301,8 +302,10 @@
   KClassEnvImpl.internal(this.cls, this._constructorMap, this._memberMap,
       this._setterMap, this._members, this._isSuperMixinApplication);
 
+  @override
   bool get isUnnamedMixinApplication => cls.isAnonymousMixin;
 
+  @override
   bool get isSuperMixinApplication {
     assert(_isSuperMixinApplication != null);
     return _isSuperMixinApplication;
@@ -354,6 +357,7 @@
         initializers: <ir.Initializer>[superInitializer]);
   }
 
+  @override
   void ensureMembers(KernelToElementMapImpl elementMap) {
     _ensureMaps(elementMap);
   }
@@ -505,6 +509,7 @@
   /// Return the [MemberEntity] for the member [name] in [cls]. If [setter] is
   /// `true`, the setter or assignable field corresponding to [name] is
   /// returned.
+  @override
   MemberEntity lookupMember(IrToElementMap elementMap, String name,
       {bool setter: false}) {
     _ensureMaps(elementMap);
@@ -513,6 +518,7 @@
   }
 
   /// Calls [f] for each member of [cls].
+  @override
   void forEachMember(IrToElementMap elementMap, void f(MemberEntity member)) {
     _ensureMaps(elementMap);
     _members.forEach((ir.Member member) {
@@ -521,6 +527,7 @@
   }
 
   /// Return the [ConstructorEntity] for the constructor [name] in [cls].
+  @override
   ConstructorEntity lookupConstructor(IrToElementMap elementMap, String name) {
     _ensureMaps(elementMap);
     ir.Member constructor = _constructorMap[name];
@@ -528,6 +535,7 @@
   }
 
   /// Calls [f] for each constructor of [cls].
+  @override
   void forEachConstructor(
       IrToElementMap elementMap, void f(ConstructorEntity constructor)) {
     _ensureMaps(elementMap);
@@ -541,10 +549,12 @@
     _constructorBodyList.add(constructorBody);
   }
 
+  @override
   void forEachConstructorBody(void f(ConstructorBodyEntity constructor)) {
     _constructorBodyList?.forEach(f);
   }
 
+  @override
   JClassEnv convert(IrToElementMap elementMap,
       Map<MemberEntity, MemberUsage> liveMemberUsage) {
     Map<String, ir.Member> constructorMap;
@@ -621,30 +631,42 @@
 }
 
 class KClassDataImpl implements KClassData {
+  @override
   final ir.Class node;
+  @override
   bool isMixinApplication;
   bool isCallTypeComputed = false;
 
+  @override
   InterfaceType thisType;
+  @override
   InterfaceType rawType;
+  @override
   InterfaceType supertype;
+  @override
   InterfaceType mixedInType;
+  @override
   List<InterfaceType> interfaces;
+  @override
   OrderedTypeSet orderedTypeSet;
 
   Iterable<ConstantValue> _metadata;
 
   KClassDataImpl(this.node);
 
+  @override
   bool get isEnumClass => node.isEnum;
 
+  @override
   DartType get callType => null;
 
+  @override
   Iterable<ConstantValue> getMetadata(
       covariant KernelToElementMapImpl elementMap) {
     return _metadata ??= elementMap.getMetadata(node.annotations);
   }
 
+  @override
   JClassData convert() {
     return new JClassDataImpl(node, new RegularClassDefinition(node));
   }
@@ -666,19 +688,23 @@
 }
 
 abstract class KMemberDataImpl implements KMemberData {
+  @override
   final ir.Member node;
 
   Iterable<ConstantValue> _metadata;
 
+  @override
   Map<ir.Expression, ir.DartType> staticTypes;
 
   KMemberDataImpl(this.node);
 
+  @override
   Iterable<ConstantValue> getMetadata(
       covariant KernelToElementMapImpl elementMap) {
     return _metadata ??= elementMap.getMetadata(node.annotations);
   }
 
+  @override
   InterfaceType getMemberThisType(JsToElementMap elementMap) {
     MemberEntity member = elementMap.getMember(node);
     ClassEntity cls = member.enclosingClass;
@@ -702,6 +728,7 @@
   ir.FunctionNode get functionNode;
   List<TypeVariableType> _typeVariables;
 
+  @override
   List<TypeVariableType> getFunctionTypeVariables(
       covariant KernelToElementMapImpl elementMap) {
     if (_typeVariables == null) {
@@ -729,15 +756,18 @@
 class KFunctionDataImpl extends KMemberDataImpl
     with KFunctionDataMixin
     implements KFunctionData {
+  @override
   final ir.FunctionNode functionNode;
   FunctionType _type;
 
   KFunctionDataImpl(ir.Member node, this.functionNode) : super(node);
 
+  @override
   FunctionType getFunctionType(covariant KernelToElementMapImpl elementMap) {
     return _type ??= elementMap.getFunctionType(functionNode);
   }
 
+  @override
   void forEachParameter(JsToElementMap elementMap,
       void f(DartType type, String name, ConstantValue defaultValue)) {
     void handleParameter(ir.VariableDeclaration node, {bool isOptional: true}) {
@@ -789,6 +819,7 @@
   KConstructorDataImpl(ir.Member node, ir.FunctionNode functionNode)
       : super(node, functionNode);
 
+  @override
   ConstantConstructor getConstructorConstant(
       KernelToElementMapImpl elementMap, ConstructorEntity constructor) {
     if (_constantConstructor == null) {
@@ -835,12 +866,15 @@
 
   KFieldDataImpl(ir.Field node) : super(node);
 
+  @override
   ir.Field get node => super.node;
 
+  @override
   DartType getFieldType(covariant KernelToElementMapImpl elementMap) {
     return _type ??= elementMap.getDartType(node.type);
   }
 
+  @override
   ConstantExpression getFieldConstantExpression(
       KernelToElementMapImpl elementMap) {
     if (_constantExpression == null) {
diff --git a/pkg/compiler/lib/src/kernel/front_end_adapter.dart b/pkg/compiler/lib/src/kernel/front_end_adapter.dart
index 169237d..571f11f 100644
--- a/pkg/compiler/lib/src/kernel/front_end_adapter.dart
+++ b/pkg/compiler/lib/src/kernel/front_end_adapter.dart
@@ -32,6 +32,7 @@
 }
 
 class _CompilerFileSystemEntity implements fe.FileSystemEntity {
+  @override
   final Uri uri;
   final CompilerFileSystem fs;
 
diff --git a/pkg/compiler/lib/src/kernel/kelements.dart b/pkg/compiler/lib/src/kernel/kelements.dart
index 2f1a8f5..1ac70af 100644
--- a/pkg/compiler/lib/src/kernel/kelements.dart
+++ b/pkg/compiler/lib/src/kernel/kelements.dart
@@ -13,18 +13,24 @@
 const String kElementPrefix = 'k:';
 
 class KLibrary extends IndexedLibrary {
+  @override
   final String name;
+  @override
   final Uri canonicalUri;
 
   KLibrary(this.name, this.canonicalUri);
 
+  @override
   String toString() => '${kElementPrefix}library($name)';
 }
 
 class KClass extends IndexedClass {
+  @override
   final KLibrary library;
 
+  @override
   final String name;
+  @override
   final bool isAbstract;
 
   KClass(this.library, this.name, {this.isAbstract});
@@ -32,21 +38,27 @@
   @override
   bool get isClosure => false;
 
+  @override
   String toString() => '${kElementPrefix}class($name)';
 }
 
 class KTypedef extends IndexedTypedef {
+  @override
   final KLibrary library;
 
+  @override
   final String name;
 
   KTypedef(this.library, this.name);
 
+  @override
   String toString() => '${kElementPrefix}typedef($name)';
 }
 
 abstract class KMember extends IndexedMember {
+  @override
   final KLibrary library;
+  @override
   final KClass enclosingClass;
   final Name _name;
   final bool _isStatic;
@@ -54,8 +66,10 @@
   KMember(this.library, this.enclosingClass, this._name, {bool isStatic: false})
       : _isStatic = isStatic;
 
+  @override
   String get name => _name.text;
 
+  @override
   Name get memberName => _name;
 
   @override
@@ -93,14 +107,18 @@
 
   String get _kind;
 
+  @override
   String toString() => '${kElementPrefix}$_kind'
       '(${enclosingClass != null ? '${enclosingClass.name}.' : ''}$name)';
 }
 
 abstract class KFunction extends KMember
     implements FunctionEntity, IndexedFunction {
+  @override
   final ParameterStructure parameterStructure;
+  @override
   final bool isExternal;
+  @override
   final AsyncMarker asyncMarker;
 
   KFunction(KLibrary library, KClass enclosingClass, Name name,
@@ -111,6 +129,7 @@
 
 abstract class KConstructor extends KFunction
     implements ConstructorEntity, IndexedConstructor {
+  @override
   final bool isConst;
 
   KConstructor(
@@ -135,6 +154,7 @@
   @override
   bool get isFromEnvironmentConstructor => false;
 
+  @override
   String get _kind => 'constructor';
 }
 
@@ -170,6 +190,7 @@
 }
 
 class KMethod extends KFunction {
+  @override
   final bool isAbstract;
 
   KMethod(KLibrary library, KClass enclosingClass, Name name,
@@ -181,10 +202,12 @@
   @override
   bool get isFunction => true;
 
+  @override
   String get _kind => 'method';
 }
 
 class KGetter extends KFunction {
+  @override
   final bool isAbstract;
 
   KGetter(KLibrary library, KClass enclosingClass, Name name,
@@ -197,10 +220,12 @@
   @override
   bool get isGetter => true;
 
+  @override
   String get _kind => 'getter';
 }
 
 class KSetter extends KFunction {
+  @override
   final bool isAbstract;
 
   KSetter(KLibrary library, KClass enclosingClass, Name name,
@@ -215,11 +240,14 @@
   @override
   bool get isSetter => true;
 
+  @override
   String get _kind => 'setter';
 }
 
 class KField extends KMember implements FieldEntity, IndexedField {
+  @override
   final bool isAssignable;
+  @override
   final bool isConst;
 
   KField(KLibrary library, KClass enclosingClass, Name name,
@@ -229,21 +257,27 @@
   @override
   bool get isField => true;
 
+  @override
   String get _kind => 'field';
 }
 
 class KTypeVariable extends IndexedTypeVariable {
+  @override
   final Entity typeDeclaration;
+  @override
   final String name;
+  @override
   final int index;
 
   KTypeVariable(this.typeDeclaration, this.name, this.index);
 
+  @override
   String toString() =>
       '${kElementPrefix}type_variable(${typeDeclaration.name}.$name)';
 }
 
 class KLocalFunction implements Local {
+  @override
   final String name;
   final MemberEntity memberContext;
   final Entity executableContext;
@@ -253,19 +287,24 @@
   KLocalFunction(
       this.name, this.memberContext, this.executableContext, this.node);
 
+  @override
   String toString() => '${kElementPrefix}local_function'
       '(${memberContext.name}.${name ?? '<anonymous>'})';
 }
 
 class KLocalTypeVariable implements TypeVariableEntity {
+  @override
   final Entity typeDeclaration;
+  @override
   final String name;
+  @override
   final int index;
   DartType bound;
   DartType defaultType;
 
   KLocalTypeVariable(this.typeDeclaration, this.name, this.index);
 
+  @override
   String toString() =>
       '${kElementPrefix}local_type_variable(${typeDeclaration.name}.$name)';
 }
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index f65c5d6..2b2499e 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -21,6 +21,7 @@
 import '../ir/util.dart';
 import '../js_backend/annotations.dart';
 import '../js_backend/native_data.dart';
+import '../native/behavior.dart';
 import '../options.dart';
 import '../resolution/registry.dart' show ResolutionWorldImpactBuilder;
 import '../universe/call_structure.dart';
@@ -33,10 +34,15 @@
 /// Visitor that computes the world impact of a member.
 class KernelImpactBuilder extends ImpactBuilderBase
     with KernelImpactRegistryMixin {
+  @override
   final ResolutionWorldImpactBuilder impactBuilder;
+  @override
   final KernelToElementMap elementMap;
+  @override
   final DiagnosticReporter reporter;
+  @override
   final CompilerOptions _options;
+  @override
   final MemberEntity currentMember;
   final Set<PragmaAnnotation> _annotations;
 
@@ -47,12 +53,16 @@
         super(elementMap.typeEnvironment, elementMap.classHierarchy,
             variableScopeModel);
 
+  @override
   CommonElements get commonElements => elementMap.commonElements;
 
+  @override
   NativeBasicData get _nativeBasicData => elementMap.nativeBasicData;
 
+  @override
   bool get useAsserts => _options.enableUserAssertions;
 
+  @override
   bool get inferEffectivelyFinalVariableTypes =>
       !_annotations.contains(PragmaAnnotation.disableFinal);
 }
@@ -60,10 +70,15 @@
 /// Converts a [ImpactData] object based on kernel to the corresponding
 /// [ResolutionImpact] based on the K model.
 class KernelImpactConverter extends KernelImpactRegistryMixin {
+  @override
   final ResolutionWorldImpactBuilder impactBuilder;
+  @override
   final KernelToElementMap elementMap;
+  @override
   final DiagnosticReporter reporter;
+  @override
   final CompilerOptions _options;
+  @override
   final MemberEntity currentMember;
 
   KernelImpactConverter(
@@ -71,10 +86,13 @@
       : this.impactBuilder =
             new ResolutionWorldImpactBuilder('${currentMember}');
 
+  @override
   ir.TypeEnvironment get typeEnvironment => elementMap.typeEnvironment;
 
+  @override
   CommonElements get commonElements => elementMap.commonElements;
 
+  @override
   NativeBasicData get _nativeBasicData => elementMap.nativeBasicData;
 
   /// Converts a [ImpactData] object based on kernel to the corresponding
@@ -133,9 +151,18 @@
     if (field.isInstanceMember &&
         elementMap.isNativeClass(field.enclosingClass)) {
       MemberEntity member = elementMap.getMember(field);
+      // TODO(johnniwinther): NativeDataBuilder already has the native behavior
+      // at this point. Use that instead.
       bool isJsInterop = _nativeBasicData.isJsInteropMember(member);
-      impactBuilder.registerNativeData(elementMap
-          .getNativeBehaviorForFieldLoad(field, isJsInterop: isJsInterop));
+      List<ConstantValue> metadata =
+          elementMap.elementEnvironment.getMemberMetadata(member);
+      Iterable<String> createsAnnotations =
+          getCreatesAnnotations(reporter, commonElements, metadata);
+      Iterable<String> returnsAnnotations =
+          getReturnsAnnotations(reporter, commonElements, metadata);
+      impactBuilder.registerNativeData(elementMap.getNativeBehaviorForFieldLoad(
+          field, createsAnnotations, returnsAnnotations,
+          isJsInterop: isJsInterop));
       impactBuilder
           .registerNativeData(elementMap.getNativeBehaviorForFieldStore(field));
     }
@@ -145,9 +172,18 @@
   void registerConstructorNode(ir.Constructor constructor) {
     MemberEntity member = elementMap.getMember(constructor);
     if (constructor.isExternal && !commonElements.isForeignHelper(member)) {
+      // TODO(johnniwinther): NativeDataBuilder already has the native behavior
+      // at this point. Use that instead.
       bool isJsInterop = _nativeBasicData.isJsInteropMember(member);
-      impactBuilder.registerNativeData(elementMap
-          .getNativeBehaviorForMethod(constructor, isJsInterop: isJsInterop));
+      List<ConstantValue> metadata =
+          elementMap.elementEnvironment.getMemberMetadata(member);
+      Iterable<String> createsAnnotations =
+          getCreatesAnnotations(reporter, commonElements, metadata);
+      Iterable<String> returnsAnnotations =
+          getReturnsAnnotations(reporter, commonElements, metadata);
+      impactBuilder.registerNativeData(elementMap.getNativeBehaviorForMethod(
+          constructor, createsAnnotations, returnsAnnotations,
+          isJsInterop: isJsInterop));
     }
   }
 
@@ -182,9 +218,18 @@
   void registerProcedureNode(ir.Procedure procedure) {
     MemberEntity member = elementMap.getMember(procedure);
     if (procedure.isExternal && !commonElements.isForeignHelper(member)) {
+      // TODO(johnniwinther): NativeDataBuilder already has the native behavior
+      // at this point. Use that instead.
       bool isJsInterop = _nativeBasicData.isJsInteropMember(member);
-      impactBuilder.registerNativeData(elementMap
-          .getNativeBehaviorForMethod(procedure, isJsInterop: isJsInterop));
+      List<ConstantValue> metadata =
+          elementMap.elementEnvironment.getMemberMetadata(member);
+      Iterable<String> createsAnnotations =
+          getCreatesAnnotations(reporter, commonElements, metadata);
+      Iterable<String> returnsAnnotations =
+          getReturnsAnnotations(reporter, commonElements, metadata);
+      impactBuilder.registerNativeData(elementMap.getNativeBehaviorForMethod(
+          procedure, createsAnnotations, returnsAnnotations,
+          isJsInterop: isJsInterop));
     }
   }
 
@@ -284,6 +329,7 @@
     }
   }
 
+  @override
   void registerConstConstructorInvocationNode(ir.ConstructorInvocation node) {
     assert(node.isConst);
     ConstructorEntity constructor = elementMap.getConstructor(node.target);
@@ -669,6 +715,7 @@
     impactBuilder.registerFeature(Feature.THROW_EXPRESSION);
   }
 
+  @override
   void registerSyncForIn(ir.DartType iterableType) {
     // TODO(johnniwinther): Use receiver constraints for the dynamic uses in
     // strong mode.
@@ -678,6 +725,7 @@
     impactBuilder.registerDynamicUse(new DynamicUse(Selectors.moveNext));
   }
 
+  @override
   void registerAsyncForIn(ir.DartType iterableType) {
     // TODO(johnniwinther): Use receiver constraints for the dynamic uses in
     // strong mode.
@@ -687,14 +735,17 @@
     impactBuilder.registerDynamicUse(new DynamicUse(Selectors.moveNext));
   }
 
+  @override
   void registerCatch() {
     impactBuilder.registerFeature(Feature.CATCH_STATEMENT);
   }
 
+  @override
   void registerStackTrace() {
     impactBuilder.registerFeature(Feature.STACK_TRACE_IN_CATCH);
   }
 
+  @override
   void registerCatchType(ir.DartType type) {
     impactBuilder
         .registerTypeUse(new TypeUse.catchType(elementMap.getDartType(type)));
@@ -734,9 +785,8 @@
 
   @override
   void registerConstant(ir.ConstantExpression node) {
-    // ignore: unused_local_variable
     ConstantValue value = elementMap.getConstantValue(node);
-    // TODO(johnniwinther,fishythefish): Register the constant.
+    impactBuilder.registerConstantUse(new ConstantUse.literal(value));
   }
 
   @override
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index 7feda83..46f5293 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -4,6 +4,8 @@
 
 library dart2js.kernel.frontend_strategy;
 
+import 'package:kernel/ast.dart' as ir;
+
 import '../common.dart';
 import '../common/backend_api.dart';
 import '../common/resolution.dart';
@@ -19,6 +21,8 @@
 import '../frontend_strategy.dart';
 import '../ir/annotations.dart';
 import '../ir/closure.dart' show ClosureScopeModel;
+import '../ir/impact.dart';
+import '../ir/modular.dart';
 import '../ir/scope.dart' show ScopeModel;
 import '../js_backend/annotations.dart';
 import '../js_backend/field_analysis.dart' show KFieldAnalysis;
@@ -34,6 +38,7 @@
 import '../universe/resolution_world_builder.dart';
 import '../universe/world_builder.dart';
 import '../universe/world_impact.dart';
+import '../util/enumset.dart';
 import 'deferred_load.dart';
 import 'element_map.dart';
 import 'element_map_impl.dart';
@@ -51,26 +56,38 @@
 
   final Map<MemberEntity, ClosureScopeModel> closureModels = {};
 
+  ModularStrategy _modularStrategy;
+  IrAnnotationData _irAnnotationData;
+
   KernelFrontEndStrategy(this._compilerTask, this._options,
       DiagnosticReporter reporter, env.Environment environment) {
     assert(_compilerTask != null);
     _elementMap =
         new KernelToElementMapImpl(reporter, environment, this, _options);
+    _modularStrategy = new KernelModularStrategy(_compilerTask, _elementMap);
   }
 
   @override
   void registerLoadedLibraries(KernelResult kernelResult) {
     _elementMap.addComponent(kernelResult.component);
-    _annotationProcessor = new KernelAnnotationProcessor(elementMap,
-        nativeBasicDataBuilder, processAnnotations(kernelResult.component));
+    if (useIrAnnotationsDataForTesting) {
+      _irAnnotationData = processAnnotations(kernelResult.component);
+    }
+    _annotationProcessor = new KernelAnnotationProcessor(
+        elementMap, nativeBasicDataBuilder, _irAnnotationData);
   }
 
+  IrAnnotationData get irAnnotationDataForTesting => _irAnnotationData;
+
+  ModularStrategy get modularStrategyForTesting => _modularStrategy;
+
   @override
   ElementEnvironment get elementEnvironment => _elementMap.elementEnvironment;
 
   @override
   CommonElements get commonElements => _elementMap.commonElements;
 
+  @override
   DartTypes get dartTypes => _elementMap.types;
 
   KernelToElementMap get elementMap => _elementMap;
@@ -92,16 +109,19 @@
         _elementMap.elementEnvironment, nativeBasicData);
   }
 
+  @override
   NoSuchMethodResolver createNoSuchMethodResolver() {
     return new KernelNoSuchMethodResolver(elementMap);
   }
 
   /// Computes the main function from [mainLibrary] adding additional world
   /// impact to [impactBuilder].
+  @override
   FunctionEntity computeMain(WorldImpactBuilder impactBuilder) {
     return elementEnvironment.mainFunction;
   }
 
+  @override
   RuntimeTypesNeedBuilder createRuntimeTypesNeedBuilder() {
     return _runtimeTypesNeedBuilder ??= _options.disableRtiOptimization
         ? const TrivialRuntimeTypesNeedBuilder()
@@ -109,9 +129,11 @@
             elementEnvironment, _elementMap.types);
   }
 
+  @override
   RuntimeTypesNeedBuilder get runtimeTypesNeedBuilderForTesting =>
       _runtimeTypesNeedBuilder;
 
+  @override
   ResolutionWorldBuilder createResolutionWorldBuilder(
       NativeBasicData nativeBasicData,
       NativeDataBuilder nativeDataBuilder,
@@ -162,9 +184,12 @@
         impactTransformer,
         closureModels,
         impactCache,
-        fieldAnalysis);
+        fieldAnalysis,
+        _modularStrategy,
+        _irAnnotationData);
   }
 
+  @override
   ClassQueries createClassQueries() {
     return new KernelClassQueries(elementMap);
   }
@@ -184,6 +209,8 @@
   final Map<MemberEntity, ClosureScopeModel> _closureModels;
   final Map<Entity, WorldImpact> _impactCache;
   final KFieldAnalysis _fieldAnalysis;
+  final ModularStrategy _modularStrategy;
+  final IrAnnotationData _irAnnotationData;
 
   KernelWorkItemBuilder(
       this._compilerTask,
@@ -194,7 +221,9 @@
       this._impactTransformer,
       this._closureModels,
       this._impactCache,
-      this._fieldAnalysis)
+      this._fieldAnalysis,
+      this._modularStrategy,
+      this._irAnnotationData)
       : _nativeMemberResolver = new KernelNativeMemberResolver(
             _elementMap, nativeBasicData, nativeDataBuilder);
 
@@ -209,7 +238,9 @@
         entity,
         _closureModels,
         _impactCache,
-        _fieldAnalysis);
+        _fieldAnalysis,
+        _modularStrategy,
+        _irAnnotationData);
   }
 }
 
@@ -219,10 +250,13 @@
   final ImpactTransformer _impactTransformer;
   final NativeMemberResolver _nativeMemberResolver;
   final AnnotationsDataBuilder _annotationsDataBuilder;
+  @override
   final MemberEntity element;
   final Map<MemberEntity, ClosureScopeModel> _closureModels;
   final Map<Entity, WorldImpact> _impactCache;
   final KFieldAnalysis _fieldAnalysis;
+  final ModularStrategy _modularStrategy;
+  final IrAnnotationData _irAnnotationData;
 
   KernelWorkItem(
       this._compilerTask,
@@ -233,33 +267,44 @@
       this.element,
       this._closureModels,
       this._impactCache,
-      this._fieldAnalysis);
+      this._fieldAnalysis,
+      this._modularStrategy,
+      this._irAnnotationData);
 
   @override
   WorldImpact run() {
     return _compilerTask.measure(() {
-      _nativeMemberResolver.resolveNativeMember(element);
-      Set<PragmaAnnotation> annotations = processMemberAnnotations(
+      _nativeMemberResolver.resolveNativeMember(element, _irAnnotationData);
+      ir.Member node = _elementMap.getMemberNode(element);
+
+      List<PragmaAnnotationData> pragmaAnnotationData =
+          _modularStrategy.getPragmaAnnotationData(node);
+
+      EnumSet<PragmaAnnotation> annotations = processMemberAnnotations(
           _elementMap.options,
           _elementMap.reporter,
-          _elementMap.commonElements,
-          _elementMap.elementEnvironment,
-          _annotationsDataBuilder,
-          element);
-      ScopeModel scopeModel = _compilerTask.measureSubtask('closures', () {
-        ScopeModel scopeModel = _elementMap.computeScopeModel(element);
-        if (scopeModel?.closureScopeModel != null) {
-          _closureModels[element] = scopeModel.closureScopeModel;
-        }
-        if (element.isField && !element.isInstanceMember) {
-          _fieldAnalysis.registerStaticField(
-              element, scopeModel?.initializerComplexity);
-        }
-        return scopeModel;
-      });
+          _elementMap.getMemberNode(element),
+          pragmaAnnotationData);
+      _annotationsDataBuilder.registerPragmaAnnotations(element, annotations);
+
+      ModularMemberData modularMemberData =
+          _modularStrategy.getModularMemberData(node, annotations);
+      ScopeModel scopeModel = modularMemberData.scopeModel;
+      if (scopeModel.closureScopeModel != null) {
+        _closureModels[element] = scopeModel.closureScopeModel;
+      }
+      if (element.isField && !element.isInstanceMember) {
+        _fieldAnalysis.registerStaticField(
+            element, scopeModel.initializerComplexity);
+      }
+      ImpactBuilderData impactBuilderData = modularMemberData.impactBuilderData;
       return _compilerTask.measureSubtask('worldImpact', () {
         ResolutionImpact impact = _elementMap.computeWorldImpact(
-            element, scopeModel?.variableScopeModel, annotations);
+            element,
+            scopeModel.variableScopeModel,
+            new Set<PragmaAnnotation>.from(
+                annotations.iterable(PragmaAnnotation.values)),
+            impactBuilderData: impactBuilderData);
         WorldImpact worldImpact =
             _impactTransformer.transformResolutionImpact(impact);
         if (_impactCache != null) {
@@ -270,3 +315,52 @@
     });
   }
 }
+
+/// If `true` kernel impacts are computed as [ImpactData] directly on kernel
+/// and converted to the K model afterwards. This is a pre-step to modularizing
+/// the world impact computation.
+bool useImpactDataForTesting = false;
+
+/// If `true` pragma annotations are computed directly on kernel. This is a
+/// pre-step to modularizing the world impact computation.
+bool useIrAnnotationsDataForTesting = false;
+
+class KernelModularStrategy extends ModularStrategy {
+  final CompilerTask _compilerTask;
+  final KernelToElementMapImpl _elementMap;
+
+  KernelModularStrategy(this._compilerTask, this._elementMap);
+
+  @override
+  List<PragmaAnnotationData> getPragmaAnnotationData(ir.Member node) {
+    if (useIrAnnotationsDataForTesting) {
+      return computePragmaAnnotationDataFromIr(node);
+    } else {
+      return computePragmaAnnotationData(_elementMap.commonElements,
+          _elementMap.elementEnvironment, _elementMap.getMember(node));
+    }
+  }
+
+  @override
+  ModularMemberData getModularMemberData(
+      ir.Member node, EnumSet<PragmaAnnotation> annotations) {
+    ScopeModel scopeModel = _compilerTask.measureSubtask(
+        'closures', () => new ScopeModel.from(node));
+    ImpactBuilderData impactBuilderData;
+    if (useImpactDataForTesting) {
+      // TODO(johnniwinther): Always create and use the [ImpactBuilderData].
+      // Currently it is a bit half-baked since we cannot compute data that
+      // depend on metadata, so these parts of the impact data need to be
+      // computed during conversion to [ResolutionImpact].
+      impactBuilderData = _compilerTask.measureSubtask('worldImpact', () {
+        ImpactBuilder builder = new ImpactBuilder(_elementMap.typeEnvironment,
+            _elementMap.classHierarchy, scopeModel.variableScopeModel,
+            useAsserts: _elementMap.options.enableUserAssertions,
+            inferEffectivelyFinalVariableTypes:
+                !annotations.contains(PragmaAnnotation.disableFinal));
+        return builder.computeImpact(node);
+      });
+    }
+    return new ModularMemberData(scopeModel, impactBuilderData);
+  }
+}
diff --git a/pkg/compiler/lib/src/kernel/kernel_world.dart b/pkg/compiler/lib/src/kernel/kernel_world.dart
index 673ba75..053c528 100644
--- a/pkg/compiler/lib/src/kernel/kernel_world.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_world.dart
@@ -24,33 +24,49 @@
 
 class KClosedWorldImpl implements KClosedWorld {
   final KernelToElementMapImpl elementMap;
+  @override
   final KElementEnvironment elementEnvironment;
+  @override
   final DartTypes dartTypes;
+  @override
   final KCommonElements commonElements;
+  @override
   final NativeData nativeData;
+  @override
   final InterceptorData interceptorData;
+  @override
   final BackendUsage backendUsage;
+  @override
   final NoSuchMethodData noSuchMethodData;
 
+  @override
   final Map<ClassEntity, Set<ClassEntity>> mixinUses;
 
+  @override
   final Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses;
 
   // TODO(johnniwinther): Can this be derived from [ClassSet]s?
   final Set<ClassEntity> _implementedClasses;
 
+  @override
   final Iterable<MemberEntity> liveInstanceMembers;
 
   /// Members that are written either directly or through a setter selector.
+  @override
   final Iterable<MemberEntity> assignedInstanceMembers;
+  @override
   final KFieldAnalysis fieldAnalysis;
 
+  @override
   final Iterable<ClassEntity> liveNativeClasses;
 
+  @override
   final Map<MemberEntity, MemberUsage> liveMemberUsage;
 
+  @override
   final ClassHierarchy classHierarchy;
 
+  @override
   final AnnotationsData annotationsData;
 
   RuntimeTypesNeed _rtiNeed;
@@ -81,9 +97,11 @@
         resolutionWorldBuilder, this, options);
   }
 
+  @override
   RuntimeTypesNeed get rtiNeed => _rtiNeed;
 
   /// Returns `true` if [cls] is implemented by an instantiated class.
+  @override
   bool isImplemented(ClassEntity cls) {
     return _implementedClasses.contains(cls);
   }
diff --git a/pkg/compiler/lib/src/kernel/loader.dart b/pkg/compiler/lib/src/kernel/loader.dart
index 7b56f28..b972976 100644
--- a/pkg/compiler/lib/src/kernel/loader.dart
+++ b/pkg/compiler/lib/src/kernel/loader.dart
@@ -51,6 +51,7 @@
       : initializedCompilerState = _options.kernelInitializedCompilerState,
         super(measurer);
 
+  @override
   String get name => 'kernel loader';
 
   /// Loads an entire Kernel [Component] from a file on disk.
@@ -157,5 +158,6 @@
     assert(rootLibraryUri != null);
   }
 
+  @override
   String toString() => 'root=$rootLibraryUri,libraries=${libraries}';
 }
diff --git a/pkg/compiler/lib/src/kernel/native_basic_data.dart b/pkg/compiler/lib/src/kernel/native_basic_data.dart
index 8bcc052..745afa5 100644
--- a/pkg/compiler/lib/src/kernel/native_basic_data.dart
+++ b/pkg/compiler/lib/src/kernel/native_basic_data.dart
@@ -13,14 +13,17 @@
   KernelAnnotationProcessor(
       this.elementMap, this._nativeBasicDataBuilder, this.annotationData);
 
+  @override
   void extractNativeAnnotations(LibraryEntity library) {
     KElementEnvironment elementEnvironment = elementMap.elementEnvironment;
     KCommonElements commonElements = elementMap.commonElements;
 
     elementEnvironment.forEachClass(library, (ClassEntity cls) {
       ir.Class node = elementMap.getClassNode(cls);
-      String annotationName = annotationData.getNativeClassName(node);
-      if (annotationName == null) {
+      String annotationName;
+      if (annotationData != null) {
+        annotationName = annotationData.getNativeClassName(node);
+      } else {
         // TODO(johnniwinther): Remove this branch when we use constants from
         // CFE.
         for (ConstantValue value in elementEnvironment.getClassMetadata(cls)) {
@@ -66,25 +69,34 @@
     }
   }
 
+  @override
   void extractJsInteropAnnotations(LibraryEntity library) {
     DiagnosticReporter reporter = elementMap.reporter;
     KElementEnvironment elementEnvironment = elementMap.elementEnvironment;
     KCommonElements commonElements = elementMap.commonElements;
 
     ir.Library libraryNode = elementMap.getLibraryNode(library);
-    String libraryName = annotationData.getJsInteropLibraryName(libraryNode);
-    // TODO(johnniwinther): Remove this when we use constants from CFE.
-    libraryName ??= getJsInteropName(
-        library, elementEnvironment.getLibraryMetadata(library));
+    String libraryName;
+    if (annotationData != null) {
+      libraryName = annotationData.getJsInteropLibraryName(libraryNode);
+    } else {
+      // TODO(johnniwinther): Remove this when we use constants from CFE.
+      libraryName = getJsInteropName(
+          library, elementEnvironment.getLibraryMetadata(library));
+    }
     final bool isExplicitlylyJsLibrary = libraryName != null;
     bool isJsLibrary = isExplicitlylyJsLibrary;
 
     elementEnvironment.forEachLibraryMember(library, (MemberEntity member) {
       ir.Member memberNode = elementMap.getMemberNode(member);
-      String memberName = annotationData.getJsInteropMemberName(memberNode);
-      // TODO(johnniwinther): Remove this when we use constants from CFE.
-      memberName ??= getJsInteropName(
-          library, elementEnvironment.getMemberMetadata(member));
+      String memberName;
+      if (annotationData != null) {
+        memberName = annotationData.getJsInteropMemberName(memberNode);
+      } else {
+        // TODO(johnniwinther): Remove this when we use constants from CFE.
+        memberName = getJsInteropName(
+            library, elementEnvironment.getMemberMetadata(member));
+      }
       if (member.isField) {
         if (memberName != null) {
           // TODO(34174): Disallow js-interop fields.
@@ -119,15 +131,22 @@
     });
 
     elementEnvironment.forEachClass(library, (ClassEntity cls) {
+      Iterable<ConstantValue> metadata;
       ir.Class classNode = elementMap.getClassNode(cls);
-      String className = annotationData.getJsInteropClassName(classNode);
-      Iterable<ConstantValue> metadata =
-          elementEnvironment.getClassMetadata(cls);
-      // TODO(johnniwinther): Remove this when we use constants from CFE.
-      className ??= getJsInteropName(cls, metadata);
+      String className;
+      if (annotationData != null) {
+        className = annotationData.getJsInteropClassName(classNode);
+      } else {
+        metadata = elementEnvironment.getClassMetadata(cls);
+        // TODO(johnniwinther): Remove this when we use constants from CFE.
+        className = getJsInteropName(cls, metadata);
+      }
       if (className != null) {
-        bool isAnonymous = annotationData.isAnonymousJsInteropClass(classNode);
-        if (!isAnonymous) {
+        bool isAnonymous;
+        if (annotationData != null) {
+          isAnonymous = annotationData.isAnonymousJsInteropClass(classNode);
+        } else {
+          isAnonymous = false;
           // TODO(johnniwinther): Remove this branch when we use constants from
           // CFE.
           for (ConstantValue value in metadata) {
@@ -153,12 +172,14 @@
           } else {
             FunctionEntity function = member;
             ir.Member memberNode = elementMap.getMemberNode(member);
-            String memberName =
-                annotationData.getJsInteropMemberName(memberNode);
-            // TODO(johnniwinther): Remove this when we use constants from CFE.
-            memberName ??= getJsInteropName(
-                library, elementEnvironment.getMemberMetadata(function));
-
+            String memberName;
+            if (annotationData != null) {
+              memberName = annotationData.getJsInteropMemberName(memberNode);
+            } else {
+              // TODO(johnniwinther): Remove this when we use constants from CFE.
+              memberName = getJsInteropName(
+                  library, elementEnvironment.getMemberMetadata(function));
+            }
             if (function.isExternal) {
               memberName ??= function.name;
             }
@@ -278,10 +299,14 @@
       // it.
       elementEnvironment.forEachClass(library, (ClassEntity cls) {
         ir.Class classNode = elementMap.getClassNode(cls);
-        String className = annotationData.getJsInteropClassName(classNode);
-        // TODO(johnniwinther): Remove this when we use constants from CFE.
-        className ??=
-            getJsInteropName(cls, elementEnvironment.getClassMetadata(cls));
+        String className;
+        if (annotationData != null) {
+          className = annotationData.getJsInteropClassName(classNode);
+        } else {
+          // TODO(johnniwinther): Remove this when we use constants from CFE.
+          className ??=
+              getJsInteropName(cls, elementEnvironment.getClassMetadata(cls));
+        }
         if (className != null) {
           bool implementsJsJavaScriptObjectClass = false;
           elementEnvironment.forEachSupertype(cls, (InterfaceType supertype) {
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 07e03da..5bb7e12 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -24,8 +24,10 @@
   /// The type Object, but no subtypes:
   static const JsObject = const SpecialType._('=Object');
 
+  @override
   int get hashCode => name.hashCode;
 
+  @override
   String toString() => name;
 
   static SpecialType fromName(String name) {
@@ -68,6 +70,7 @@
     return this;
   }
 
+  @override
   String toString() {
     if (this == NEVER) return 'never';
     if (this == MAY) return 'may';
@@ -258,6 +261,7 @@
     sink.end(tag);
   }
 
+  @override
   String toString() {
     return 'NativeBehavior('
         'returns: ${typesReturned}'
@@ -736,14 +740,12 @@
 
   NativeBehavior _behavior;
 
-  void _overrideWithAnnotations(
-      Iterable<ConstantValue> metadata, TypeLookup lookupType) {
-    if (metadata.isEmpty) return;
+  void _overrideWithAnnotations(Iterable<String> createsAnnotations,
+      Iterable<String> returnsAnnotations, TypeLookup lookupType) {
+    if (createsAnnotations.isEmpty && returnsAnnotations.isEmpty) return;
 
-    List creates =
-        _collect(metadata, commonElements.annotationCreatesClass, lookupType);
-    List returns =
-        _collect(metadata, commonElements.annotationReturnsClass, lookupType);
+    List creates = _collect(createsAnnotations, lookupType);
+    List returns = _collect(returnsAnnotations, lookupType);
 
     if (creates != null) {
       _behavior.typesInstantiated
@@ -760,22 +762,9 @@
   /// Returns a list of type constraints from the annotations of
   /// [annotationClass].
   /// Returns `null` if no constraints.
-  List _collect(Iterable<ConstantValue> metadata, ClassEntity annotationClass,
-      TypeLookup lookupType) {
+  List _collect(Iterable<String> annotations, TypeLookup lookupType) {
     var types = null;
-    for (ConstantValue value in metadata) {
-      if (!value.isConstructedObject) continue;
-      ConstructedConstantValue constructedObject = value;
-      if (constructedObject.type.element != annotationClass) continue;
-
-      Iterable<ConstantValue> fields = constructedObject.fields.values;
-      // TODO(sra): Better validation of the constant.
-      if (fields.length != 1 || !fields.single.isString) {
-        reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
-            'Annotations needs one string: ${value.toStructuredText()}');
-      }
-      StringConstantValue specStringConstant = fields.single;
-      String specString = specStringConstant.stringValue;
+    for (String specString in annotations) {
       for (final typeString in specString.split('|')) {
         var type = NativeBehavior._parseType(typeString, lookupType);
         if (types == null) types = [];
@@ -847,7 +836,10 @@
   }
 
   NativeBehavior buildFieldLoadBehavior(
-      DartType type, Iterable<ConstantValue> metadata, TypeLookup lookupType,
+      DartType type,
+      Iterable<String> createsAnnotations,
+      Iterable<String> returnsAnnotations,
+      TypeLookup lookupType,
       {bool isJsInterop}) {
     _behavior = new NativeBehavior();
     // TODO(sigmund,sra): consider doing something better for numeric types.
@@ -857,7 +849,8 @@
     // Declared types are nullable.
     _behavior.typesReturned.add(commonElements.nullType);
     _capture(type, isJsInterop);
-    _overrideWithAnnotations(metadata, lookupType);
+    _overrideWithAnnotations(
+        createsAnnotations, returnsAnnotations, lookupType);
     return _behavior;
   }
 
@@ -869,8 +862,11 @@
     return _behavior;
   }
 
-  NativeBehavior buildMethodBehavior(FunctionType type,
-      Iterable<ConstantValue> metadata, TypeLookup lookupType,
+  NativeBehavior buildMethodBehavior(
+      FunctionType type,
+      Iterable<String> createAnnotations,
+      Iterable<String> returnsAnnotations,
+      TypeLookup lookupType,
       {bool isJsInterop}) {
     _behavior = new NativeBehavior();
     DartType returnType = type.returnType;
@@ -899,7 +895,40 @@
       _escape(type, isJsInterop);
     }
 
-    _overrideWithAnnotations(metadata, lookupType);
+    _overrideWithAnnotations(createAnnotations, returnsAnnotations, lookupType);
     return _behavior;
   }
 }
+
+List<String> _getAnnotations(DiagnosticReporter reporter,
+    Iterable<ConstantValue> metadata, ClassEntity cls) {
+  List<String> annotations = [];
+  for (ConstantValue value in metadata) {
+    if (!value.isConstructedObject) continue;
+    ConstructedConstantValue constructedObject = value;
+    if (constructedObject.type.element != cls) continue;
+
+    Iterable<ConstantValue> fields = constructedObject.fields.values;
+    // TODO(sra): Better validation of the constant.
+    if (fields.length != 1 || !fields.single.isString) {
+      reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
+          'Annotations needs one string: ${value.toStructuredText()}');
+    }
+    StringConstantValue specStringConstant = fields.single;
+    String specString = specStringConstant.stringValue;
+    annotations.add(specString);
+  }
+  return annotations;
+}
+
+List<String> getCreatesAnnotations(DiagnosticReporter reporter,
+    CommonElements commonElements, Iterable<ConstantValue> metadata) {
+  return _getAnnotations(
+      reporter, metadata, commonElements.annotationCreatesClass);
+}
+
+List<String> getReturnsAnnotations(DiagnosticReporter reporter,
+    CommonElements commonElements, Iterable<ConstantValue> metadata) {
+  return _getAnnotations(
+      reporter, metadata, commonElements.annotationReturnsClass);
+}
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index dfd4b8f..4552d00 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -40,6 +40,7 @@
   final Set<ClassEntity> _registeredClasses = new Set<ClassEntity>();
   final Set<ClassEntity> _unusedClasses = new Set<ClassEntity>();
 
+  @override
   bool get hasInstantiatedNativeClasses => !_registeredClasses.isEmpty;
 
   /// Log message reported if all native types are used.
@@ -56,6 +57,7 @@
 
   bool get enableLiveTypeAnalysis => _options.enableNativeLiveTypeAnalysis;
 
+  @override
   void onInstantiatedType(InterfaceType type) {
     if (_unusedClasses.remove(type.element)) {
       _registeredClasses.add(type.element);
@@ -77,6 +79,7 @@
     }
   }
 
+  @override
   void registerNativeBehavior(
       WorldImpactBuilder impactBuilder, NativeBehavior nativeBehavior, cause) {
     _processNativeBehavior(impactBuilder, nativeBehavior, cause);
@@ -161,6 +164,7 @@
     });
   }
 
+  @override
   void logSummary(void log(String message)) {
     if (_allUsedMessage != null) {
       log(_allUsedMessage);
@@ -189,6 +193,7 @@
 
   Iterable<ClassEntity> get liveNativeClasses => _registeredClasses;
 
+  @override
   WorldImpact processNativeClasses(Iterable<Uri> libraries) {
     WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
     Iterable<ClassEntity> nativeClasses =
@@ -201,6 +206,7 @@
     return impactBuilder;
   }
 
+  @override
   void logSummary(void log(String message)) {
     super.logSummary(log);
     log('Resolved ${_registeredClasses.length} native elements used, '
@@ -225,6 +231,7 @@
       this._nativeData)
       : super(options, elementEnvironment, commonElements, dartTypes);
 
+  @override
   WorldImpact processNativeClasses(Iterable<Uri> libraries) {
     WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
     _unusedClasses.addAll(_nativeClasses);
@@ -247,6 +254,7 @@
     return impactBuilder;
   }
 
+  @override
   void _registerTypeUses(
       WorldImpactBuilder impactBuilder, Set<ClassEntity> classes, cause) {
     super._registerTypeUses(impactBuilder, classes, cause);
@@ -288,6 +296,7 @@
     directSubtypes.add(cls);
   }
 
+  @override
   void logSummary(void log(String message)) {
     super.logSummary(log);
     log('Compiled ${_registeredClasses.length} native classes, '
diff --git a/pkg/compiler/lib/src/native/js.dart b/pkg/compiler/lib/src/native/js.dart
index 0c83197..bbc8bd0 100644
--- a/pkg/compiler/lib/src/native/js.dart
+++ b/pkg/compiler/lib/src/native/js.dart
@@ -41,18 +41,21 @@
     node.accept(this);
   }
 
+  @override
   void visitLiteralExpression(js.LiteralExpression node) {
     sideEffects.setAllSideEffects();
     sideEffects.setDependsOnSomething();
     node.visitChildren(this);
   }
 
+  @override
   void visitLiteralStatement(js.LiteralStatement node) {
     sideEffects.setAllSideEffects();
     sideEffects.setDependsOnSomething();
     node.visitChildren(this);
   }
 
+  @override
   void visitAssignment(js.Assignment node) {
     sideEffects.setChangesStaticProperty();
     sideEffects.setChangesInstanceProperty();
@@ -60,32 +63,38 @@
     node.visitChildren(this);
   }
 
+  @override
   void visitVariableInitialization(js.VariableInitialization node) {
     node.visitChildren(this);
   }
 
+  @override
   void visitCall(js.Call node) {
     sideEffects.setAllSideEffects();
     sideEffects.setDependsOnSomething();
     node.visitChildren(this);
   }
 
+  @override
   void visitBinary(js.Binary node) {
     node.visitChildren(this);
   }
 
+  @override
   void visitThrow(js.Throw node) {
     // TODO(ngeoffray): Incorporate a mayThrow flag in the
     // [SideEffects] class.
     sideEffects.setAllSideEffects();
   }
 
+  @override
   void visitNew(js.New node) {
     sideEffects.setAllSideEffects();
     sideEffects.setDependsOnSomething();
     node.visitChildren(this);
   }
 
+  @override
   void visitPrefix(js.Prefix node) {
     if (node.op == 'delete') {
       sideEffects.setChangesStaticProperty();
@@ -95,14 +104,17 @@
     node.visitChildren(this);
   }
 
+  @override
   void visitVariableUse(js.VariableUse node) {
     sideEffects.setDependsOnStaticPropertyStore();
   }
 
+  @override
   void visitPostfix(js.Postfix node) {
     node.visitChildren(this);
   }
 
+  @override
   void visitAccess(js.PropertyAccess node) {
     sideEffects.setDependsOnIndexStore();
     sideEffects.setDependsOnInstancePropertyStore();
@@ -149,43 +161,53 @@
     return node.accept(this);
   }
 
+  @override
   NativeThrowBehavior visitNode(js.Node node) {
     return NativeThrowBehavior.MAY;
   }
 
+  @override
   NativeThrowBehavior visitLiteral(js.Literal node) {
     return NativeThrowBehavior.NEVER;
   }
 
+  @override
   NativeThrowBehavior visitInterpolatedExpression(js.InterpolatedNode node) {
     return NativeThrowBehavior.NEVER;
   }
 
+  @override
   NativeThrowBehavior visitInterpolatedSelector(js.InterpolatedNode node) {
     return NativeThrowBehavior.NEVER;
   }
 
+  @override
   NativeThrowBehavior visitArrayInitializer(js.ArrayInitializer node) {
     return node.elements.map(visit).fold(NativeThrowBehavior.NEVER, sequence);
   }
 
+  @override
   NativeThrowBehavior visitArrayHole(js.ArrayHole node) {
     return NativeThrowBehavior.NEVER;
   }
 
+  @override
   NativeThrowBehavior visitObjectInitializer(js.ObjectInitializer node) {
     return node.properties.map(visit).fold(NativeThrowBehavior.NEVER, sequence);
   }
 
+  @override
   NativeThrowBehavior visitProperty(js.Property node) {
     return sequence(visit(node.name), visit(node.value));
   }
 
+  @override
   NativeThrowBehavior visitAssignment(js.Assignment node) {
     // TODO(sra): Can we make "#.p = #" be null(1)?
     return NativeThrowBehavior.MAY;
   }
 
+  @override
   NativeThrowBehavior visitCall(js.Call node) {
     js.Expression target = node.target;
     if (target is js.PropertyAccess && _isFirstInterpolatedProperty(target)) {
@@ -201,11 +223,13 @@
     return NativeThrowBehavior.MAY;
   }
 
+  @override
   NativeThrowBehavior visitNew(js.New node) {
     // TODO(sra): `new Array(x)` where `x` is a small number.
     return NativeThrowBehavior.MAY;
   }
 
+  @override
   NativeThrowBehavior visitBinary(js.Binary node) {
     NativeThrowBehavior left = visit(node.left);
     NativeThrowBehavior right = visit(node.right);
@@ -248,10 +272,12 @@
     }
   }
 
+  @override
   NativeThrowBehavior visitThrow(js.Throw node) {
     return sequence(visit(node.expression), NativeThrowBehavior.MAY);
   }
 
+  @override
   NativeThrowBehavior visitPrefix(js.Prefix node) {
     if (node.op == 'typeof' && node.argument is js.VariableUse)
       return NativeThrowBehavior.NEVER;
@@ -269,6 +295,7 @@
     }
   }
 
+  @override
   NativeThrowBehavior visitVariableUse(js.VariableUse node) {
     // We could get a ReferenceError unless the variable is in scope. The AST
     // could distinguish in-scope and out-of scope references. For JS fragments,
@@ -284,6 +311,7 @@
     }
   }
 
+  @override
   NativeThrowBehavior visitAccess(js.PropertyAccess node) {
     js.Node receiver = node.receiver;
     NativeThrowBehavior first = visit(receiver);
diff --git a/pkg/compiler/lib/src/native/resolver.dart b/pkg/compiler/lib/src/native/resolver.dart
index 2b4ad8a..8a9ed11 100644
--- a/pkg/compiler/lib/src/native/resolver.dart
+++ b/pkg/compiler/lib/src/native/resolver.dart
@@ -6,12 +6,14 @@
 import '../common_elements.dart' show KElementEnvironment;
 import '../constants/values.dart';
 import '../elements/entities.dart';
+import '../ir/annotations.dart';
 import '../js_backend/native_data.dart';
 
 /// Interface for computing native members.
 abstract class NativeMemberResolver {
   /// Computes whether [element] is native or JsInterop.
-  void resolveNativeMember(MemberEntity element);
+  void resolveNativeMember(
+      MemberEntity element, IrAnnotationData annotationData);
 }
 
 /// Determines all native classes in a set of libraries.
@@ -28,6 +30,7 @@
 
   BaseNativeClassFinder(this._elementEnvironment, this._nativeBasicData);
 
+  @override
   Iterable<ClassEntity> computeNativeClasses(Iterable<Uri> libraries) {
     Set<ClassEntity> nativeClasses = new Set<ClassEntity>();
     libraries.forEach((uri) => _processNativeClassesInLibrary(
diff --git a/pkg/compiler/lib/src/null_compiler_output.dart b/pkg/compiler/lib/src/null_compiler_output.dart
index 95206bb..b01e544 100644
--- a/pkg/compiler/lib/src/null_compiler_output.dart
+++ b/pkg/compiler/lib/src/null_compiler_output.dart
@@ -29,10 +29,13 @@
 
   NullSink(this.name);
 
+  @override
   void add(String value) {}
 
+  @override
   void close() {}
 
+  @override
   String toString() => name;
 
   /// Convenience method for getting an [api.CompilerOutputProvider].
@@ -53,5 +56,6 @@
   @override
   void close() {}
 
+  @override
   String toString() => 'NullBinarySink($uri)';
 }
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index c9c8862..9ee2539 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -136,15 +136,19 @@
   bool disableProgramSplit = false;
 
   /// Diagnostic option: If `true`, warnings cause the compilation to fail.
+  @override
   bool fatalWarnings = false;
 
   /// Diagnostic option: Emit terse diagnostics without howToFix.
+  @override
   bool terseDiagnostics = false;
 
   /// Diagnostic option: If `true`, warnings are not reported.
+  @override
   bool suppressWarnings = false;
 
   /// Diagnostic option: If `true`, hints are not reported.
+  @override
   bool suppressHints = false;
 
   /// Diagnostic option: List of packages for which warnings and hints are
@@ -449,14 +453,17 @@
   }
 
   /// Returns `true` if warnings and hints are shown for all packages.
+  @override
   bool get showAllPackageWarnings {
     return shownPackageWarnings != null && shownPackageWarnings.isEmpty;
   }
 
   /// Returns `true` if warnings and hints are hidden for all packages.
+  @override
   bool get hidePackageWarnings => shownPackageWarnings == null;
 
   /// Returns `true` if warnings should be should for [uri].
+  @override
   bool showPackageWarningsFor(Uri uri) {
     if (showAllPackageWarnings) {
       return true;
@@ -485,6 +492,7 @@
   static const trusted = const CheckPolicy(isTrusted: true);
   static const checked = const CheckPolicy(isEmitted: true);
 
+  @override
   String toString() => 'CheckPolicy(isTrusted=$isTrusted,'
       'isEmitted=$isEmitted)';
 }
diff --git a/pkg/compiler/lib/src/ordered_typeset.dart b/pkg/compiler/lib/src/ordered_typeset.dart
index efec511..ce4ff17 100644
--- a/pkg/compiler/lib/src/ordered_typeset.dart
+++ b/pkg/compiler/lib/src/ordered_typeset.dart
@@ -175,6 +175,7 @@
     return null;
   }
 
+  @override
   String toString() => types.toString();
 }
 
@@ -213,6 +214,7 @@
   int getHierarchyDepth(covariant ClassEntity cls);
   OrderedTypeSet getOrderedTypeSet(covariant ClassEntity cls);
 
+  @override
   OrderedTypeSet createOrderedTypeSet(
       InterfaceType supertype, Link<DartType> interfaces) {
     // TODO(15296): Collapse these iterations to one when the order is not
@@ -305,6 +307,7 @@
     return new OrderedTypeSet.internal(levels, levels.last);
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     for (int depth = 0; depth <= maxDepth; depth++) {
diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart
index 853beb3..9fdb9bb 100644
--- a/pkg/compiler/lib/src/resolution/registry.dart
+++ b/pkg/compiler/lib/src/resolution/registry.dart
@@ -103,6 +103,7 @@
     _constantLiterals.add(constant);
   }
 
+  @override
   Iterable<ConstantExpression> get constantLiterals {
     return _constantLiterals != null
         ? _constantLiterals
@@ -140,6 +141,7 @@
     return _genericInstantiations ?? const <GenericInstantiation>[];
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('ResolutionWorldImpactBuilder($name)');
diff --git a/pkg/compiler/lib/src/serialization/abstract_sink.dart b/pkg/compiler/lib/src/serialization/abstract_sink.dart
index 0c95e75..737c314 100644
--- a/pkg/compiler/lib/src/serialization/abstract_sink.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_sink.dart
@@ -43,6 +43,7 @@
     _importIndex = new IndexedSink<ImportEntity>(this);
   }
 
+  @override
   void begin(String tag) {
     if (useDataKinds) {
       _tags ??= <String>[];
@@ -51,6 +52,7 @@
     }
   }
 
+  @override
   void end(Object tag) {
     if (useDataKinds) {
       _end(tag);
@@ -207,6 +209,7 @@
     _writeIntInternal(value);
   }
 
+  @override
   void writeTreeNode(ir.TreeNode value) {
     _writeDataKind(DataKind.treeNode);
     _writeTreeNode(value);
@@ -294,22 +297,27 @@
     if (useDataKinds) _writeEnumInternal(kind);
   }
 
+  @override
   void writeLibrary(IndexedLibrary value) {
     writeInt(value.libraryIndex);
   }
 
+  @override
   void writeClass(IndexedClass value) {
     writeInt(value.classIndex);
   }
 
+  @override
   void writeTypedef(IndexedTypedef value) {
     writeInt(value.typedefIndex);
   }
 
+  @override
   void writeMember(IndexedMember value) {
     writeInt(value.memberIndex);
   }
 
+  @override
   void writeLocal(Local local) {
     if (local is JLocal) {
       writeEnum(LocalKind.jLocal);
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index a78fbea..b9660bd 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -27,14 +27,17 @@
     _importIndex = new IndexedSource<ImportEntity>(this);
   }
 
+  @override
   void begin(String tag) {
     if (useDataKinds) _begin(tag);
   }
 
+  @override
   void end(String tag) {
     if (useDataKinds) _end(tag);
   }
 
+  @override
   void registerComponentLookup(ComponentLookup componentLookup) {
     assert(_componentLookup == null);
     _componentLookup = componentLookup;
@@ -45,6 +48,7 @@
     return _componentLookup;
   }
 
+  @override
   void registerEntityLookup(EntityLookup entityLookup) {
     assert(_entityLookup == null);
     _entityLookup = entityLookup;
@@ -55,6 +59,7 @@
     return _entityLookup;
   }
 
+  @override
   void registerLocalLookup(LocalLookup localLookup) {
     assert(_localLookup == null);
     _localLookup = localLookup;
@@ -71,18 +76,22 @@
     return source.read(f);
   }
 
+  @override
   IndexedLibrary readLibrary() {
     return getIndexedLibrary(readInt());
   }
 
+  @override
   IndexedClass readClass() {
     return getIndexedClass(readInt());
   }
 
+  @override
   IndexedTypedef readTypedef() {
     return getIndexedTypedef(readInt());
   }
 
+  @override
   IndexedMember readMember() {
     return getIndexedMember(readInt());
   }
@@ -409,6 +418,7 @@
     return _readConstant();
   }
 
+  @override
   double readDoubleValue() {
     _checkDataKind(DataKind.double);
     return _readDoubleValue();
@@ -423,6 +433,7 @@
     return data.getFloat64(0);
   }
 
+  @override
   int readIntegerValue() {
     _checkDataKind(DataKind.int);
     return _readBigInt().toInt();
diff --git a/pkg/compiler/lib/src/serialization/binary_sink.dart b/pkg/compiler/lib/src/serialization/binary_sink.dart
index ae11f9b..3f771b4 100644
--- a/pkg/compiler/lib/src/serialization/binary_sink.dart
+++ b/pkg/compiler/lib/src/serialization/binary_sink.dart
@@ -16,9 +16,11 @@
       : _bufferedSink = new BufferedSink(sink),
         super(useDataKinds: useDataKinds);
 
+  @override
   void _begin(String tag) {
     // TODO(johnniwinther): Support tags in binary serialization?
   }
+  @override
   void _end(String tag) {
     // TODO(johnniwinther): Support tags in binary serialization?
   }
@@ -57,6 +59,7 @@
     _writeIntInternal(value.index);
   }
 
+  @override
   void close() {
     _bufferedSink.flushAndDestroy();
     _bufferedSink = null;
@@ -64,5 +67,6 @@
   }
 
   /// Returns the number of bytes written to this data sink.
+  @override
   int get length => _length;
 }
diff --git a/pkg/compiler/lib/src/serialization/binary_source.dart b/pkg/compiler/lib/src/serialization/binary_source.dart
index c68e4c9..11132b9 100644
--- a/pkg/compiler/lib/src/serialization/binary_source.dart
+++ b/pkg/compiler/lib/src/serialization/binary_source.dart
@@ -14,7 +14,9 @@
   BinarySourceImpl(this._bytes, {bool useDataKinds: false})
       : super(useDataKinds: useDataKinds);
 
+  @override
   void _begin(String tag) {}
+  @override
   void _end(String tag) {}
 
   int _readByte() => _bytes[_byteOffset++];
diff --git a/pkg/compiler/lib/src/serialization/helpers.dart b/pkg/compiler/lib/src/serialization/helpers.dart
index d6db5f2..4bb57a4 100644
--- a/pkg/compiler/lib/src/serialization/helpers.dart
+++ b/pkg/compiler/lib/src/serialization/helpers.dart
@@ -71,14 +71,17 @@
 
   Tag(this.value);
 
+  @override
   int get hashCode => value.hashCode * 13;
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! Tag) return false;
     return value == other.value;
   }
 
+  @override
   String toString() => 'Tag($value)';
 }
 
@@ -102,6 +105,7 @@
 
   DartTypeWriter(this._sink);
 
+  @override
   void visit(covariant DartType type,
           List<FunctionTypeVariable> functionTypeVariables) =>
       type.accept(this, functionTypeVariables);
@@ -114,11 +118,13 @@
     }
   }
 
+  @override
   void visitVoidType(covariant VoidType type,
       List<FunctionTypeVariable> functionTypeVariables) {
     _sink.writeEnum(DartTypeKind.voidType);
   }
 
+  @override
   void visitTypeVariableType(covariant TypeVariableType type,
       List<FunctionTypeVariable> functionTypeVariables) {
     _sink.writeEnum(DartTypeKind.typeVariable);
@@ -126,6 +132,7 @@
     _sink.writeInt(typeVariable.typeVariableIndex);
   }
 
+  @override
   void visitFunctionTypeVariable(covariant FunctionTypeVariable type,
       List<FunctionTypeVariable> functionTypeVariables) {
     int index = functionTypeVariables.indexOf(type);
@@ -138,6 +145,7 @@
     }
   }
 
+  @override
   void visitFunctionType(covariant FunctionType type,
       List<FunctionTypeVariable> functionTypeVariables) {
     _sink.writeEnum(DartTypeKind.functionType);
@@ -157,6 +165,7 @@
     }
   }
 
+  @override
   void visitInterfaceType(covariant InterfaceType type,
       List<FunctionTypeVariable> functionTypeVariables) {
     _sink.writeEnum(DartTypeKind.interfaceType);
@@ -164,6 +173,7 @@
     visitTypes(type.typeArguments, functionTypeVariables);
   }
 
+  @override
   void visitTypedefType(covariant TypedefType type,
       List<FunctionTypeVariable> functionTypeVariables) {
     _sink.writeEnum(DartTypeKind.typedef);
@@ -172,11 +182,13 @@
     _sink._writeDartType(type.unaliased, functionTypeVariables);
   }
 
+  @override
   void visitDynamicType(covariant DynamicType type,
       List<FunctionTypeVariable> functionTypeVariables) {
     _sink.writeEnum(DartTypeKind.dynamicType);
   }
 
+  @override
   void visitFutureOrType(covariant FutureOrType type,
       List<FunctionTypeVariable> functionTypeVariables) {
     _sink.writeEnum(DartTypeKind.futureOr);
@@ -217,27 +229,32 @@
     }
   }
 
+  @override
   void defaultDartType(
       ir.DartType node, List<ir.TypeParameter> functionTypeVariables) {
     throw new UnsupportedError(
         "Unexpected ir.DartType $node (${node.runtimeType}).");
   }
 
+  @override
   void visitInvalidType(
       ir.InvalidType node, List<ir.TypeParameter> functionTypeVariables) {
     _sink.writeEnum(DartTypeNodeKind.invalidType);
   }
 
+  @override
   void visitDynamicType(
       ir.DynamicType node, List<ir.TypeParameter> functionTypeVariables) {
     _sink.writeEnum(DartTypeNodeKind.dynamicType);
   }
 
+  @override
   void visitVoidType(
       ir.VoidType node, List<ir.TypeParameter> functionTypeVariables) {
     _sink.writeEnum(DartTypeNodeKind.voidType);
   }
 
+  @override
   void visitBottomType(
       ir.BottomType node, List<ir.TypeParameter> functionTypeVariables) {
     if (node == const DoesNotCompleteType()) {
@@ -247,6 +264,7 @@
     }
   }
 
+  @override
   void visitInterfaceType(
       ir.InterfaceType node, List<ir.TypeParameter> functionTypeVariables) {
     if (node is ThisInterfaceType) {
@@ -260,6 +278,7 @@
     visitTypes(node.typeArguments, functionTypeVariables);
   }
 
+  @override
   void visitFunctionType(
       ir.FunctionType node, List<ir.TypeParameter> functionTypeVariables) {
     _sink.writeEnum(DartTypeNodeKind.functionType);
@@ -286,6 +305,7 @@
     _sink.end(functionTypeNodeTag);
   }
 
+  @override
   void visitTypeParameterType(
       ir.TypeParameterType node, List<ir.TypeParameter> functionTypeVariables) {
     int index = functionTypeVariables.indexOf(node.parameter);
@@ -302,6 +322,7 @@
     }
   }
 
+  @override
   void visitTypedefType(
       ir.TypedefType node, List<ir.TypeParameter> functionTypeVariables) {
     _sink.writeEnum(DartTypeNodeKind.typedef);
diff --git a/pkg/compiler/lib/src/serialization/member_data.dart b/pkg/compiler/lib/src/serialization/member_data.dart
index b4aeee12..f088210 100644
--- a/pkg/compiler/lib/src/serialization/member_data.dart
+++ b/pkg/compiler/lib/src/serialization/member_data.dart
@@ -108,6 +108,7 @@
     return _members[name];
   }
 
+  @override
   String toString() => '_LibraryData($node(${identityHashCode(node)}))';
 }
 
@@ -137,6 +138,7 @@
     return _members[name];
   }
 
+  @override
   String toString() => '_ClassData($node(${identityHashCode(node)}))';
 }
 
@@ -180,5 +182,6 @@
     return index;
   }
 
+  @override
   String toString() => '_MemberData($node(${identityHashCode(node)}))';
 }
diff --git a/pkg/compiler/lib/src/serialization/object_sink.dart b/pkg/compiler/lib/src/serialization/object_sink.dart
index 3246b9f..31376e3 100644
--- a/pkg/compiler/lib/src/serialization/object_sink.dart
+++ b/pkg/compiler/lib/src/serialization/object_sink.dart
@@ -14,10 +14,12 @@
   ObjectSink(this._data, {bool useDataKinds})
       : super(useDataKinds: useDataKinds);
 
+  @override
   void _begin(String tag) {
     _data.add(new Tag('begin:$tag'));
   }
 
+  @override
   void _end(String tag) {
     _data.add(new Tag('end:$tag'));
   }
diff --git a/pkg/compiler/lib/src/serialization/object_source.dart b/pkg/compiler/lib/src/serialization/object_source.dart
index 4ce571e..54207a2 100644
--- a/pkg/compiler/lib/src/serialization/object_source.dart
+++ b/pkg/compiler/lib/src/serialization/object_source.dart
@@ -21,6 +21,7 @@
     return value;
   }
 
+  @override
   void _begin(String tag) {
     Tag expectedTag = new Tag('begin:$tag');
     Tag actualTag = _read();
@@ -30,6 +31,7 @@
         "Expected $expectedTag, found $actualTag.$_errorContext");
   }
 
+  @override
   void _end(String tag) {
     Tag expectedTag = new Tag('end:$tag');
     Tag actualTag = _read();
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 3aac9f3..56ab4bd 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -49,6 +49,7 @@
 
   SerializationTask(this.compiler, Measurer measurer) : super(measurer);
 
+  @override
   String get name => 'Serialization';
 
   void serialize(GlobalTypeInferenceResults results) {
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index f6551af..3a6f81a 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -176,6 +176,7 @@
 class CompilerSourceFileProvider extends SourceFileProvider {
   // TODO(johnniwinther): Remove this when no longer needed for the old compiler
   // API.
+  @override
   Future<List<int>> call(Uri resourceUri) =>
       readFromUri(resourceUri).then((input) => input.data);
 
@@ -372,6 +373,7 @@
     return uri;
   }
 
+  @override
   OutputSink createOutputSink(String name, String extension, OutputType type) {
     Uri uri = createUri(name, extension, type);
     bool isPrimaryOutput = uri == out;
@@ -474,8 +476,10 @@
 
   _OutputSinkWrapper(this.onAdd, this.onClose);
 
+  @override
   void add(String data) => onAdd(data);
 
+  @override
   void close() => onClose();
 }
 
@@ -485,9 +489,11 @@
 
   _BinaryOutputSinkWrapper(this.onWrite, this.onClose);
 
+  @override
   void write(List<int> data, [int start = 0, int end]) =>
       onWrite(data, start, end);
 
+  @override
   void close() => onClose();
 }
 
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 242f060..8047624 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -83,11 +83,14 @@
 
 class KernelSsaGraphBuilder extends ir.Visitor
     with GraphBuilder, SsaBuilderFieldMixin {
+  @override
   final MemberEntity targetElement;
   final MemberEntity initialTargetElement;
 
+  @override
   final JClosedWorld closedWorld;
   final CodegenWorldBuilder _worldBuilder;
+  @override
   final CodegenRegistry registry;
   final ClosureData closureDataLookup;
 
@@ -105,6 +108,7 @@
 
   HInstruction rethrowableException;
 
+  @override
   final Compiler compiler;
 
   @override
@@ -112,8 +116,10 @@
 
   final SourceInformationStrategy _sourceInformationStrategy;
   final JsToElementMap _elementMap;
+  @override
   final GlobalTypeInferenceResults globalInferenceResults;
   LoopHandler loopHandler;
+  @override
   TypeBuilder typeBuilder;
 
   final NativeEmitter nativeEmitter;
@@ -233,7 +239,20 @@
               // the constant value.
               return null;
             } else if (targetElement.isStatic || targetElement.isTopLevel) {
-              backend.constants.registerLazyStatic(targetElement);
+              if (_fieldAnalysis.getFieldData(targetElement).isLazy) {
+                // TODO(johnniwinther): Lazy fields should be collected like
+                // eager and non-final fields.
+                backend.constants.registerLazyStatic(targetElement);
+              }
+            } else {
+              assert(targetElement.isInstanceMember);
+              if (_fieldAnalysis
+                      .getFieldData(targetElement)
+                      .isEffectivelyFinal ||
+                  !options.parameterCheckPolicy.isEmitted) {
+                // No need for a checked setter.
+                return null;
+              }
             }
             buildField(target);
           } else if (target is ir.FunctionExpression) {
@@ -258,8 +277,8 @@
           buildConstructorBody(constructor);
           break;
         case MemberKind.closureField:
-          failedAt(targetElement, "Unexpected closure field: $targetElement");
-          break;
+          // Closure fields have no setter and therefore never require any code.
+          return null;
         case MemberKind.signature:
           ir.Node target = definition.node;
           ir.FunctionNode originalClosureNode;
@@ -1417,29 +1436,8 @@
   }
 
   @override
-  void defaultExpression(ir.Expression expression) {
-    // TODO(johnniwinther): We should make this an internal error.
-    _trap('Unhandled ir.${expression.runtimeType}  $expression');
-  }
-
-  @override
-  void defaultStatement(ir.Statement statement) {
-    // TODO(johnniwinther): We should make this an internal error.
-    _trap('Unhandled ir.${statement.runtimeType}  $statement');
-    pop();
-  }
-
-  void _trap(String message) {
-    HInstruction nullValue = graph.addConstantNull(closedWorld);
-    HInstruction errorMessage = graph.addConstantString(message, closedWorld);
-    HInstruction trap = new HForeignCode(
-        js.js.parseForeignJS("#.#"),
-        abstractValueDomain.dynamicType,
-        <HInstruction>[nullValue, errorMessage]);
-    trap.sideEffects
-      ..setAllSideEffects()
-      ..setDependsOnSomething();
-    push(trap);
+  void defaultNode(ir.Node node) {
+    throw new UnsupportedError("Unhandled node $node (${node.runtimeType})");
   }
 
   /// Returns the current source element. This is used by the type builder.
@@ -1526,6 +1524,12 @@
     }
   }
 
+  @override
+  void visitConstantExpression(ir.ConstantExpression node) {
+    stack.add(
+        graph.addConstant(_elementMap.getConstantValue(node), closedWorld));
+  }
+
   /// Returns true if the [type] is a valid return type for an asynchronous
   /// function.
   ///
@@ -1944,6 +1948,7 @@
       ..cleanUp();
   }
 
+  @override
   HInstruction callSetRuntimeTypeInfo(HInstruction typeInfo,
       HInstruction newObject, SourceInformation sourceInformation) {
     // Set the runtime type information on the object.
@@ -3078,26 +3083,26 @@
     } else if (staticTarget is ir.Field) {
       FieldEntity field = _elementMap.getField(staticTarget);
       FieldAnalysisData fieldData = _fieldAnalysis.getFieldData(field);
-      if (fieldData.initialValue != null) {
-        if (fieldData.isEffectivelyFinal) {
-          var unit = closedWorld.outputUnitData.outputUnitForMember(field);
-          // TODO(sigmund): this is not equivalent to what the old FE does: if
-          // there is no prefix the old FE wouldn't treat this in any special
-          // way. Also, if the prefix points to a constant in the main output
-          // unit, the old FE would still generate a deferred wrapper here.
-          if (!closedWorld.outputUnitData
-              .hasOnlyNonDeferredImportPaths(targetElement, field)) {
-            stack.add(graph.addDeferredConstant(fieldData.initialValue, unit,
-                sourceInformation, compiler, closedWorld));
-          } else {
-            stack.add(graph.addConstant(fieldData.initialValue, closedWorld,
-                sourceInformation: sourceInformation));
-          }
+      if (fieldData.isEager) {
+        push(new HStatic(field, _typeInferenceMap.getInferredTypeOf(field),
+            sourceInformation));
+      } else if (fieldData.isEffectivelyConstant) {
+        var unit = closedWorld.outputUnitData.outputUnitForMember(field);
+        // TODO(sigmund): this is not equivalent to what the old FE does: if
+        // there is no prefix the old FE wouldn't treat this in any special
+        // way. Also, if the prefix points to a constant in the main output
+        // unit, the old FE would still generate a deferred wrapper here.
+        if (!closedWorld.outputUnitData
+            .hasOnlyNonDeferredImportPaths(targetElement, field)) {
+          stack.add(graph.addDeferredConstant(fieldData.initialValue, unit,
+              sourceInformation, compiler, closedWorld));
         } else {
-          push(new HStatic(field, _typeInferenceMap.getInferredTypeOf(field),
-              sourceInformation));
+          stack.add(graph.addConstant(fieldData.initialValue, closedWorld,
+              sourceInformation: sourceInformation));
         }
       } else {
+        assert(
+            fieldData.isLazy, "Unexpected field data for $field: $fieldData");
         push(new HLazyStatic(field, _typeInferenceMap.getInferredTypeOf(field),
             sourceInformation));
       }
@@ -5043,6 +5048,7 @@
     }
   }
 
+  @override
   void visitYieldStatement(ir.YieldStatement node) {
     node.expression.accept(this);
     add(new HYield(abstractValueDomain, pop(), node.isYieldStar,
@@ -6598,8 +6604,10 @@
   KernelTypeBuilder(KernelSsaGraphBuilder builder, this._elementMap)
       : super(builder);
 
+  @override
   KernelSsaGraphBuilder get builder => super.builder;
 
+  @override
   ClassTypeVariableAccess computeTypeVariableAccess(MemberEntity member) {
     return _elementMap.getClassTypeVariableAccessForMember(member);
   }
@@ -6612,17 +6620,22 @@
   static bool check(ir.Initializer initializer) =>
       initializer.accept(new _ErroneousInitializerVisitor());
 
+  @override
   bool defaultInitializer(ir.Node node) => false;
 
+  @override
   bool visitInvalidInitializer(ir.InvalidInitializer node) => true;
 
+  @override
   bool visitLocalInitializer(ir.LocalInitializer node) {
     return node.variable.initializer?.accept(this) ?? false;
   }
 
   // Expressions: Does the expression always throw?
+  @override
   bool defaultExpression(ir.Expression node) => false;
 
+  @override
   bool visitThrow(ir.Throw node) => true;
 
   // TODO(sra): We might need to match other expressions that always throw but
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index ffccada..6c5852a 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -54,6 +54,7 @@
       : this.backend = backend,
         super(backend.compiler.measurer);
 
+  @override
   String get name => 'SSA code generator';
 
   js.Fun buildJavaScriptFunction(bool needsAsyncRewrite, FunctionEntity element,
@@ -772,8 +773,10 @@
   }
 
   // The regular [visitIf] method implements the needed logic.
+  @override
   bool visitIfInfo(HIfBlockInformation info) => false;
 
+  @override
   bool visitSwitchInfo(HSwitchBlockInformation info) {
     bool isExpression = isJSExpression(info.expression);
     if (!isExpression) {
@@ -845,23 +848,28 @@
     return true;
   }
 
+  @override
   bool visitSequenceInfo(HStatementSequenceInformation info) {
     return false;
   }
 
+  @override
   bool visitSubGraphInfo(HSubGraphBlockInformation info) {
     visitSubGraph(info.subGraph);
     return true;
   }
 
+  @override
   bool visitSubExpressionInfo(HSubExpressionBlockInformation info) {
     return false;
   }
 
+  @override
   bool visitAndOrInfo(HAndOrBlockInformation info) {
     return false;
   }
 
+  @override
   bool visitTryInfo(HTryBlockInformation info) {
     js.Block body = generateStatementsInNewBlock(info.body);
     js.Catch catchPart = null;
@@ -902,6 +910,7 @@
     }
   }
 
+  @override
   bool visitLoopInfo(HLoopBlockInformation info) {
     HExpressionInformation condition = info.condition;
     bool isConditionExpression = isJSCondition(condition);
@@ -1122,6 +1131,7 @@
     return true;
   }
 
+  @override
   bool visitLabeledBlockInfo(HLabeledBlockInformation labeledBlockInfo) {
     Link<Entity> continueOverrides = const Link<Entity>();
 
@@ -1408,6 +1418,7 @@
         .withSourceInformation(sourceInformation));
   }
 
+  @override
   visitLateValue(HLateValue node) {
     use(node.target);
   }
@@ -1476,21 +1487,33 @@
     }
   }
 
+  @override
   visitIdentity(HIdentity node) {
     emitIdentityComparison(node, node.sourceInformation, inverse: false);
   }
 
+  @override
   visitAdd(HAdd node) => visitInvokeBinary(node, '+');
+  @override
   visitDivide(HDivide node) => visitInvokeBinary(node, '/');
+  @override
   visitMultiply(HMultiply node) => visitInvokeBinary(node, '*');
+  @override
   visitSubtract(HSubtract node) => visitInvokeBinary(node, '-');
+  @override
   visitBitAnd(HBitAnd node) => visitBitInvokeBinary(node, '&');
+  @override
   visitBitNot(HBitNot node) => visitBitInvokeUnary(node, '~');
+  @override
   visitBitOr(HBitOr node) => visitBitInvokeBinary(node, '|');
+  @override
   visitBitXor(HBitXor node) => visitBitInvokeBinary(node, '^');
+  @override
   visitShiftLeft(HShiftLeft node) => visitBitInvokeBinary(node, '<<');
+  @override
   visitShiftRight(HShiftRight node) => visitBitInvokeBinary(node, '>>>');
 
+  @override
   visitTruncatingDivide(HTruncatingDivide node) {
     assert(node.isUInt31(_abstractValueDomain).isDefinitelyTrue);
     // TODO(karlklose): Enable this assertion again when type propagation is
@@ -1506,12 +1529,15 @@
         .withSourceInformation(node.sourceInformation));
   }
 
+  @override
   visitRemainder(HRemainder node) {
     return visitInvokeBinary(node, '%');
   }
 
+  @override
   visitNegate(HNegate node) => visitInvokeUnary(node, '-');
 
+  @override
   visitAbs(HAbs node) {
     use(node.operand);
     push(js
@@ -1519,11 +1545,16 @@
         .withSourceInformation(node.sourceInformation));
   }
 
+  @override
   visitLess(HLess node) => visitRelational(node, '<');
+  @override
   visitLessEqual(HLessEqual node) => visitRelational(node, '<=');
+  @override
   visitGreater(HGreater node) => visitRelational(node, '>');
+  @override
   visitGreaterEqual(HGreaterEqual node) => visitRelational(node, '>=');
 
+  @override
   visitBoolify(HBoolify node) {
     assert(node.inputs.length == 1);
     use(node.inputs[0]);
@@ -1532,10 +1563,12 @@
         .withSourceInformation(node.sourceInformation));
   }
 
+  @override
   visitExit(HExit node) {
     // Don't do anything.
   }
 
+  @override
   visitGoto(HGoto node) {
     HBasicBlock block = node.block;
     assert(block.successors.length == 1);
@@ -1556,6 +1589,7 @@
     continueSubGraph(dominated.first);
   }
 
+  @override
   visitLoopBranch(HLoopBranch node) {
     assert(node.block == subGraph.end);
     // We are generating code for a loop condition.
@@ -1568,6 +1602,7 @@
     }
   }
 
+  @override
   visitBreak(HBreak node) {
     assert(node.block.successors.length == 1);
     if (node.label != null) {
@@ -1594,6 +1629,7 @@
     }
   }
 
+  @override
   visitContinue(HContinue node) {
     assert(node.block.successors.length == 1);
     if (node.label != null) {
@@ -1622,6 +1658,7 @@
     }
   }
 
+  @override
   visitExitTry(HExitTry node) {
     // An [HExitTry] is used to represent the control flow graph of a
     // try/catch block, ie the try body is always a predecessor
@@ -1631,6 +1668,7 @@
     continueSubGraph(node.bodyTrySuccessor);
   }
 
+  @override
   visitTry(HTry node) {
     // We should never get here. Try/catch/finally is always handled using block
     // information in [visitTryInfo].
@@ -1729,6 +1767,7 @@
     return js.If(test, thenPart, elsePart);
   }
 
+  @override
   visitIf(HIf node) {
     if (tryControlFlowOperation(node)) return;
 
@@ -1764,6 +1803,7 @@
     }
   }
 
+  @override
   void visitInterceptor(HInterceptor node) {
     if (node.isConditionalConstantInterceptor) {
       assert(node.inputs.length == 2);
@@ -1787,6 +1827,7 @@
     }
   }
 
+  @override
   visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
     use(node.receiver);
     js.Expression object = pop();
@@ -1829,6 +1870,7 @@
         .withSourceInformation(node.sourceInformation));
   }
 
+  @override
   void visitInvokeConstructorBody(HInvokeConstructorBody node) {
     use(node.inputs[0]);
     js.Expression object = pop();
@@ -1841,6 +1883,7 @@
         node.element, new CallStructure.unnamed(arguments.length)));
   }
 
+  @override
   void visitInvokeGeneratorBody(HInvokeGeneratorBody node) {
     JGeneratorBody element = node.element;
     if (element.isInstanceMember) {
@@ -1862,6 +1905,7 @@
         .registerStaticUse(new StaticUse.generatorBodyInvoke(node.element));
   }
 
+  @override
   void visitOneShotInterceptor(HOneShotInterceptor node) {
     List<js.Expression> arguments = visitArguments(node.inputs);
     var isolate = new js.VariableUse(
@@ -1976,6 +2020,7 @@
     }
   }
 
+  @override
   visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
     use(node.receiver);
     js.Name name = _namer.invocationName(node.selector);
@@ -1985,6 +2030,7 @@
     registerSetter(node, needsCheck: node.needsCheck);
   }
 
+  @override
   visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
     use(node.receiver);
     js.Name name = _namer.invocationName(node.selector);
@@ -1994,6 +2040,7 @@
     registerGetter(node);
   }
 
+  @override
   visitInvokeClosure(HInvokeClosure node) {
     Selector call = new Selector.callClosureFrom(node.selector);
     use(node.receiver);
@@ -2008,6 +2055,7 @@
         new ConstrainedDynamicUse(call, null, node.typeArguments));
   }
 
+  @override
   visitInvokeStatic(HInvokeStatic node) {
     MemberEntity element = node.element;
     node.instantiatedTypes?.forEach(_registry.registerInstantiation);
@@ -2056,6 +2104,7 @@
     }
   }
 
+  @override
   visitInvokeSuper(HInvokeSuper node) {
     MemberEntity superElement = node.element;
     ClassEntity superClass = superElement.enclosingClass;
@@ -2116,6 +2165,7 @@
     }
   }
 
+  @override
   visitFieldGet(HFieldGet node) {
     use(node.receiver);
     if (node.isNullCheck) {
@@ -2133,6 +2183,7 @@
     }
   }
 
+  @override
   visitFieldSet(HFieldSet node) {
     FieldEntity element = node.element;
     _registry.registerStaticUse(new StaticUse.fieldSet(element));
@@ -2147,12 +2198,14 @@
         .withSourceInformation(node.sourceInformation));
   }
 
+  @override
   visitGetLength(HGetLength node) {
     use(node.receiver);
     push(new js.PropertyAccess.field(pop(), 'length')
         .withSourceInformation(node.sourceInformation));
   }
 
+  @override
   visitReadModifyWrite(HReadModifyWrite node) {
     FieldEntity element = node.element;
     _registry.registerStaticUse(new StaticUse.fieldGet(element));
@@ -2173,10 +2226,12 @@
     }
   }
 
+  @override
   visitLocalGet(HLocalGet node) {
     use(node.receiver);
   }
 
+  @override
   visitLocalSet(HLocalSet node) {
     use(node.value);
     assignVariable(
@@ -2190,6 +2245,7 @@
         _registry.worldImpact, nativeBehavior, node);
   }
 
+  @override
   visitForeignCode(HForeignCode node) {
     List<HInstruction> inputs = node.inputs;
     if (node.isJsStatement()) {
@@ -2221,6 +2277,7 @@
     }
   }
 
+  @override
   visitCreate(HCreate node) {
     js.Expression jsClassReference = _emitter.constructorAccess(node.element);
     List<js.Expression> arguments = visitArguments(node.inputs, start: 0);
@@ -2242,6 +2299,7 @@
     }
   }
 
+  @override
   visitCreateBox(HCreateBox node) {
     push(new js.ObjectInitializer(<js.Property>[]));
   }
@@ -2267,6 +2325,7 @@
     push(expression);
   }
 
+  @override
   visitConstant(HConstant node) {
     assert(isGenerateAtUseSite(node));
     generateConstant(node.constant, node.sourceInformation);
@@ -2279,6 +2338,7 @@
     }
   }
 
+  @override
   visitNot(HNot node) {
     assert(node.inputs.length == 1);
     generateNot(node.inputs[0], node.sourceInformation);
@@ -2348,6 +2408,7 @@
     }
   }
 
+  @override
   visitParameterValue(HParameterValue node) {
     assert(!isGenerateAtUseSite(node));
     String name = variableNames.getName(node);
@@ -2355,12 +2416,14 @@
     declaredLocals.add(name);
   }
 
+  @override
   visitLocalValue(HLocalValue node) {
     assert(!isGenerateAtUseSite(node));
     String name = variableNames.getName(node);
     collectedVariableDeclarations.add(name);
   }
 
+  @override
   visitPhi(HPhi node) {
     // This method is only called for phis that are generated at use
     // site. A phi can be generated at use site only if it is the
@@ -2392,6 +2455,7 @@
     }
   }
 
+  @override
   visitReturn(HReturn node) {
     assert(node.inputs.length == 1);
     HInstruction input = node.inputs[0];
@@ -2405,10 +2469,12 @@
     }
   }
 
+  @override
   visitThis(HThis node) {
     push(new js.This());
   }
 
+  @override
   visitThrow(HThrow node) {
     if (node.isRethrow) {
       use(node.inputs[0]);
@@ -2421,23 +2487,27 @@
     }
   }
 
+  @override
   visitAwait(HAwait node) {
     use(node.inputs[0]);
     push(new js.Await(pop()).withSourceInformation(node.sourceInformation));
   }
 
+  @override
   visitYield(HYield node) {
     use(node.inputs[0]);
     pushStatement(new js.DartYield(pop(), node.hasStar)
         .withSourceInformation(node.sourceInformation));
   }
 
+  @override
   visitRangeConversion(HRangeConversion node) {
     // Range conversion instructions are removed by the value range
     // analyzer.
     assert(false);
   }
 
+  @override
   visitBoundsCheck(HBoundsCheck node) {
     // TODO(ngeoffray): Separate the two checks of the bounds check, so,
     // e.g., the zero checks can be shared if possible.
@@ -2518,6 +2588,7 @@
     }
   }
 
+  @override
   visitThrowExpression(HThrowExpression node) {
     HInstruction argument = node.inputs[0];
     use(argument);
@@ -2532,10 +2603,12 @@
     push(value);
   }
 
+  @override
   void visitSwitch(HSwitch node) {
     // Switches are handled using [visitSwitchInfo].
   }
 
+  @override
   void visitStatic(HStatic node) {
     MemberEntity element = node.element;
     assert(element.isFunction || element.isField);
@@ -2552,6 +2625,7 @@
     }
   }
 
+  @override
   void visitLazyStatic(HLazyStatic node) {
     FieldEntity element = node.element;
     _registry.registerStaticUse(new StaticUse.staticInit(element));
@@ -2561,6 +2635,7 @@
     push(call);
   }
 
+  @override
   void visitStaticStore(HStaticStore node) {
     _registry.registerStaticUse(new StaticUse.staticSet(node.element));
     js.Node variable = _emitter.staticFieldAccess(node.element);
@@ -2569,6 +2644,7 @@
         .withSourceInformation(node.sourceInformation));
   }
 
+  @override
   void visitStringConcat(HStringConcat node) {
     use(node.left);
     js.Expression jsLeft = pop();
@@ -2577,6 +2653,7 @@
         .withSourceInformation(node.sourceInformation));
   }
 
+  @override
   void visitStringify(HStringify node) {
     HInstruction input = node.inputs.first;
     if (input.isString(_abstractValueDomain).isDefinitelyTrue) {
@@ -2607,6 +2684,7 @@
     }
   }
 
+  @override
   void visitLiteralList(HLiteralList node) {
     _registry
         // ignore:deprecated_member_use_from_same_package
@@ -2623,6 +2701,7 @@
         .withSourceInformation(node.sourceInformation));
   }
 
+  @override
   void visitIndex(HIndex node) {
     use(node.receiver);
     js.Expression receiver = pop();
@@ -2631,6 +2710,7 @@
         .withSourceInformation(node.sourceInformation));
   }
 
+  @override
   void visitIndexAssign(HIndexAssign node) {
     use(node.receiver);
     js.Expression receiver = pop();
@@ -2902,10 +2982,12 @@
         .withSourceInformation(sourceInformation));
   }
 
+  @override
   void visitIs(HIs node) {
     emitIs(node, "===", node.sourceInformation);
   }
 
+  @override
   void visitIsViaInterceptor(HIsViaInterceptor node) {
     emitIsViaInterceptor(node, node.sourceInformation, negative: false);
   }
@@ -3019,6 +3101,7 @@
     throw failedAt(input, 'Unexpected check: $type.');
   }
 
+  @override
   void visitTypeConversion(HTypeConversion node) {
     if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
       js.Expression test = generateReceiverOrArgumentTypeTest(node);
@@ -3078,17 +3161,20 @@
             .withSourceInformation(node.sourceInformation));
   }
 
+  @override
   void visitTypeKnown(HTypeKnown node) {
     // [HTypeKnown] instructions are removed before generating code.
     assert(false);
   }
 
+  @override
   void visitTypeInfoReadRaw(HTypeInfoReadRaw node) {
     use(node.inputs[0]);
     js.Expression receiver = pop();
     push(js.js(r'#.#', [receiver, _namer.rtiFieldJsName]));
   }
 
+  @override
   void visitTypeInfoReadVariable(HTypeInfoReadVariable node) {
     TypeVariableEntity element = node.variable.element;
     int index = element.index;
@@ -3143,6 +3229,7 @@
     }
   }
 
+  @override
   void visitTypeInfoExpression(HTypeInfoExpression node) {
     DartType type = node.dartType;
     if (node.isTypeVariableReplacement) {
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index 6c28b79..4ad0571 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -27,11 +27,13 @@
   AbstractValueDomain get _abstractValueDomain =>
       _closedWorld.abstractValueDomain;
 
+  @override
   void visitGraph(HGraph graph) {
     this.graph = graph;
     visitDominatorTree(graph);
   }
 
+  @override
   visitBasicBlock(HBasicBlock block) {
     HInstruction instruction = block.first;
     while (instruction != null) {
@@ -63,10 +65,12 @@
     }
   }
 
+  @override
   HInstruction visitInstruction(HInstruction node) {
     return node;
   }
 
+  @override
   HInstruction visitIs(HIs node) {
     if (node.kind == HIs.RAW_CHECK) {
       HInstruction interceptor = node.interceptor;
@@ -78,6 +82,7 @@
     return node;
   }
 
+  @override
   HInstruction visitIdentity(HIdentity node) {
     node.singleComparisonOp = simpleOp(node.left, node.right);
     return node;
@@ -128,6 +133,7 @@
       .isInterceptor(_abstractValueDomain.excludeNull(type))
       .isPotentiallyTrue;
 
+  @override
   HInstruction visitInvokeDynamic(HInvokeDynamic node) {
     if (node.isInterceptedCall) {
       tryReplaceInterceptorWithDummy(node, node.selector, node.mask);
@@ -135,6 +141,7 @@
     return node;
   }
 
+  @override
   HInstruction visitInvokeSuper(HInvokeSuper node) {
     if (node.isInterceptedCall) {
       AbstractValue mask = node.getDartReceiver(_closedWorld).instructionType;
@@ -143,6 +150,7 @@
     return node;
   }
 
+  @override
   HInstruction visitOneShotInterceptor(HOneShotInterceptor node) {
     // The receiver parameter should never be replaced with a dummy constant.
     return node;
@@ -195,6 +203,7 @@
     return false;
   }
 
+  @override
   HInstruction visitFieldSet(HFieldSet setter) {
     // Pattern match
     //     t1 = x.f; t2 = t1 + 1; x.f = t2; use(t2)   -->  ++x.f
@@ -305,6 +314,7 @@
     return noMatchingRead();
   }
 
+  @override
   visitIf(HIf node) {
     if (!_options.experimentToBoolean) return node;
     HInstruction condition = node.inputs.single;
@@ -343,10 +353,12 @@
 /// Remove [HTypeKnown] instructions from the graph, to make codegen
 /// analysis easier.
 class SsaTypeKnownRemover extends HBaseVisitor with CodegenPhase {
+  @override
   void visitGraph(HGraph graph) {
     visitDominatorTree(graph);
   }
 
+  @override
   void visitBasicBlock(HBasicBlock block) {
     HInstruction instruction = block.first;
     while (instruction != null) {
@@ -356,6 +368,7 @@
     }
   }
 
+  @override
   void visitTypeKnown(HTypeKnown instruction) {
     for (HInstruction user in instruction.usedBy) {
       if (user is HTypeConversion) {
@@ -374,11 +387,13 @@
 
   SsaTrustedCheckRemover(this._options);
 
+  @override
   void visitGraph(HGraph graph) {
     if (!_options.trustPrimitives) return;
     visitDominatorTree(graph);
   }
 
+  @override
   void visitBasicBlock(HBasicBlock block) {
     HInstruction instruction = block.first;
     while (instruction != null) {
@@ -388,6 +403,7 @@
     }
   }
 
+  @override
   void visitTypeConversion(HTypeConversion instruction) {
     if (instruction.isReceiverTypeCheck || instruction.isArgumentTypeCheck) {
       instruction.block.rewrite(instruction, instruction.checkedInput);
@@ -413,11 +429,13 @@
   AbstractValueDomain get _abstractValueDomain =>
       _closedWorld.abstractValueDomain;
 
+  @override
   void visitGraph(HGraph graph) {
     //this.graph = graph;
     visitDominatorTree(graph);
   }
 
+  @override
   void visitBasicBlock(HBasicBlock block) {
     HInstruction instruction = block.first;
     while (instruction != null) {
@@ -426,14 +444,17 @@
   }
 
   /// Returns the next instruction.
+  @override
   HInstruction visitInstruction(HInstruction node) {
     return node.next;
   }
 
+  @override
   HInstruction visitFieldSet(HFieldSet setter) {
     return tryChainAssignment(setter, setter.value);
   }
 
+  @override
   HInstruction visitStaticStore(HStaticStore store) {
     return tryChainAssignment(store, store.inputs.single);
   }
@@ -589,6 +610,7 @@
   SsaInstructionMerger(
       this._abstractValueDomain, this.generateAtUseSite, this._superMemberData);
 
+  @override
   void visitGraph(HGraph graph) {
     visitDominatorTree(graph);
   }
@@ -651,12 +673,14 @@
         .isNotEmpty;
   }
 
+  @override
   void visitInstruction(HInstruction instruction) {
     // A code motion invariant instruction is dealt before visiting it.
     assert(!instruction.isCodeMotionInvariant());
     analyzeInputs(instruction, 0);
   }
 
+  @override
   void visitInvokeSuper(HInvokeSuper instruction) {
     MemberEntity superMethod = instruction.element;
     Selector selector = instruction.selector;
@@ -677,6 +701,7 @@
     }
   }
 
+  @override
   void visitIs(HIs instruction) {
     // In the general case the input might be used multple multiple times, so it
     // must not be set generate at use site.
@@ -695,6 +720,7 @@
 
   // A bounds check method must not have its first input generated at use site,
   // because it's using it twice.
+  @override
   void visitBoundsCheck(HBoundsCheck instruction) {
     analyzeInputs(instruction, 1);
   }
@@ -702,6 +728,7 @@
   // An identity operation must only have its inputs generated at use site if
   // does not require an expression with multiple uses (because of null /
   // undefined).
+  @override
   void visitIdentity(HIdentity instruction) {
     if (instruction.singleComparisonOp != null) {
       super.visitIdentity(instruction);
@@ -709,6 +736,7 @@
     // Do nothing.
   }
 
+  @override
   void visitTypeConversion(HTypeConversion instruction) {
     if (!instruction.isArgumentTypeCheck && !instruction.isReceiverTypeCheck) {
       assert(instruction.isCheckedModeCheck || instruction.isCastTypeCheck);
@@ -719,6 +747,7 @@
     }
   }
 
+  @override
   void visitTypeKnown(HTypeKnown instruction) {
     // [HTypeKnown] instructions are removed before code generation.
     assert(false);
@@ -734,6 +763,7 @@
         block.successors[0].predecessors.length == 1;
   }
 
+  @override
   void visitBasicBlock(HBasicBlock block) {
     // Compensate from not merging blocks: if the block is the
     // single predecessor of its single successor, let the successor
@@ -878,6 +908,7 @@
 
   SsaConditionMerger(this.generateAtUseSite, this.controlFlowOperators);
 
+  @override
   void visitGraph(HGraph graph) {
     visitPostDominatorTree(graph);
   }
@@ -927,6 +958,7 @@
     return user.hasSameLoopHeaderAs(input);
   }
 
+  @override
   void visitBasicBlock(HBasicBlock block) {
     if (block.last is! HIf) return;
     HIf startIf = block.last;
@@ -1046,6 +1078,7 @@
 
   SsaShareRegionConstants(this._options);
 
+  @override
   visitGraph(HGraph graph) {
     // We need the async rewrite to be smarter about hoisting region constants
     // before it is worth-while.
@@ -1056,6 +1089,7 @@
     visitBasicBlock(graph.entry);
   }
 
+  @override
   visitBasicBlock(HBasicBlock block) {
     HInstruction instruction = block.first;
     while (instruction != null) {
@@ -1089,6 +1123,7 @@
     }
   }
 
+  @override
   void visitThis(HThis node) {
     int size = 4;
     // Compare the size of the unchanged minified with the size of the minified
@@ -1110,6 +1145,7 @@
     _cache(node, (_) => true, '_this');
   }
 
+  @override
   void visitConstant(HConstant node) {
     if (node.usedBy.length <= 1) return;
     ConstantValue constant = node.constant;
@@ -1218,6 +1254,7 @@
 /// A simple Entity to give intermediate values nice names when not generating
 /// minified code.
 class _ExpressionName implements Entity {
+  @override
   final String name;
   _ExpressionName(this.name);
 }
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index 3f5d89b..098809b 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -32,6 +32,7 @@
 ///
 class SsaSimplifyInterceptors extends HBaseVisitor
     implements OptimizationPhase {
+  @override
   final String name = "SsaSimplifyInterceptors";
   final JClosedWorld _closedWorld;
   final ClassEntity _enclosingClass;
@@ -46,11 +47,13 @@
   AbstractValueDomain get _abstractValueDomain =>
       _closedWorld.abstractValueDomain;
 
+  @override
   void visitGraph(HGraph graph) {
     this._graph = graph;
     visitDominatorTree(graph);
   }
 
+  @override
   void visitBasicBlock(HBasicBlock node) {
     currentBlock = node;
 
@@ -65,8 +68,10 @@
     }
   }
 
+  @override
   bool visitInstruction(HInstruction instruction) => false;
 
+  @override
   bool visitInvoke(HInvoke invoke) {
     if (!invoke.isInterceptedCall) return false;
     dynamic interceptor = invoke.inputs[0];
@@ -187,6 +192,7 @@
   static int useCount(HInstruction user, HInstruction used) =>
       user.inputs.where((input) => input == used).length;
 
+  @override
   bool visitInterceptor(HInterceptor node) {
     if (node.receiver.nonCheck() == _graph.explicitReceiverParameter) {
       // If `explicitReceiverParameter` is set it means the current method is an
@@ -431,6 +437,7 @@
     }
   }
 
+  @override
   bool visitOneShotInterceptor(HOneShotInterceptor node) {
     // 'Undo' the one-shot transformation if the receiver has a constant
     // interceptor.
diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
index 7e6e84c..42e3113 100644
--- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
+++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
@@ -116,6 +116,7 @@
 class IndexAssignSpecializer extends InvokeDynamicSpecializer {
   const IndexAssignSpecializer();
 
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
@@ -187,6 +188,7 @@
 class IndexSpecializer extends InvokeDynamicSpecializer {
   const IndexSpecializer();
 
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
@@ -221,10 +223,12 @@
 class BitNotSpecializer extends InvokeDynamicSpecializer {
   const BitNotSpecializer();
 
+  @override
   constant_system.UnaryOperation operation() {
     return constant_system.bitNot;
   }
 
+  @override
   AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -241,6 +245,7 @@
         .computeTypeFromInputTypes(instruction, results, options, closedWorld);
   }
 
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
@@ -266,10 +271,12 @@
 class UnaryNegateSpecializer extends InvokeDynamicSpecializer {
   const UnaryNegateSpecializer();
 
+  @override
   constant_system.UnaryOperation operation() {
     return constant_system.negate;
   }
 
+  @override
   AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -297,6 +304,7 @@
         .computeTypeFromInputTypes(instruction, results, options, closedWorld);
   }
 
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
@@ -322,10 +330,12 @@
 class AbsSpecializer extends InvokeDynamicSpecializer {
   const AbsSpecializer();
 
+  @override
   constant_system.UnaryOperation operation() {
     return constant_system.abs;
   }
 
+  @override
   AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -341,6 +351,7 @@
         .computeTypeFromInputTypes(instruction, results, options, closedWorld);
   }
 
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
@@ -369,6 +380,7 @@
 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer {
   const BinaryArithmeticSpecializer();
 
+  @override
   AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -408,6 +420,7 @@
             .isDefinitelyTrue;
   }
 
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
@@ -465,6 +478,7 @@
 class AddSpecializer extends BinaryArithmeticSpecializer {
   const AddSpecializer();
 
+  @override
   AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -480,10 +494,12 @@
         .computeTypeFromInputTypes(instruction, results, options, closedWorld);
   }
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.add;
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -506,10 +522,12 @@
 class DivideSpecializer extends BinaryArithmeticSpecializer {
   const DivideSpecializer();
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.divide;
   }
 
+  @override
   AbstractValue computeTypeFromInputTypes(
       HInstruction instruction,
       GlobalTypeInferenceResults results,
@@ -523,6 +541,7 @@
         .computeTypeFromInputTypes(instruction, results, options, closedWorld);
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -542,6 +561,7 @@
 class ModuloSpecializer extends BinaryArithmeticSpecializer {
   const ModuloSpecializer();
 
+  @override
   AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -554,10 +574,12 @@
         .computeTypeFromInputTypes(instruction, results, options, closedWorld);
   }
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.modulo;
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -634,6 +656,7 @@
 class RemainderSpecializer extends BinaryArithmeticSpecializer {
   const RemainderSpecializer();
 
+  @override
   AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -646,10 +669,12 @@
         .computeTypeFromInputTypes(instruction, results, options, closedWorld);
   }
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.remainder;
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -672,10 +697,12 @@
 class MultiplySpecializer extends BinaryArithmeticSpecializer {
   const MultiplySpecializer();
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.multiply;
   }
 
+  @override
   AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -688,6 +715,7 @@
         .computeTypeFromInputTypes(instruction, results, options, closedWorld);
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -710,10 +738,12 @@
 class SubtractSpecializer extends BinaryArithmeticSpecializer {
   const SubtractSpecializer();
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.subtract;
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -736,10 +766,12 @@
 class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer {
   const TruncatingDivideSpecializer();
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.truncatingDivide;
   }
 
+  @override
   AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -789,6 +821,7 @@
     return false;
   }
 
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
@@ -824,6 +857,7 @@
     return null;
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -846,6 +880,7 @@
 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer {
   const BinaryBitOpSpecializer();
 
+  @override
   AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -895,10 +930,12 @@
 class ShiftLeftSpecializer extends BinaryBitOpSpecializer {
   const ShiftLeftSpecializer();
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.shiftLeft;
   }
 
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
@@ -933,6 +970,7 @@
     return null;
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -955,6 +993,7 @@
 class ShiftRightSpecializer extends BinaryBitOpSpecializer {
   const ShiftRightSpecializer();
 
+  @override
   AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -968,6 +1007,7 @@
         .computeTypeFromInputTypes(instruction, results, options, closedWorld);
   }
 
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
@@ -1015,6 +1055,7 @@
     return null;
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -1027,6 +1068,7 @@
         computeTypeFromInputTypes(instruction, results, options, closedWorld));
   }
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.shiftRight;
   }
@@ -1041,10 +1083,12 @@
 class BitOrSpecializer extends BinaryBitOpSpecializer {
   const BitOrSpecializer();
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.bitOr;
   }
 
+  @override
   AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -1060,6 +1104,7 @@
         .computeTypeFromInputTypes(instruction, results, options, closedWorld);
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -1072,6 +1117,7 @@
         computeTypeFromInputTypes(instruction, results, options, closedWorld));
   }
 
+  @override
   void registerOptimization(
       OptimizationTestLog log, HInstruction original, HInstruction converted) {
     log.registerBitOr(original, converted);
@@ -1081,10 +1127,12 @@
 class BitAndSpecializer extends BinaryBitOpSpecializer {
   const BitAndSpecializer();
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.bitAnd;
   }
 
+  @override
   AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -1103,6 +1151,7 @@
         .computeTypeFromInputTypes(instruction, results, options, closedWorld);
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -1115,6 +1164,7 @@
         computeTypeFromInputTypes(instruction, results, options, closedWorld));
   }
 
+  @override
   void registerOptimization(
       OptimizationTestLog log, HInstruction original, HInstruction converted) {
     log.registerBitAnd(original, converted);
@@ -1124,10 +1174,12 @@
 class BitXorSpecializer extends BinaryBitOpSpecializer {
   const BitXorSpecializer();
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.bitXor;
   }
 
+  @override
   AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -1143,6 +1195,7 @@
         .computeTypeFromInputTypes(instruction, results, options, closedWorld);
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -1155,6 +1208,7 @@
         computeTypeFromInputTypes(instruction, results, options, closedWorld));
   }
 
+  @override
   void registerOptimization(
       OptimizationTestLog log, HInstruction original, HInstruction converted) {
     log.registerBitXor(original, converted);
@@ -1164,6 +1218,7 @@
 abstract class RelationalSpecializer extends InvokeDynamicSpecializer {
   const RelationalSpecializer();
 
+  @override
   AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
@@ -1178,6 +1233,7 @@
         .computeTypeFromInputTypes(instruction, results, options, closedWorld);
   }
 
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
@@ -1209,6 +1265,7 @@
 class EqualsSpecializer extends RelationalSpecializer {
   const EqualsSpecializer();
 
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
@@ -1250,10 +1307,12 @@
     return null;
   }
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.equal;
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction, JClosedWorld closedWorld) {
     return new HIdentity(instruction.inputs[1], instruction.inputs[2],
@@ -1270,10 +1329,12 @@
 class LessSpecializer extends RelationalSpecializer {
   const LessSpecializer();
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.less;
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction, JClosedWorld closedWorld) {
     return new HLess(instruction.inputs[1], instruction.inputs[2],
@@ -1290,10 +1351,12 @@
 class GreaterSpecializer extends RelationalSpecializer {
   const GreaterSpecializer();
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.greater;
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction, JClosedWorld closedWorld) {
     return new HGreater(instruction.inputs[1], instruction.inputs[2],
@@ -1310,10 +1373,12 @@
 class GreaterEqualSpecializer extends RelationalSpecializer {
   const GreaterEqualSpecializer();
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.greaterEqual;
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction, JClosedWorld closedWorld) {
     return new HGreaterEqual(instruction.inputs[1], instruction.inputs[2],
@@ -1330,10 +1395,12 @@
 class LessEqualSpecializer extends RelationalSpecializer {
   const LessEqualSpecializer();
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.lessEqual;
   }
 
+  @override
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction, JClosedWorld closedWorld) {
     return new HLessEqual(instruction.inputs[1], instruction.inputs[2],
@@ -1350,10 +1417,12 @@
 class CodeUnitAtSpecializer extends InvokeDynamicSpecializer {
   const CodeUnitAtSpecializer();
 
+  @override
   constant_system.BinaryOperation operation() {
     return constant_system.codeUnitAt;
   }
 
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
@@ -1387,6 +1456,7 @@
 class CompareToSpecializer extends InvokeDynamicSpecializer {
   const CompareToSpecializer();
 
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
@@ -1436,6 +1506,7 @@
     extends InvokeDynamicSpecializer {
   const IdempotentStringOperationSpecializer();
 
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
@@ -1482,6 +1553,7 @@
 class PatternMatchSpecializer extends InvokeDynamicSpecializer {
   const PatternMatchSpecializer();
 
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
@@ -1510,10 +1582,12 @@
 class RoundSpecializer extends InvokeDynamicSpecializer {
   const RoundSpecializer();
 
+  @override
   constant_system.UnaryOperation operation() {
     return constant_system.round;
   }
 
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
diff --git a/pkg/compiler/lib/src/ssa/jump_handler.dart b/pkg/compiler/lib/src/ssa/jump_handler.dart
index 20d604b0..df6a83e 100644
--- a/pkg/compiler/lib/src/ssa/jump_handler.dart
+++ b/pkg/compiler/lib/src/ssa/jump_handler.dart
@@ -45,25 +45,34 @@
 
   NullJumpHandler(this.reporter);
 
+  @override
   void generateBreak(SourceInformation sourceInformation,
       [LabelDefinition label]) {
     reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
         'NullJumpHandler.generateBreak should not be called.');
   }
 
+  @override
   void generateContinue(SourceInformation sourceInformation,
       [LabelDefinition label]) {
     reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
         'NullJumpHandler.generateContinue should not be called.');
   }
 
+  @override
   void forEachBreak(Function ignored) {}
+  @override
   void forEachContinue(Function ignored) {}
+  @override
   void close() {}
+  @override
   bool hasAnyContinue() => false;
+  @override
   bool hasAnyBreak() => false;
 
+  @override
   List<LabelDefinition> get labels => const <LabelDefinition>[];
+  @override
   JumpTarget get target => null;
 }
 
@@ -73,6 +82,7 @@
 /// breaks of the body. Continues in switches is currently not handled.
 class TargetJumpHandler implements JumpHandler {
   final GraphBuilder builder;
+  @override
   final JumpTarget target;
   final List<_JumpHandlerEntry> jumps;
 
@@ -83,6 +93,7 @@
     builder.jumpTargets[target] = this;
   }
 
+  @override
   void generateBreak(SourceInformation sourceInformation,
       [LabelDefinition label]) {
     HInstruction breakInstruction;
@@ -98,6 +109,7 @@
     jumps.add(new _JumpHandlerEntry(breakInstruction, locals));
   }
 
+  @override
   void generateContinue(SourceInformation sourceInformation,
       [LabelDefinition label]) {
     HInstruction continueInstruction;
@@ -116,18 +128,21 @@
     jumps.add(new _JumpHandlerEntry(continueInstruction, locals));
   }
 
+  @override
   void forEachBreak(Function action) {
     for (_JumpHandlerEntry entry in jumps) {
       if (entry.isBreak()) action(entry.jumpInstruction, entry.locals);
     }
   }
 
+  @override
   void forEachContinue(Function action) {
     for (_JumpHandlerEntry entry in jumps) {
       if (entry.isContinue()) action(entry.jumpInstruction, entry.locals);
     }
   }
 
+  @override
   bool hasAnyContinue() {
     for (_JumpHandlerEntry entry in jumps) {
       if (entry.isContinue()) return true;
@@ -135,6 +150,7 @@
     return false;
   }
 
+  @override
   bool hasAnyBreak() {
     for (_JumpHandlerEntry entry in jumps) {
       if (entry.isBreak()) return true;
@@ -142,11 +158,13 @@
     return false;
   }
 
+  @override
   void close() {
     // The mapping from TargetElement to JumpHandler is no longer needed.
     builder.jumpTargets.remove(target);
   }
 
+  @override
   List<LabelDefinition> get labels {
     List<LabelDefinition> result = null;
     for (LabelDefinition element in target.labels) {
@@ -167,6 +185,7 @@
   SwitchCaseJumpHandler(GraphBuilder builder, JumpTarget target)
       : super(builder, target);
 
+  @override
   void generateBreak(SourceInformation sourceInformation,
       [LabelDefinition label]) {
     if (label == null) {
@@ -189,6 +208,7 @@
     return label != null && targetIndexMap.containsKey(label.target);
   }
 
+  @override
   void generateContinue(SourceInformation sourceInformation,
       [LabelDefinition label]) {
     if (isContinueToSwitchCase(label)) {
@@ -212,6 +232,7 @@
     }
   }
 
+  @override
   void close() {
     // The mapping from TargetElement to JumpHandler is no longer needed.
     for (JumpTarget target in targetIndexMap.keys) {
diff --git a/pkg/compiler/lib/src/ssa/locals_handler.dart b/pkg/compiler/lib/src/ssa/locals_handler.dart
index b74bb8c..9c08d57 100644
--- a/pkg/compiler/lib/src/ssa/locals_handler.dart
+++ b/pkg/compiler/lib/src/ssa/locals_handler.dart
@@ -692,15 +692,18 @@
 /// For instance used for holding return value of function or the exception of a
 /// try-catch statement.
 class SyntheticLocal extends Local {
+  @override
   final String name;
   final Entity executableContext;
   final MemberEntity memberContext;
 
   // Avoid slow Object.hashCode.
+  @override
   final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30);
   static int _nextHashCode = 0;
 
   SyntheticLocal(this.name, this.executableContext, this.memberContext);
 
+  @override
   toString() => 'SyntheticLocal($name)';
 }
diff --git a/pkg/compiler/lib/src/ssa/logging.dart b/pkg/compiler/lib/src/ssa/logging.dart
index cdaef90..0a99d31 100644
--- a/pkg/compiler/lib/src/ssa/logging.dart
+++ b/pkg/compiler/lib/src/ssa/logging.dart
@@ -244,6 +244,7 @@
     return entries.join(',\n');
   }
 
+  @override
   String toString() => 'OptimizationLog(${getText()})';
 }
 
@@ -257,5 +258,6 @@
 
   OptimizationLogEntry(this.tag, this.features);
 
+  @override
   String toString() => '$tag(${features.getText()})';
 }
diff --git a/pkg/compiler/lib/src/ssa/loop_handler.dart b/pkg/compiler/lib/src/ssa/loop_handler.dart
index be4fb554..f9fda03 100644
--- a/pkg/compiler/lib/src/ssa/loop_handler.dart
+++ b/pkg/compiler/lib/src/ssa/loop_handler.dart
@@ -313,6 +313,7 @@
 // TODO(het): Since kernel simplifies loop breaks and continues, we should
 // rewrite the loop handler from scratch to account for the simplified structure
 class KernelLoopHandler extends LoopHandler {
+  @override
   final KernelSsaGraphBuilder builder;
 
   KernelLoopHandler(KernelSsaGraphBuilder builder)
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 3b46935..0ec907d 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -188,6 +188,7 @@
 
   visitInstruction(HInstruction node);
 
+  @override
   visitBasicBlock(HBasicBlock node) {
     void visitInstructionList(HInstructionList list) {
       HInstruction instruction = list.first;
@@ -398,12 +399,14 @@
     return validator.isValid;
   }
 
+  @override
   toString() => 'HGraph($element)';
 }
 
 class HBaseVisitor extends HGraphVisitor implements HVisitor {
   HBasicBlock currentBlock;
 
+  @override
   visitBasicBlock(HBasicBlock node) {
     currentBlock = node;
 
@@ -428,93 +431,171 @@
   visitFieldAccess(HFieldAccess node) => visitInstruction(node);
   visitRelational(HRelational node) => visitInvokeBinary(node);
 
+  @override
   visitAbs(HAbs node) => visitInvokeUnary(node);
+  @override
   visitAdd(HAdd node) => visitBinaryArithmetic(node);
+  @override
   visitBitAnd(HBitAnd node) => visitBinaryBitOp(node);
+  @override
   visitBitNot(HBitNot node) => visitInvokeUnary(node);
+  @override
   visitBitOr(HBitOr node) => visitBinaryBitOp(node);
+  @override
   visitBitXor(HBitXor node) => visitBinaryBitOp(node);
+  @override
   visitBoolify(HBoolify node) => visitInstruction(node);
+  @override
   visitBoundsCheck(HBoundsCheck node) => visitCheck(node);
+  @override
   visitBreak(HBreak node) => visitJump(node);
+  @override
   visitContinue(HContinue node) => visitJump(node);
   visitCheck(HCheck node) => visitInstruction(node);
+  @override
   visitConstant(HConstant node) => visitInstruction(node);
+  @override
   visitCreate(HCreate node) => visitInstruction(node);
+  @override
   visitCreateBox(HCreateBox node) => visitInstruction(node);
+  @override
   visitDivide(HDivide node) => visitBinaryArithmetic(node);
+  @override
   visitExit(HExit node) => visitControlFlow(node);
+  @override
   visitExitTry(HExitTry node) => visitControlFlow(node);
+  @override
   visitFieldGet(HFieldGet node) => visitFieldAccess(node);
+  @override
   visitFieldSet(HFieldSet node) => visitFieldAccess(node);
+  @override
   visitForeignCode(HForeignCode node) => visitInstruction(node);
+  @override
   visitGetLength(HGetLength node) => visitInstruction(node);
+  @override
   visitGoto(HGoto node) => visitControlFlow(node);
+  @override
   visitGreater(HGreater node) => visitRelational(node);
+  @override
   visitGreaterEqual(HGreaterEqual node) => visitRelational(node);
+  @override
   visitIdentity(HIdentity node) => visitRelational(node);
+  @override
   visitIf(HIf node) => visitConditionalBranch(node);
+  @override
   visitIndex(HIndex node) => visitInstruction(node);
+  @override
   visitIndexAssign(HIndexAssign node) => visitInstruction(node);
+  @override
   visitInterceptor(HInterceptor node) => visitInstruction(node);
+  @override
   visitInvokeClosure(HInvokeClosure node) => visitInvokeDynamic(node);
+  @override
   visitInvokeConstructorBody(HInvokeConstructorBody node) =>
       visitInvokeStatic(node);
+  @override
   visitInvokeGeneratorBody(HInvokeGeneratorBody node) =>
       visitInvokeStatic(node);
+  @override
   visitInvokeDynamicMethod(HInvokeDynamicMethod node) =>
       visitInvokeDynamic(node);
+  @override
   visitInvokeDynamicGetter(HInvokeDynamicGetter node) =>
       visitInvokeDynamicField(node);
+  @override
   visitInvokeDynamicSetter(HInvokeDynamicSetter node) =>
       visitInvokeDynamicField(node);
+  @override
   visitInvokeStatic(HInvokeStatic node) => visitInvoke(node);
+  @override
   visitInvokeSuper(HInvokeSuper node) => visitInvokeStatic(node);
   visitJump(HJump node) => visitControlFlow(node);
+  @override
   visitLazyStatic(HLazyStatic node) => visitInstruction(node);
+  @override
   visitLess(HLess node) => visitRelational(node);
+  @override
   visitLessEqual(HLessEqual node) => visitRelational(node);
+  @override
   visitLiteralList(HLiteralList node) => visitInstruction(node);
   visitLocalAccess(HLocalAccess node) => visitInstruction(node);
+  @override
   visitLocalGet(HLocalGet node) => visitLocalAccess(node);
+  @override
   visitLocalSet(HLocalSet node) => visitLocalAccess(node);
+  @override
   visitLocalValue(HLocalValue node) => visitInstruction(node);
+  @override
   visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node);
+  @override
   visitNegate(HNegate node) => visitInvokeUnary(node);
+  @override
   visitNot(HNot node) => visitInstruction(node);
+  @override
   visitOneShotInterceptor(HOneShotInterceptor node) => visitInvokeDynamic(node);
+  @override
   visitPhi(HPhi node) => visitInstruction(node);
+  @override
   visitMultiply(HMultiply node) => visitBinaryArithmetic(node);
+  @override
   visitParameterValue(HParameterValue node) => visitLocalValue(node);
+  @override
   visitRangeConversion(HRangeConversion node) => visitCheck(node);
+  @override
   visitReadModifyWrite(HReadModifyWrite node) => visitInstruction(node);
+  @override
   visitRef(HRef node) => node.value.accept(this);
+  @override
   visitRemainder(HRemainder node) => visitBinaryArithmetic(node);
+  @override
   visitReturn(HReturn node) => visitControlFlow(node);
+  @override
   visitShiftLeft(HShiftLeft node) => visitBinaryBitOp(node);
+  @override
   visitShiftRight(HShiftRight node) => visitBinaryBitOp(node);
+  @override
   visitSubtract(HSubtract node) => visitBinaryArithmetic(node);
+  @override
   visitSwitch(HSwitch node) => visitControlFlow(node);
+  @override
   visitStatic(HStatic node) => visitInstruction(node);
+  @override
   visitStaticStore(HStaticStore node) => visitInstruction(node);
+  @override
   visitStringConcat(HStringConcat node) => visitInstruction(node);
+  @override
   visitStringify(HStringify node) => visitInstruction(node);
+  @override
   visitThis(HThis node) => visitParameterValue(node);
+  @override
   visitThrow(HThrow node) => visitControlFlow(node);
+  @override
   visitThrowExpression(HThrowExpression node) => visitInstruction(node);
+  @override
   visitTruncatingDivide(HTruncatingDivide node) => visitBinaryArithmetic(node);
+  @override
   visitTry(HTry node) => visitControlFlow(node);
+  @override
   visitIs(HIs node) => visitInstruction(node);
+  @override
   visitLateValue(HLateValue node) => visitInstruction(node);
+  @override
   visitIsViaInterceptor(HIsViaInterceptor node) => visitInstruction(node);
+  @override
   visitTypeConversion(HTypeConversion node) => visitCheck(node);
+  @override
   visitTypeKnown(HTypeKnown node) => visitCheck(node);
+  @override
   visitAwait(HAwait node) => visitInstruction(node);
+  @override
   visitYield(HYield node) => visitInstruction(node);
 
+  @override
   visitTypeInfoReadRaw(HTypeInfoReadRaw node) => visitInstruction(node);
+  @override
   visitTypeInfoReadVariable(HTypeInfoReadVariable node) =>
       visitInstruction(node);
+  @override
   visitTypeInfoExpression(HTypeInfoExpression node) => visitInstruction(node);
 }
 
@@ -669,6 +750,7 @@
         successors = const <HBasicBlock>[],
         dominatedBlocks = <HBasicBlock>[];
 
+  @override
   int get hashCode => id;
 
   bool isNew() => status == STATUS_NEW;
@@ -762,6 +844,7 @@
     instruction.notifyAddedToBlock(this);
   }
 
+  @override
   void remove(HInstruction instruction) {
     assert(isOpen() || isClosed());
     assert(instruction is! HPhi);
@@ -924,6 +1007,7 @@
         other.dominatorDfsOut <= this.dominatorDfsOut;
   }
 
+  @override
   toString() => 'HBasicBlock($id)';
 }
 
@@ -996,6 +1080,7 @@
     assert(inputs.every((e) => e != null), "inputs: $inputs");
   }
 
+  @override
   int get hashCode => id;
 
   bool useGvn() => _useGvn;
@@ -1473,6 +1558,7 @@
   @override
   accept(HVisitor visitor) => visitor.visitRef(this);
 
+  @override
   String toString() => 'HRef(${value})';
 }
 
@@ -1490,9 +1576,13 @@
     sourceInformation = value.sourceInformation;
   }
 
+  @override
   accept(HVisitor visitor) => visitor.visitBoolify(this);
+  @override
   int typeCode() => HInstruction.BOOLIFY_TYPECODE;
+  @override
   bool typeEquals(other) => other is HBoolify;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
@@ -1506,9 +1596,12 @@
     setUseGvn();
   }
   HInstruction get checkedInput => inputs[0];
+  @override
   bool isJsStatement() => true;
+  @override
   bool canThrow(AbstractValueDomain domain) => true;
 
+  @override
   HInstruction nonCheck() => checkedInput.nonCheck();
 }
 
@@ -1532,11 +1625,16 @@
   // There can be an additional fourth input which is the index to report to
   // [ioore]. This is used by the expansion of [JSArray.removeLast].
   HInstruction get reportedIndex => inputs.length > 3 ? inputs[3] : index;
+  @override
   bool isControlFlow() => true;
 
+  @override
   accept(HVisitor visitor) => visitor.visitBoundsCheck(this);
+  @override
   int typeCode() => HInstruction.BOUNDS_CHECK_TYPECODE;
+  @override
   bool typeEquals(other) => other is HBoundsCheck;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
@@ -1554,7 +1652,9 @@
       // have an `instructionType`, or statement-like [HInstruction]s should
       // have a throwing getter.
       : super(inputs, domain.emptyType);
+  @override
   bool isControlFlow() => true;
+  @override
   bool isJsStatement() => true;
 }
 
@@ -1582,6 +1682,7 @@
     this.sourceInformation = sourceInformation;
   }
 
+  @override
   bool isAllocation(AbstractValueDomain domain) => true;
 
   HInstruction get rtiInput {
@@ -1589,8 +1690,10 @@
     return inputs.last;
   }
 
+  @override
   accept(HVisitor visitor) => visitor.visitCreate(this);
 
+  @override
   String toString() => 'HCreate($element, ${instantiatedTypes})';
 }
 
@@ -1598,10 +1701,13 @@
 class HCreateBox extends HInstruction {
   HCreateBox(AbstractValue type) : super(<HInstruction>[], type);
 
+  @override
   bool isAllocation(AbstractValueDomain domain) => true;
 
+  @override
   accept(HVisitor visitor) => visitor.visitCreateBox(this);
 
+  @override
   String toString() => 'HCreateBox()';
 }
 
@@ -1617,7 +1723,9 @@
     sideEffects.setDependsOnSomething();
   }
   static const int ARGUMENTS_OFFSET = 1;
+  @override
   bool canThrow(AbstractValueDomain domain) => true;
+  @override
   bool isAllocation(AbstractValueDomain domain) => _isAllocation;
   void setAllocation(bool value) {
     _isAllocation = value;
@@ -1626,6 +1734,7 @@
 
 abstract class HInvokeDynamic extends HInvoke {
   final InvokeDynamicSpecializer specializer;
+  @override
   Selector selector;
   AbstractValue mask;
   MemberEntity element;
@@ -1640,8 +1749,10 @@
     assert(isIntercepted != null);
     isInterceptedCall = isIntercepted;
   }
+  @override
   toString() => 'invoke dynamic: selector=$selector, mask=$mask';
   HInstruction get receiver => inputs[0];
+  @override
   HInstruction getDartReceiver(JClosedWorld closedWorld) {
     return isCallOnInterceptor(closedWorld) ? inputs[1] : inputs[0];
   }
@@ -1654,8 +1765,11 @@
     return isInterceptedCall && receiver.isInterceptor(closedWorld);
   }
 
+  @override
   int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE;
+  @override
   bool typeEquals(other) => other is HInvokeDynamic;
+  @override
   bool dataEquals(HInvokeDynamic other) {
     // Use the name and the kind instead of [Selector.operator==]
     // because we don't need to check the arity (already checked in
@@ -1666,6 +1780,7 @@
 }
 
 class HInvokeClosure extends HInvokeDynamic {
+  @override
   final List<DartType> typeArguments;
 
   HInvokeClosure(Selector selector, List<HInstruction> inputs,
@@ -1675,10 +1790,12 @@
     assert(selector.callStructure.typeArgumentCount == typeArguments.length);
     assert(!isInterceptedCall);
   }
+  @override
   accept(HVisitor visitor) => visitor.visitInvokeClosure(this);
 }
 
 class HInvokeDynamicMethod extends HInvokeDynamic {
+  @override
   final List<DartType> typeArguments;
 
   HInvokeDynamicMethod(
@@ -1694,7 +1811,9 @@
     assert(selector.callStructure.typeArgumentCount == typeArguments.length);
   }
 
+  @override
   String toString() => 'invoke dynamic method: selector=$selector, mask=$mask';
+  @override
   accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
 }
 
@@ -1708,6 +1827,7 @@
       AbstractValue type)
       : super(selector, mask, element, inputs, isIntercepted, type);
 
+  @override
   String toString() => 'invoke dynamic field: selector=$selector, mask=$mask';
 }
 
@@ -1724,17 +1844,21 @@
     this.sourceInformation = sourceInformation;
   }
 
+  @override
   accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this);
 
   bool get isTearOff => element != null && element.isFunction;
 
+  @override
   List<DartType> get typeArguments => const <DartType>[];
 
   // There might be an interceptor input, so `inputs.last` is the dart receiver.
+  @override
   bool canThrow(AbstractValueDomain domain) => isTearOff
       ? inputs.last.isNull(domain).isPotentiallyTrue
       : super.canThrow(domain);
 
+  @override
   String toString() => 'invoke dynamic getter: selector=$selector, mask=$mask';
 }
 
@@ -1755,10 +1879,13 @@
     this.sourceInformation = sourceInformation;
   }
 
+  @override
   accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this);
 
+  @override
   List<DartType> get typeArguments => const <DartType>[];
 
+  @override
   String toString() =>
       'invoke dynamic setter: selector=$selector, mask=$mask, element=$element';
 }
@@ -1771,6 +1898,7 @@
 
   final bool targetCanThrow;
 
+  @override
   bool canThrow(AbstractValueDomain domain) => targetCanThrow;
 
   /// If this instruction is a call to a constructor, [instantiatedTypes]
@@ -1786,10 +1914,13 @@
     isInterceptedCall = isIntercepted;
   }
 
+  @override
   accept(HVisitor visitor) => visitor.visitInvokeStatic(this);
 
+  @override
   int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE;
 
+  @override
   String toString() => 'invoke static: $element';
 }
 
@@ -1797,6 +1928,7 @@
   /// The class where the call to super is being done.
   final ClassEntity caller;
   final bool isSetter;
+  @override
   final Selector selector;
 
   HInvokeSuper(
@@ -1815,6 +1947,7 @@
   }
 
   HInstruction get receiver => inputs[0];
+  @override
   HInstruction getDartReceiver(JClosedWorld closedWorld) {
     return isCallOnInterceptor(closedWorld) ? inputs[1] : inputs[0];
   }
@@ -1824,7 +1957,9 @@
     return isInterceptedCall && receiver.isInterceptor(closedWorld);
   }
 
+  @override
   toString() => 'invoke super: $element';
+  @override
   accept(HVisitor visitor) => visitor.visitInvokeSuper(this);
 
   HInstruction get value {
@@ -1847,7 +1982,9 @@
     this.sourceInformation = sourceInformation;
   }
 
+  @override
   String toString() => 'invoke constructor body: ${element.name}';
+  @override
   accept(HVisitor visitor) => visitor.visitInvokeConstructorBody(this);
 }
 
@@ -1866,7 +2003,9 @@
     this.sourceInformation = sourceInformation;
   }
 
+  @override
   String toString() => 'HInvokeGeneratorBody(${element.name})';
+  @override
   accept(HVisitor visitor) => visitor.visitInvokeGeneratorBody(this);
 }
 
@@ -1897,6 +2036,7 @@
     }
   }
 
+  @override
   bool isInterceptor(JClosedWorld closedWorld) {
     if (sourceElement == null) return false;
     // In case of a closure inside an interceptor class, [:this:] is
@@ -1910,18 +2050,26 @@
     return false;
   }
 
+  @override
   bool canThrow(AbstractValueDomain domain) =>
       receiver.isNull(domain).isPotentiallyTrue;
 
+  @override
   HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
+  @override
   bool onlyThrowsNSM() => true;
   bool get isNullCheck => element == null;
 
+  @override
   accept(HVisitor visitor) => visitor.visitFieldGet(this);
 
+  @override
   int typeCode() => HInstruction.FIELD_GET_TYPECODE;
+  @override
   bool typeEquals(other) => other is HFieldGet;
+  @override
   bool dataEquals(HFieldGet other) => element == other.element;
+  @override
   String toString() => "FieldGet(element=$element,type=$instructionType)";
 }
 
@@ -1934,18 +2082,24 @@
     sideEffects.setChangesInstanceProperty();
   }
 
+  @override
   bool canThrow(AbstractValueDomain domain) =>
       receiver.isNull(domain).isPotentiallyTrue;
 
+  @override
   HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
+  @override
   bool onlyThrowsNSM() => true;
 
   HInstruction get value => inputs[1];
+  @override
   accept(HVisitor visitor) => visitor.visitFieldSet(this);
 
   // HFieldSet is an expression if it has a user.
+  @override
   bool isJsStatement() => usedBy.isEmpty;
 
+  @override
   String toString() => "FieldSet(element=$element,type=$instructionType)";
 }
 
@@ -1965,17 +2119,25 @@
 
   HInstruction get receiver => inputs.single;
 
+  @override
   bool canThrow(AbstractValueDomain domain) =>
       receiver.isNull(domain).isPotentiallyTrue;
 
+  @override
   HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
+  @override
   bool onlyThrowsNSM() => true;
 
+  @override
   accept(HVisitor visitor) => visitor.visitGetLength(this);
 
+  @override
   int typeCode() => HInstruction.GET_LENGTH_TYPECODE;
+  @override
   bool typeEquals(other) => other is HGetLength;
+  @override
   bool dataEquals(HGetLength other) => true;
+  @override
   String toString() => "GetLength()";
 }
 
@@ -2017,16 +2179,22 @@
   bool get isPostOp => opKind == POST_OP;
   bool get isAssignOp => opKind == ASSIGN_OP;
 
+  @override
   bool canThrow(AbstractValueDomain domain) =>
       receiver.isNull(domain).isPotentiallyTrue;
 
+  @override
   HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
+  @override
   bool onlyThrowsNSM() => true;
 
   HInstruction get value => inputs[1];
+  @override
   accept(HVisitor visitor) => visitor.visitReadModifyWrite(this);
 
+  @override
   bool isJsStatement() => isAssignOp;
+  @override
   String toString() => "ReadModifyWrite $jsOp $opKind $element";
 }
 
@@ -2048,6 +2216,7 @@
     this.sourceInformation = sourceInformation;
   }
 
+  @override
   accept(HVisitor visitor) => visitor.visitLocalGet(this);
 
   HLocalValue get local => inputs[0];
@@ -2058,10 +2227,12 @@
       HInstruction value)
       : super(variable, <HInstruction>[local, value], domain.emptyType);
 
+  @override
   accept(HVisitor visitor) => visitor.visitLocalSet(this);
 
   HLocalValue get local => inputs[0];
   HInstruction get value => inputs[1];
+  @override
   bool isJsStatement() => true;
 }
 
@@ -2071,6 +2242,7 @@
   bool get isStatement => false;
   NativeBehavior get nativeBehavior => null;
 
+  @override
   bool canThrow(AbstractValueDomain domain) {
     return sideEffects.hasSideEffects() || sideEffects.dependsOnSomething();
   }
@@ -2078,7 +2250,9 @@
 
 class HForeignCode extends HForeign {
   final js.Template codeTemplate;
+  @override
   final bool isStatement;
+  @override
   final NativeBehavior nativeBehavior;
   NativeThrowBehavior throwBehavior;
   final FunctionEntity foreignFunction;
@@ -2116,9 +2290,12 @@
             effects: effects,
             nativeBehavior: nativeBehavior);
 
+  @override
   accept(HVisitor visitor) => visitor.visitForeignCode(this);
 
+  @override
   bool isJsStatement() => isStatement;
+  @override
   bool canThrow(AbstractValueDomain domain) {
     if (inputs.length > 0) {
       return inputs.first.isNull(domain).isPotentiallyTrue
@@ -2128,24 +2305,31 @@
     return throwBehavior.canThrow;
   }
 
+  @override
   bool onlyThrowsNSM() => throwBehavior.isOnlyNullNSMGuard;
 
+  @override
   bool isAllocation(AbstractValueDomain domain) =>
       nativeBehavior != null &&
       nativeBehavior.isAllocation &&
       isNull(domain).isDefinitelyFalse;
 
+  @override
   int typeCode() => HInstruction.FOREIGN_CODE_TYPECODE;
+  @override
   bool typeEquals(other) => other is HForeignCode;
+  @override
   bool dataEquals(HForeignCode other) {
     return codeTemplate.source != null &&
         codeTemplate.source == other.codeTemplate.source;
   }
 
+  @override
   String toString() => 'HForeignCode("${codeTemplate.source}")';
 }
 
 abstract class HInvokeBinary extends HInstruction {
+  @override
   final Selector selector;
   HInvokeBinary(
       HInstruction left, HInstruction right, this.selector, AbstractValue type)
@@ -2165,6 +2349,7 @@
   HBinaryArithmetic(HInstruction left, HInstruction right, Selector selector,
       AbstractValue type)
       : super(left, right, selector, type);
+  @override
   constant_system.BinaryOperation operation();
 }
 
@@ -2172,11 +2357,16 @@
   HAdd(HInstruction left, HInstruction right, Selector selector,
       AbstractValue type)
       : super(left, right, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitAdd(this);
 
+  @override
   constant_system.BinaryOperation operation() => constant_system.add;
+  @override
   int typeCode() => HInstruction.ADD_TYPECODE;
+  @override
   bool typeEquals(other) => other is HAdd;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
@@ -2184,11 +2374,16 @@
   HDivide(HInstruction left, HInstruction right, Selector selector,
       AbstractValue type)
       : super(left, right, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitDivide(this);
 
+  @override
   constant_system.BinaryOperation operation() => constant_system.divide;
+  @override
   int typeCode() => HInstruction.DIVIDE_TYPECODE;
+  @override
   bool typeEquals(other) => other is HDivide;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
@@ -2196,11 +2391,16 @@
   HMultiply(HInstruction left, HInstruction right, Selector selector,
       AbstractValue type)
       : super(left, right, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitMultiply(this);
 
+  @override
   constant_system.BinaryOperation operation() => constant_system.multiply;
+  @override
   int typeCode() => HInstruction.MULTIPLY_TYPECODE;
+  @override
   bool typeEquals(other) => other is HMultiply;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
@@ -2208,11 +2408,16 @@
   HSubtract(HInstruction left, HInstruction right, Selector selector,
       AbstractValue type)
       : super(left, right, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitSubtract(this);
 
+  @override
   constant_system.BinaryOperation operation() => constant_system.subtract;
+  @override
   int typeCode() => HInstruction.SUBTRACT_TYPECODE;
+  @override
   bool typeEquals(other) => other is HSubtract;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
@@ -2220,12 +2425,17 @@
   HTruncatingDivide(HInstruction left, HInstruction right, Selector selector,
       AbstractValue type)
       : super(left, right, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitTruncatingDivide(this);
 
+  @override
   constant_system.BinaryOperation operation() =>
       constant_system.truncatingDivide;
+  @override
   int typeCode() => HInstruction.TRUNCATING_DIVIDE_TYPECODE;
+  @override
   bool typeEquals(other) => other is HTruncatingDivide;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
@@ -2233,11 +2443,16 @@
   HRemainder(HInstruction left, HInstruction right, Selector selector,
       AbstractValue type)
       : super(left, right, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitRemainder(this);
 
+  @override
   constant_system.BinaryOperation operation() => constant_system.remainder;
+  @override
   int typeCode() => HInstruction.REMAINDER_TYPECODE;
+  @override
   bool typeEquals(other) => other is HRemainder;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
@@ -2256,8 +2471,10 @@
   /// following join-block.
   HBasicBlock get defaultTarget => block.successors.last;
 
+  @override
   accept(HVisitor visitor) => visitor.visitSwitch(this);
 
+  @override
   String toString() => "HSwitch cases = $inputs";
 }
 
@@ -2271,11 +2488,16 @@
   HShiftLeft(HInstruction left, HInstruction right, Selector selector,
       AbstractValue type)
       : super(left, right, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitShiftLeft(this);
 
+  @override
   constant_system.BinaryOperation operation() => constant_system.shiftLeft;
+  @override
   int typeCode() => HInstruction.SHIFT_LEFT_TYPECODE;
+  @override
   bool typeEquals(other) => other is HShiftLeft;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
@@ -2283,11 +2505,16 @@
   HShiftRight(HInstruction left, HInstruction right, Selector selector,
       AbstractValue type)
       : super(left, right, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitShiftRight(this);
 
+  @override
   constant_system.BinaryOperation operation() => constant_system.shiftRight;
+  @override
   int typeCode() => HInstruction.SHIFT_RIGHT_TYPECODE;
+  @override
   bool typeEquals(other) => other is HShiftRight;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
@@ -2295,11 +2522,16 @@
   HBitOr(HInstruction left, HInstruction right, Selector selector,
       AbstractValue type)
       : super(left, right, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitBitOr(this);
 
+  @override
   constant_system.BinaryOperation operation() => constant_system.bitOr;
+  @override
   int typeCode() => HInstruction.BIT_OR_TYPECODE;
+  @override
   bool typeEquals(other) => other is HBitOr;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
@@ -2307,11 +2539,16 @@
   HBitAnd(HInstruction left, HInstruction right, Selector selector,
       AbstractValue type)
       : super(left, right, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitBitAnd(this);
 
+  @override
   constant_system.BinaryOperation operation() => constant_system.bitAnd;
+  @override
   int typeCode() => HInstruction.BIT_AND_TYPECODE;
+  @override
   bool typeEquals(other) => other is HBitAnd;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
@@ -2319,15 +2556,21 @@
   HBitXor(HInstruction left, HInstruction right, Selector selector,
       AbstractValue type)
       : super(left, right, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitBitXor(this);
 
+  @override
   constant_system.BinaryOperation operation() => constant_system.bitXor;
+  @override
   int typeCode() => HInstruction.BIT_XOR_TYPECODE;
+  @override
   bool typeEquals(other) => other is HBitXor;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
 abstract class HInvokeUnary extends HInstruction {
+  @override
   final Selector selector;
   HInvokeUnary(HInstruction input, this.selector, type)
       : super(<HInstruction>[input], type) {
@@ -2344,45 +2587,64 @@
 class HNegate extends HInvokeUnary {
   HNegate(HInstruction input, Selector selector, AbstractValue type)
       : super(input, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitNegate(this);
 
+  @override
   constant_system.UnaryOperation operation() => constant_system.negate;
+  @override
   int typeCode() => HInstruction.NEGATE_TYPECODE;
+  @override
   bool typeEquals(other) => other is HNegate;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
 class HAbs extends HInvokeUnary {
   HAbs(HInstruction input, Selector selector, AbstractValue type)
       : super(input, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitAbs(this);
 
+  @override
   constant_system.UnaryOperation operation() => constant_system.abs;
+  @override
   int typeCode() => HInstruction.ABS_TYPECODE;
+  @override
   bool typeEquals(other) => other is HAbs;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
 class HBitNot extends HInvokeUnary {
   HBitNot(HInstruction input, Selector selector, AbstractValue type)
       : super(input, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitBitNot(this);
 
+  @override
   constant_system.UnaryOperation operation() => constant_system.bitNot;
+  @override
   int typeCode() => HInstruction.BIT_NOT_TYPECODE;
+  @override
   bool typeEquals(other) => other is HBitNot;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
 class HExit extends HControlFlow {
   HExit(AbstractValueDomain domain) : super(domain, const <HInstruction>[]);
+  @override
   toString() => 'exit';
+  @override
   accept(HVisitor visitor) => visitor.visitExit(this);
 }
 
 class HGoto extends HControlFlow {
   HGoto(AbstractValueDomain domain) : super(domain, const <HInstruction>[]);
+  @override
   toString() => 'goto';
+  @override
   accept(HVisitor visitor) => visitor.visitGoto(this);
 }
 
@@ -2420,8 +2682,10 @@
       : breakSwitchContinueLoop = false,
         super.toLabel(domain, label, sourceInformation);
 
+  @override
   String toString() => (label != null) ? 'break ${label.labelName}' : 'break';
 
+  @override
   accept(HVisitor visitor) => visitor.visitBreak(this);
 }
 
@@ -2434,9 +2698,11 @@
       SourceInformation sourceInformation)
       : super.toLabel(domain, label, sourceInformation);
 
+  @override
   String toString() =>
       (label != null) ? 'continue ${label.labelName}' : 'continue';
 
+  @override
   accept(HVisitor visitor) => visitor.visitContinue(this);
 }
 
@@ -2445,7 +2711,9 @@
   HBasicBlock catchBlock;
   HBasicBlock finallyBlock;
   HTry(AbstractValueDomain domain) : super(domain, const <HInstruction>[]);
+  @override
   toString() => 'try';
+  @override
   accept(HVisitor visitor) => visitor.visitTry(this);
   HBasicBlock get joinBlock => this.block.successors.last;
 }
@@ -2457,7 +2725,9 @@
 // finally.
 class HExitTry extends HControlFlow {
   HExitTry(AbstractValueDomain domain) : super(domain, const <HInstruction>[]);
+  @override
   toString() => 'exit try';
+  @override
   accept(HVisitor visitor) => visitor.visitExitTry(this);
   HBasicBlock get bodyTrySuccessor => block.successors[0];
 }
@@ -2466,7 +2736,9 @@
   HBlockFlow blockInformation = null;
   HIf(AbstractValueDomain domain, HInstruction condition)
       : super(domain, <HInstruction>[condition]);
+  @override
   toString() => 'if';
+  @override
   accept(HVisitor visitor) => visitor.visitIf(this);
 
   HBasicBlock get thenBlock {
@@ -2490,7 +2762,9 @@
   HLoopBranch(AbstractValueDomain domain, HInstruction condition,
       [this.kind = CONDITION_FIRST_LOOP])
       : super(domain, <HInstruction>[condition]);
+  @override
   toString() => 'loop-branch';
+  @override
   accept(HVisitor visitor) => visitor.visitLoopBranch(this);
 }
 
@@ -2499,25 +2773,40 @@
   HConstant.internal(this.constant, AbstractValue constantType)
       : super(<HInstruction>[], constantType);
 
+  @override
   toString() => 'literal: ${constant.toStructuredText()}';
+  @override
   accept(HVisitor visitor) => visitor.visitConstant(this);
 
+  @override
   bool isConstant() => true;
+  @override
   bool isConstantBoolean() => constant.isBool;
+  @override
   bool isConstantNull() => constant.isNull;
+  @override
   bool isConstantNumber() => constant.isNum;
+  @override
   bool isConstantInteger() => constant.isInt;
+  @override
   bool isConstantString() => constant.isString;
+  @override
   bool isConstantList() => constant.isList;
+  @override
   bool isConstantMap() => constant.isMap;
+  @override
   bool isConstantFalse() => constant.isFalse;
+  @override
   bool isConstantTrue() => constant.isTrue;
 
+  @override
   bool isInterceptor(JClosedWorld closedWorld) => constant.isInterceptor;
 
   // Maybe avoid this if the literal is big?
+  @override
   bool isCodeMotionInvariant() => true;
 
+  @override
   set instructionType(type) {
     // Only lists can be specialized. The SSA builder uses the
     // inferrer for finding the type of a constant list. We should
@@ -2533,9 +2822,13 @@
     setUseGvn();
   }
 
+  @override
   accept(HVisitor visitor) => visitor.visitNot(this);
+  @override
   int typeCode() => HInstruction.NOT_TYPECODE;
+  @override
   bool typeEquals(other) => other is HNot;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
@@ -2548,7 +2841,9 @@
     sourceElement = variable;
   }
 
+  @override
   toString() => 'local ${sourceElement.name}';
+  @override
   accept(HVisitor visitor) => visitor.visitLocalValue(this);
 }
 
@@ -2566,27 +2861,35 @@
     return false;
   }
 
+  @override
   toString() => 'parameter ${sourceElement.name}';
+  @override
   accept(HVisitor visitor) => visitor.visitParameterValue(this);
 }
 
 class HThis extends HParameterValue {
   HThis(ThisLocal element, AbstractValue type) : super(element, type);
 
+  @override
   ThisLocal get sourceElement => super.sourceElement;
+  @override
   void set sourceElement(covariant ThisLocal local) {
     super.sourceElement = local;
   }
 
+  @override
   accept(HVisitor visitor) => visitor.visitThis(this);
 
+  @override
   bool isCodeMotionInvariant() => true;
 
+  @override
   bool isInterceptor(JClosedWorld closedWorld) {
     return closedWorld.interceptorData
         .isInterceptedClass(sourceElement.enclosingClass);
   }
 
+  @override
   String toString() => 'this';
 }
 
@@ -2618,7 +2921,9 @@
     input.usedBy.add(this);
   }
 
+  @override
   toString() => 'phi $id';
+  @override
   accept(HVisitor visitor) => visitor.visitPhi(this);
 }
 
@@ -2632,52 +2937,77 @@
   String singleComparisonOp; // null, '===', '=='
 
   HIdentity(left, right, selector, type) : super(left, right, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitIdentity(this);
 
+  @override
   constant_system.BinaryOperation operation() => constant_system.identity;
+  @override
   int typeCode() => HInstruction.IDENTITY_TYPECODE;
+  @override
   bool typeEquals(other) => other is HIdentity;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
 class HGreater extends HRelational {
   HGreater(left, right, selector, type) : super(left, right, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitGreater(this);
 
+  @override
   constant_system.BinaryOperation operation() => constant_system.greater;
+  @override
   int typeCode() => HInstruction.GREATER_TYPECODE;
+  @override
   bool typeEquals(other) => other is HGreater;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
 class HGreaterEqual extends HRelational {
   HGreaterEqual(left, right, selector, type)
       : super(left, right, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitGreaterEqual(this);
 
+  @override
   constant_system.BinaryOperation operation() => constant_system.greaterEqual;
+  @override
   int typeCode() => HInstruction.GREATER_EQUAL_TYPECODE;
+  @override
   bool typeEquals(other) => other is HGreaterEqual;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
 class HLess extends HRelational {
   HLess(left, right, selector, type) : super(left, right, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitLess(this);
 
+  @override
   constant_system.BinaryOperation operation() => constant_system.less;
+  @override
   int typeCode() => HInstruction.LESS_TYPECODE;
+  @override
   bool typeEquals(other) => other is HLess;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
 class HLessEqual extends HRelational {
   HLessEqual(left, right, selector, type) : super(left, right, selector, type);
+  @override
   accept(HVisitor visitor) => visitor.visitLessEqual(this);
 
+  @override
   constant_system.BinaryOperation operation() => constant_system.lessEqual;
+  @override
   int typeCode() => HInstruction.LESS_EQUAL_TYPECODE;
+  @override
   bool typeEquals(other) => other is HLessEqual;
+  @override
   bool dataEquals(HInstruction other) => true;
 }
 
@@ -2687,7 +3017,9 @@
       : super(domain, <HInstruction>[value]) {
     this.sourceInformation = sourceInformation;
   }
+  @override
   toString() => 'return';
+  @override
   accept(HVisitor visitor) => visitor.visitReturn(this);
 }
 
@@ -2697,18 +3029,25 @@
       : super(<HInstruction>[value], domain.emptyType) {
     this.sourceInformation = sourceInformation;
   }
+  @override
   toString() => 'throw expression';
+  @override
   accept(HVisitor visitor) => visitor.visitThrowExpression(this);
+  @override
   bool canThrow(AbstractValueDomain domain) => true;
 }
 
 class HAwait extends HInstruction {
   HAwait(HInstruction value, AbstractValue type)
       : super(<HInstruction>[value], type);
+  @override
   toString() => 'await';
+  @override
   accept(HVisitor visitor) => visitor.visitAwait(this);
   // An await will throw if its argument is not a real future.
+  @override
   bool canThrow(AbstractValueDomain domain) => true;
+  @override
   SideEffects sideEffects = new SideEffects();
 }
 
@@ -2719,9 +3058,13 @@
     this.sourceInformation = sourceInformation;
   }
   bool hasStar;
+  @override
   toString() => 'yield';
+  @override
   accept(HVisitor visitor) => visitor.visitYield(this);
+  @override
   bool canThrow(AbstractValueDomain domain) => false;
+  @override
   SideEffects sideEffects = new SideEffects();
 }
 
@@ -2733,7 +3076,9 @@
       : super(domain, <HInstruction>[value]) {
     this.sourceInformation = sourceInformation;
   }
+  @override
   toString() => 'throw';
+  @override
   accept(HVisitor visitor) => visitor.visitThrow(this);
 }
 
@@ -2750,13 +3095,20 @@
     setUseGvn();
     this.sourceInformation = sourceInformation;
   }
+  @override
   toString() => 'static ${element.name}';
+  @override
   accept(HVisitor visitor) => visitor.visitStatic(this);
 
+  @override
   int gvnHashCode() => super.gvnHashCode() ^ element.hashCode;
+  @override
   int typeCode() => HInstruction.STATIC_TYPECODE;
+  @override
   bool typeEquals(other) => other is HStatic;
+  @override
   bool dataEquals(HStatic other) => element == other.element;
+  @override
   bool isCodeMotionInvariant() => !element.isAssignable;
 }
 
@@ -2782,7 +3134,9 @@
     setUseGvn();
   }
 
+  @override
   String toString() => 'interceptor on $interceptedClasses';
+  @override
   accept(HVisitor visitor) => visitor.visitInterceptor(this);
   HInstruction get receiver => inputs[0];
 
@@ -2793,10 +3147,14 @@
     inputs.add(constant);
   }
 
+  @override
   bool isInterceptor(JClosedWorld closedWorld) => true;
 
+  @override
   int typeCode() => HInstruction.INTERCEPTOR_TYPECODE;
+  @override
   bool typeEquals(other) => other is HInterceptor;
+  @override
   bool dataEquals(HInterceptor other) {
     return interceptedClasses == other.interceptedClasses ||
         (interceptedClasses.length == other.interceptedClasses.length &&
@@ -2812,6 +3170,7 @@
 /// calls, this class extends [HInvokeDynamic] and also has the null
 /// constant as the first input.
 class HOneShotInterceptor extends HInvokeDynamic {
+  @override
   List<DartType> typeArguments;
   Set<ClassEntity> interceptedClasses;
 
@@ -2828,9 +3187,12 @@
     assert(inputs[0].instructionType == domain.nullType);
     assert(selector.callStructure.typeArgumentCount == typeArguments.length);
   }
+  @override
   bool isCallOnInterceptor(JClosedWorld closedWorld) => true;
 
+  @override
   String toString() => 'one shot interceptor: selector=$selector, mask=$mask';
+  @override
   accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this);
 }
 
@@ -2848,12 +3210,17 @@
     this.sourceInformation = sourceInformation;
   }
 
+  @override
   toString() => 'lazy static ${element.name}';
+  @override
   accept(HVisitor visitor) => visitor.visitLazyStatic(this);
 
+  @override
   int typeCode() => 30;
   // TODO(4931): can we do better here?
+  @override
   bool isCodeMotionInvariant() => false;
+  @override
   bool canThrow(AbstractValueDomain domain) => true;
 }
 
@@ -2865,29 +3232,39 @@
     sideEffects.clearAllDependencies();
     sideEffects.setChangesStaticProperty();
   }
+  @override
   toString() => 'static store ${element.name}';
+  @override
   accept(HVisitor visitor) => visitor.visitStaticStore(this);
 
   HInstruction get value => inputs.single;
 
+  @override
   int typeCode() => HInstruction.STATIC_STORE_TYPECODE;
+  @override
   bool typeEquals(other) => other is HStaticStore;
+  @override
   bool dataEquals(HStaticStore other) => element == other.element;
+  @override
   bool isJsStatement() => usedBy.isEmpty;
 }
 
 class HLiteralList extends HInstruction {
   HLiteralList(List<HInstruction> inputs, AbstractValue type)
       : super(inputs, type);
+  @override
   toString() => 'literal list';
+  @override
   accept(HVisitor visitor) => visitor.visitLiteralList(this);
 
+  @override
   bool isAllocation(AbstractValueDomain domain) => true;
 }
 
 /// The primitive array indexing operation. Note that this instruction
 /// does not throw because we generate the checks explicitly.
 class HIndex extends HInstruction {
+  @override
   final Selector selector;
   HIndex(HInstruction receiver, HInstruction index, this.selector,
       AbstractValue type)
@@ -2898,7 +3275,9 @@
     setUseGvn();
   }
 
+  @override
   String toString() => 'index operator';
+  @override
   accept(HVisitor visitor) => visitor.visitIndex(this);
 
   HInstruction get receiver => inputs[0];
@@ -2906,21 +3285,29 @@
 
   // Implicit dependency on HBoundsCheck or constraints on index.
   // TODO(27272): Make HIndex dependent on bounds checking.
+  @override
   bool get isMovable => false;
 
+  @override
   HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
+  @override
   bool onlyThrowsNSM() => true;
+  @override
   bool canThrow(AbstractValueDomain domain) =>
       receiver.isNull(domain).isPotentiallyTrue;
 
+  @override
   int typeCode() => HInstruction.INDEX_TYPECODE;
+  @override
   bool typeEquals(HInstruction other) => other is HIndex;
+  @override
   bool dataEquals(HIndex other) => true;
 }
 
 /// The primitive array assignment operation. Note that this instruction
 /// does not throw because we generate the checks explicitly.
 class HIndexAssign extends HInstruction {
+  @override
   final Selector selector;
   HIndexAssign(AbstractValueDomain domain, HInstruction receiver,
       HInstruction index, HInstruction value, this.selector)
@@ -2929,7 +3316,9 @@
     sideEffects.clearAllDependencies();
     sideEffects.setChangesIndex();
   }
+  @override
   String toString() => 'index assign operator';
+  @override
   accept(HVisitor visitor) => visitor.visitIndexAssign(this);
 
   HInstruction get receiver => inputs[0];
@@ -2938,10 +3327,14 @@
 
   // Implicit dependency on HBoundsCheck or constraints on index.
   // TODO(27272): Make HIndex dependent on bounds checking.
+  @override
   bool get isMovable => false;
 
+  @override
   HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
+  @override
   bool onlyThrowsNSM() => true;
+  @override
   bool canThrow(AbstractValueDomain domain) =>
       receiver.isNull(domain).isPotentiallyTrue;
 }
@@ -3030,14 +3423,19 @@
   bool get isVariableCheck => kind == VARIABLE_CHECK;
   bool get isCompoundCheck => kind == COMPOUND_CHECK;
 
+  @override
   accept(HVisitor visitor) => visitor.visitIs(this);
 
+  @override
   toString() => "$expression is $typeExpression";
 
+  @override
   int typeCode() => HInstruction.IS_TYPECODE;
 
+  @override
   bool typeEquals(HInstruction other) => other is HIs;
 
+  @override
   bool dataEquals(HIs other) {
     return typeExpression == other.typeExpression && kind == other.kind;
   }
@@ -3056,10 +3454,15 @@
 
   HInstruction get interceptor => inputs[0];
 
+  @override
   accept(HVisitor visitor) => visitor.visitIsViaInterceptor(this);
+  @override
   toString() => "$interceptor is $typeExpression";
+  @override
   int typeCode() => HInstruction.IS_VIA_INTERCEPTOR_TYPECODE;
+  @override
   bool typeEquals(HInstruction other) => other is HIsViaInterceptor;
+  @override
   bool dataEquals(HIs other) {
     return typeExpression == other.typeExpression;
   }
@@ -3077,7 +3480,9 @@
 
   HInstruction get target => inputs.single;
 
+  @override
   accept(HVisitor visitor) => visitor.visitLateValue(this);
+  @override
   toString() => 'HLateValue($target)';
 }
 
@@ -3143,8 +3548,10 @@
 
   HInstruction get typeRepresentation => inputs[1];
 
+  @override
   HInstruction get checkedInput => super.checkedInput;
 
+  @override
   HInstruction convertType(JClosedWorld closedWorld, DartType type, int kind) {
     if (typeExpression == type) {
       // Don't omit a boolean conversion (which doesn't allow `null`) unless
@@ -3165,15 +3572,22 @@
   bool get isCastTypeCheck => kind == CAST_TYPE_CHECK;
   bool get isBooleanConversionCheck => kind == BOOLEAN_CONVERSION_CHECK;
 
+  @override
   accept(HVisitor visitor) => visitor.visitTypeConversion(this);
 
+  @override
   bool isJsStatement() => isControlFlow();
+  @override
   bool isControlFlow() => isArgumentTypeCheck || isReceiverTypeCheck;
 
+  @override
   int typeCode() => HInstruction.TYPE_CONVERSION_TYPECODE;
+  @override
   bool typeEquals(HInstruction other) => other is HTypeConversion;
+  @override
   bool isCodeMotionInvariant() => false;
 
+  @override
   bool dataEquals(HTypeConversion other) {
     return kind == other.kind &&
         typeExpression == other.typeExpression &&
@@ -3220,6 +3634,7 @@
     return abstractValueDomain.isIn(inputType, checkedType).isDefinitelyTrue;
   }
 
+  @override
   String toString() => 'HTypeConversion(type=$typeExpression, kind=$kind, '
       '${hasTypeRepresentation ? 'representation=$typeRepresentation, ' : ''}'
       'checkedInput=$checkedInput)';
@@ -3241,22 +3656,32 @@
         this._isMovable = true,
         super(<HInstruction>[input, witness], knownType);
 
+  @override
   toString() => 'TypeKnown $knownType';
+  @override
   accept(HVisitor visitor) => visitor.visitTypeKnown(this);
 
+  @override
   bool isJsStatement() => false;
+  @override
   bool isControlFlow() => false;
+  @override
   bool canThrow(AbstractValueDomain domain) => false;
 
   bool get isPinned => inputs.length == 1;
 
   HInstruction get witness => inputs.length == 2 ? inputs[1] : null;
 
+  @override
   int typeCode() => HInstruction.TYPE_KNOWN_TYPECODE;
+  @override
   bool typeEquals(HInstruction other) => other is HTypeKnown;
+  @override
   bool isCodeMotionInvariant() => true;
+  @override
   bool get isMovable => _isMovable && useGvn();
 
+  @override
   bool dataEquals(HTypeKnown other) {
     return knownType == other.knownType &&
         instructionType == other.instructionType;
@@ -3278,8 +3703,10 @@
     sourceElement = input.sourceElement;
   }
 
+  @override
   bool get isMovable => false;
 
+  @override
   accept(HVisitor visitor) => visitor.visitRangeConversion(this);
 }
 
@@ -3295,7 +3722,9 @@
   HInstruction get left => inputs[0];
   HInstruction get right => inputs[1];
 
+  @override
   accept(HVisitor visitor) => visitor.visitStringConcat(this);
+  @override
   toString() => "string concat";
 }
 
@@ -3308,7 +3737,9 @@
     sideEffects.setDependsOnSomething();
   }
 
+  @override
   accept(HVisitor visitor) => visitor.visitStringify(this);
+  @override
   toString() => "stringify";
 }
 
@@ -3372,11 +3803,13 @@
 
 /// Information about a statement-like structure.
 abstract class HStatementInformation extends HBlockInformation {
+  @override
   bool accept(HStatementInformationVisitor visitor);
 }
 
 /// Information about an expression-like structure.
 abstract class HExpressionInformation extends HBlockInformation {
+  @override
   bool accept(HExpressionInformationVisitor visitor);
   HInstruction get conditionExpression;
 }
@@ -3407,9 +3840,12 @@
   final SubGraph subGraph;
   HSubGraphBlockInformation(this.subGraph);
 
+  @override
   HBasicBlock get start => subGraph.start;
+  @override
   HBasicBlock get end => subGraph.end;
 
+  @override
   bool accept(HStatementInformationVisitor visitor) =>
       visitor.visitSubGraphInfo(this);
 }
@@ -3420,11 +3856,15 @@
   final SubExpression subExpression;
   HSubExpressionBlockInformation(this.subExpression);
 
+  @override
   HBasicBlock get start => subExpression.start;
+  @override
   HBasicBlock get end => subExpression.end;
 
+  @override
   HInstruction get conditionExpression => subExpression.conditionExpression;
 
+  @override
   bool accept(HExpressionInformationVisitor visitor) =>
       visitor.visitSubExpressionInfo(this);
 }
@@ -3434,9 +3874,12 @@
   final List<HStatementInformation> statements;
   HStatementSequenceInformation(this.statements);
 
+  @override
   HBasicBlock get start => statements[0].start;
+  @override
   HBasicBlock get end => statements.last.end;
 
+  @override
   bool accept(HStatementInformationVisitor visitor) =>
       visitor.visitSequenceInfo(this);
 }
@@ -3456,9 +3899,12 @@
       {this.isContinue: false})
       : this.labels = const <LabelDefinition>[];
 
+  @override
   HBasicBlock get start => body.start;
+  @override
   HBasicBlock get end => body.end;
 
+  @override
   bool accept(HStatementInformationVisitor visitor) =>
       visitor.visitLabeledBlockInfo(this);
 }
@@ -3486,6 +3932,7 @@
         (kind == DO_WHILE_LOOP ? body.start : condition.start).isLoopHeader());
   }
 
+  @override
   HBasicBlock get start {
     if (initializer != null) return initializer.start;
     if (kind == DO_WHILE_LOOP) {
@@ -3498,6 +3945,7 @@
     return kind == DO_WHILE_LOOP ? body.start : condition.start;
   }
 
+  @override
   HBasicBlock get end {
     if (updates != null) return updates.end;
     if (kind == DO_WHILE_LOOP && condition != null) {
@@ -3506,6 +3954,7 @@
     return body.end;
   }
 
+  @override
   bool accept(HStatementInformationVisitor visitor) =>
       visitor.visitLoopInfo(this);
 }
@@ -3516,9 +3965,12 @@
   final HStatementInformation elseGraph;
   HIfBlockInformation(this.condition, this.thenGraph, this.elseGraph);
 
+  @override
   HBasicBlock get start => condition.start;
+  @override
   HBasicBlock get end => elseGraph == null ? thenGraph.end : elseGraph.end;
 
+  @override
   bool accept(HStatementInformationVisitor visitor) =>
       visitor.visitIfInfo(this);
 }
@@ -3529,14 +3981,18 @@
   final HExpressionInformation right;
   HAndOrBlockInformation(this.isAnd, this.left, this.right);
 
+  @override
   HBasicBlock get start => left.start;
+  @override
   HBasicBlock get end => right.end;
 
   // We don't currently use HAndOrBlockInformation.
+  @override
   HInstruction get conditionExpression {
     return null;
   }
 
+  @override
   bool accept(HExpressionInformationVisitor visitor) =>
       visitor.visitAndOrInfo(this);
 }
@@ -3549,10 +4005,13 @@
   HTryBlockInformation(
       this.body, this.catchVariable, this.catchBlock, this.finallyBlock);
 
+  @override
   HBasicBlock get start => body.start;
+  @override
   HBasicBlock get end =>
       finallyBlock == null ? catchBlock.end : finallyBlock.end;
 
+  @override
   bool accept(HStatementInformationVisitor visitor) =>
       visitor.visitTryInfo(this);
 }
@@ -3567,13 +4026,16 @@
   HSwitchBlockInformation(this.expression, this.statements, this.target,
       this.labels, this.sourceInformation);
 
+  @override
   HBasicBlock get start => expression.start;
+  @override
   HBasicBlock get end {
     // We don't create a switch block if there are no cases.
     assert(!statements.isEmpty);
     return statements.last.end;
   }
 
+  @override
   bool accept(HStatementInformationVisitor visitor) =>
       visitor.visitSwitchInfo(this);
 }
@@ -3585,13 +4047,18 @@
     setUseGvn();
   }
 
+  @override
   accept(HVisitor visitor) => visitor.visitTypeInfoReadRaw(this);
 
+  @override
   bool canThrow(AbstractValueDomain domain) => false;
 
+  @override
   int typeCode() => HInstruction.TYPE_INFO_READ_RAW_TYPECODE;
+  @override
   bool typeEquals(HInstruction other) => other is HTypeInfoReadRaw;
 
+  @override
   bool dataEquals(HTypeInfoReadRaw other) {
     return true;
   }
@@ -3626,17 +4093,23 @@
 
   HInstruction get object => inputs.last;
 
+  @override
   accept(HVisitor visitor) => visitor.visitTypeInfoReadVariable(this);
 
+  @override
   bool canThrow(AbstractValueDomain domain) => false;
 
+  @override
   int typeCode() => HInstruction.TYPE_INFO_READ_VARIABLE_TYPECODE;
+  @override
   bool typeEquals(HInstruction other) => other is HTypeInfoReadVariable;
 
+  @override
   bool dataEquals(HTypeInfoReadVariable other) {
     return variable == other.variable;
   }
 
+  @override
   String toString() => 'HTypeInfoReadVariable($variable)';
 }
 
@@ -3706,17 +4179,23 @@
     setUseGvn();
   }
 
+  @override
   accept(HVisitor visitor) => visitor.visitTypeInfoExpression(this);
 
+  @override
   bool canThrow(AbstractValueDomain domain) => false;
 
+  @override
   int typeCode() => HInstruction.TYPE_INFO_EXPRESSION_TYPECODE;
+  @override
   bool typeEquals(HInstruction other) => other is HTypeInfoExpression;
 
+  @override
   bool dataEquals(HTypeInfoExpression other) {
     return kind == other.kind && dartType == other.dartType;
   }
 
+  @override
   String toString() => 'HTypeInfoExpression($kindAsString, $dartType)';
 
   // ignore: MISSING_RETURN
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index e40719b..e584210 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -48,6 +48,7 @@
 
   SsaOptimizerTask(this._backend) : super(_backend.compiler.measurer);
 
+  @override
   String get name => 'SSA optimizer';
 
   Compiler get _compiler => _backend.compiler;
@@ -191,6 +192,7 @@
   // strings.
   static const MAX_SHARED_CONSTANT_FOLDED_STRING_LENGTH = 512;
 
+  @override
   final String name = "SsaInstructionSimplifier";
   final GlobalTypeInferenceResults _globalInferenceResults;
   final CompilerOptions _options;
@@ -210,11 +212,13 @@
 
   NativeData get _nativeData => _closedWorld.nativeData;
 
+  @override
   void visitGraph(HGraph visitee) {
     _graph = visitee;
     visitDominatorTree(visitee);
   }
 
+  @override
   visitBasicBlock(HBasicBlock block) {
     simplifyPhis(block);
     HInstruction instruction = block.first;
@@ -383,6 +387,7 @@
     return true;
   }
 
+  @override
   HInstruction visitInstruction(HInstruction node) {
     return node;
   }
@@ -411,6 +416,7 @@
     }
   }
 
+  @override
   HInstruction visitParameterValue(HParameterValue node) {
     // [HParameterValue]s are either the value of the parameter (in fully SSA
     // converted code), or the mutable variable containing the value (in
@@ -436,6 +442,7 @@
     return node;
   }
 
+  @override
   HInstruction visitBoolify(HBoolify node) {
     List<HInstruction> inputs = node.inputs;
     assert(inputs.length == 1);
@@ -462,6 +469,7 @@
     return node;
   }
 
+  @override
   HInstruction visitNot(HNot node) {
     List<HInstruction> inputs = node.inputs;
     assert(inputs.length == 1);
@@ -476,6 +484,7 @@
     return node;
   }
 
+  @override
   HInstruction visitInvokeUnary(HInvokeUnary node) {
     HInstruction folded = foldUnary(node.operation(), node.operand);
     return folded != null ? folded : node;
@@ -688,6 +697,7 @@
     return tagInstruction;
   }
 
+  @override
   HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
     propagateConstantValueToUses(node);
     if (node.isInterceptedCall) {
@@ -849,6 +859,7 @@
     return result;
   }
 
+  @override
   HInstruction visitBoundsCheck(HBoundsCheck node) {
     HInstruction index = node.index;
     if (index.isInteger(_abstractValueDomain).isDefinitelyTrue) {
@@ -876,6 +887,7 @@
     return null;
   }
 
+  @override
   HInstruction visitAdd(HAdd node) {
     HInstruction left = node.left;
     HInstruction right = node.right;
@@ -889,6 +901,7 @@
     return super.visitAdd(node);
   }
 
+  @override
   HInstruction visitMultiply(HMultiply node) {
     HInstruction left = node.left;
     HInstruction right = node.right;
@@ -900,6 +913,7 @@
     return super.visitMultiply(node);
   }
 
+  @override
   HInstruction visitInvokeBinary(HInvokeBinary node) {
     HInstruction left = node.left;
     HInstruction right = node.right;
@@ -918,6 +932,7 @@
     return true;
   }
 
+  @override
   HInstruction visitRelational(HRelational node) {
     if (allUsersAreBoolifies(node)) {
       // TODO(ngeoffray): Call a boolified selector.
@@ -987,6 +1002,7 @@
     return null;
   }
 
+  @override
   HInstruction visitIdentity(HIdentity node) {
     HInstruction newInstruction = handleIdentityCheck(node);
     return newInstruction == null ? super.visitIdentity(node) : newInstruction;
@@ -1019,6 +1035,7 @@
     uses.replaceWith(_graph.addConstantBool(value, _closedWorld));
   }
 
+  @override
   HInstruction visitIf(HIf node) {
     HInstruction condition = node.condition;
     if (condition.isConstant()) return node;
@@ -1044,6 +1061,7 @@
     return node;
   }
 
+  @override
   HInstruction visitIs(HIs node) {
     DartType type = node.typeExpression;
 
@@ -1118,6 +1136,7 @@
     return node;
   }
 
+  @override
   HInstruction visitTypeConversion(HTypeConversion node) {
     if (node.isRedundant(_closedWorld)) return node.checkedInput;
 
@@ -1139,6 +1158,7 @@
     return node;
   }
 
+  @override
   HInstruction visitTypeKnown(HTypeKnown node) {
     return node.isRedundant(_closedWorld) ? node.checkedInput : node;
   }
@@ -1152,6 +1172,7 @@
     return member is FieldEntity ? member : null;
   }
 
+  @override
   HInstruction visitFieldGet(HFieldGet node) {
     if (node.isNullCheck) return node;
     var receiver = node.receiver;
@@ -1173,6 +1194,7 @@
     return node;
   }
 
+  @override
   HInstruction visitGetLength(HGetLength node) {
     HInstruction receiver = node.receiver;
     if (_graph.allocatedFixedLists.contains(receiver)) {
@@ -1219,6 +1241,7 @@
     return node;
   }
 
+  @override
   HInstruction visitIndex(HIndex node) {
     if (node.receiver.isConstantList() && node.index.isConstantInteger()) {
       HConstant instruction = node.receiver;
@@ -1234,6 +1257,7 @@
     return node;
   }
 
+  @override
   HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
     propagateConstantValueToUses(node);
     if (node.isInterceptedCall) {
@@ -1312,6 +1336,7 @@
         isAssignable: isAssignable);
   }
 
+  @override
   HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
     if (node.isInterceptedCall) {
       HInstruction folded = handleInterceptedCall(node);
@@ -1356,6 +1381,7 @@
     }
   }
 
+  @override
   HInstruction visitInvokeClosure(HInvokeClosure node) {
     HInstruction closure = node.getDartReceiver(_closedWorld);
 
@@ -1378,6 +1404,7 @@
     return node;
   }
 
+  @override
   HInstruction visitInvokeStatic(HInvokeStatic node) {
     propagateConstantValueToUses(node);
     MemberEntity element = node.element;
@@ -1478,6 +1505,7 @@
     return source;
   }
 
+  @override
   HInstruction visitStringConcat(HStringConcat node) {
     // Simplify string concat:
     //
@@ -1525,6 +1553,7 @@
     return new HStringConcat(prefix, folded, _abstractValueDomain.stringType);
   }
 
+  @override
   HInstruction visitStringify(HStringify node) {
     HInstruction input = node.inputs[0];
     if (input.isString(_abstractValueDomain).isDefinitelyTrue) {
@@ -1602,6 +1631,7 @@
     return tryConstant() ?? tryToString() ?? node;
   }
 
+  @override
   HInstruction visitOneShotInterceptor(HOneShotInterceptor node) {
     return handleInterceptedCall(node);
   }
@@ -1615,6 +1645,7 @@
     });
   }
 
+  @override
   HInstruction visitTypeInfoExpression(HTypeInfoExpression node) {
     // Identify the case where the type info expression would be of the form:
     //
@@ -1673,6 +1704,7 @@
     return tryCopyInfo() ?? node;
   }
 
+  @override
   HInstruction visitTypeInfoReadVariable(HTypeInfoReadVariable node) {
     TypeVariableType variable = node.variable;
     ClassEntity contextClass = variable.element.typeDeclaration;
@@ -1810,6 +1842,7 @@
   final Set<HInstruction> boundsChecked;
   final bool trustPrimitives;
   final JClosedWorld closedWorld;
+  @override
   final String name = "SsaCheckInserter";
   HGraph graph;
 
@@ -1818,6 +1851,7 @@
   AbstractValueDomain get _abstractValueDomain =>
       closedWorld.abstractValueDomain;
 
+  @override
   void visitGraph(HGraph graph) {
     this.graph = graph;
 
@@ -1829,6 +1863,7 @@
     visitDominatorTree(graph);
   }
 
+  @override
   void visitBasicBlock(HBasicBlock block) {
     HInstruction instruction = block.first;
     while (instruction != null) {
@@ -1866,18 +1901,21 @@
     return check;
   }
 
+  @override
   void visitIndex(HIndex node) {
     if (boundsChecked.contains(node)) return;
     HInstruction index = node.index;
     index = insertBoundsCheck(node, node.receiver, index);
   }
 
+  @override
   void visitIndexAssign(HIndexAssign node) {
     if (boundsChecked.contains(node)) return;
     HInstruction index = node.index;
     index = insertBoundsCheck(node, node.receiver, index);
   }
 
+  @override
   void visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
     MemberEntity element = node.element;
     if (node.isInterceptedCall) return;
@@ -1894,6 +1932,7 @@
 }
 
 class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase {
+  @override
   final String name = "SsaDeadCodeEliminator";
 
   final JClosedWorld closedWorld;
@@ -2018,6 +2057,7 @@
     return true;
   }
 
+  @override
   void visitGraph(HGraph graph) {
     _graph = graph;
     analyzer = new SsaLiveBlockAnalyzer(graph, closedWorld, optimizer);
@@ -2026,6 +2066,7 @@
     cleanPhis();
   }
 
+  @override
   void visitBasicBlock(HBasicBlock block) {
     bool isDeadBlock = analyzer.isDeadBlock(block);
     block.isLive = !isDeadBlock;
@@ -2247,10 +2288,12 @@
     }
   }
 
+  @override
   void visitControlFlow(HControlFlow instruction) {
     instruction.block.successors.forEach(markBlockLive);
   }
 
+  @override
   void visitIf(HIf instruction) {
     HInstruction condition = instruction.condition;
     if (condition.isConstant()) {
@@ -2264,6 +2307,7 @@
     }
   }
 
+  @override
   void visitSwitch(HSwitch node) {
     if (node.expression.isInteger(_abstractValueDomain).isDefinitelyTrue) {
       Range switchRange = ranges[node.expression];
@@ -2296,8 +2340,10 @@
 }
 
 class SsaDeadPhiEliminator implements OptimizationPhase {
+  @override
   final String name = "SsaDeadPhiEliminator";
 
+  @override
   void visitGraph(HGraph graph) {
     final List<HPhi> worklist = <HPhi>[];
     // A set to keep track of the live phis that we found.
@@ -2353,8 +2399,10 @@
 }
 
 class SsaRedundantPhiEliminator implements OptimizationPhase {
+  @override
   final String name = "SsaRedundantPhiEliminator";
 
+  @override
   void visitGraph(HGraph graph) {
     final List<HPhi> worklist = <HPhi>[];
 
@@ -2412,6 +2460,7 @@
 
 class SsaGlobalValueNumberer implements OptimizationPhase {
   final AbstractValueDomain _abstractValueDomain;
+  @override
   final String name = "SsaGlobalValueNumberer";
   final Set<int> visited;
 
@@ -2420,6 +2469,7 @@
 
   SsaGlobalValueNumberer(this._abstractValueDomain) : visited = new Set<int>();
 
+  @override
   void visitGraph(HGraph graph) {
     computeChangesFlags(graph);
     moveLoopInvariantCode(graph);
@@ -2635,6 +2685,7 @@
 class SsaCodeMotion extends HBaseVisitor implements OptimizationPhase {
   final AbstractValueDomain _abstractValueDomain;
 
+  @override
   final String name = "SsaCodeMotion";
 
   bool movedCode = false;
@@ -2642,6 +2693,7 @@
 
   SsaCodeMotion(this._abstractValueDomain);
 
+  @override
   void visitGraph(HGraph graph) {
     values = new List<ValueSet>(graph.blocks.length);
     for (int i = 0; i < graph.blocks.length; i++) {
@@ -2650,6 +2702,7 @@
     visitPostDominatorTree(graph);
   }
 
+  @override
   void visitBasicBlock(HBasicBlock block) {
     List<HBasicBlock> successors = block.successors;
 
@@ -2739,6 +2792,7 @@
 
 class SsaTypeConversionInserter extends HBaseVisitor
     implements OptimizationPhase {
+  @override
   final String name = "SsaTypeconversionInserter";
   final JClosedWorld closedWorld;
 
@@ -2747,6 +2801,7 @@
   AbstractValueDomain get _abstractValueDomain =>
       closedWorld.abstractValueDomain;
 
+  @override
   void visitGraph(HGraph graph) {
     visitDominatorTree(graph);
   }
@@ -2776,6 +2831,7 @@
     dominatedUses.replaceWith(newInput);
   }
 
+  @override
   void visitIs(HIs instruction) {
     DartType type = instruction.typeExpression;
     if (!instruction.isRawCheck) {
@@ -2806,6 +2862,7 @@
     // false. Avoid strengthening to `null`.
   }
 
+  @override
   void visitIdentity(HIdentity instruction) {
     // At HIf(HIdentity(x, null)) strengthens x to non-null on else branch.
     HInstruction left = instruction.left;
@@ -2885,6 +2942,7 @@
   final Compiler compiler;
   final JClosedWorld closedWorld;
   final JFieldAnalysis _fieldAnalysis;
+  @override
   final String name = "SsaLoadElimination";
   MemorySet memorySet;
   List<MemorySet> memories;
@@ -2897,6 +2955,7 @@
   AbstractValueDomain get _abstractValueDomain =>
       closedWorld.abstractValueDomain;
 
+  @override
   void visitGraph(HGraph graph) {
     _graph = graph;
     memories = new List<MemorySet>(graph.blocks.length);
@@ -2915,6 +2974,7 @@
     }
   }
 
+  @override
   void visitBasicBlock(HBasicBlock block) {
     if (block.predecessors.length == 0) {
       // Entry block.
@@ -2957,6 +3017,7 @@
     }
   }
 
+  @override
   void visitFieldGet(HFieldGet instruction) {
     if (instruction.isNullCheck) return;
     FieldEntity element = instruction.element;
@@ -2964,6 +3025,7 @@
     _visitFieldGet(element, receiver, instruction);
   }
 
+  @override
   void visitGetLength(HGetLength instruction) {
     HInstruction receiver = instruction.receiver.nonCheck();
     HInstruction existing =
@@ -2989,6 +3051,7 @@
     }
   }
 
+  @override
   void visitFieldSet(HFieldSet instruction) {
     FieldEntity element = instruction.element;
     HInstruction receiver = instruction.getDartReceiver(closedWorld).nonCheck();
@@ -2998,6 +3061,7 @@
     }
   }
 
+  @override
   void visitCreate(HCreate instruction) {
     memorySet.registerAllocation(instruction);
     if (shouldTrackInitialValues(instruction)) {
@@ -3063,6 +3127,7 @@
     return interestingUse(instruction, 0);
   }
 
+  @override
   void visitInstruction(HInstruction instruction) {
     if (instruction.isAllocation(_abstractValueDomain)) {
       memorySet.registerAllocation(instruction);
@@ -3070,6 +3135,7 @@
     memorySet.killAffectedBy(instruction);
   }
 
+  @override
   void visitLazyStatic(HLazyStatic instruction) {
     FieldEntity field = instruction.element;
     handleStaticLoad(field, instruction);
@@ -3086,10 +3152,12 @@
     }
   }
 
+  @override
   void visitStatic(HStatic instruction) {
     handleStaticLoad(instruction.element, instruction);
   }
 
+  @override
   void visitStaticStore(HStaticStore instruction) {
     if (memorySet.registerFieldValueUpdate(
         instruction.element, null, instruction.inputs.last)) {
@@ -3097,6 +3165,7 @@
     }
   }
 
+  @override
   void visitLiteralList(HLiteralList instruction) {
     memorySet.registerAllocation(instruction);
     memorySet.killAffectedBy(instruction);
@@ -3104,6 +3173,7 @@
     // TODO(sra): Set initial length.
   }
 
+  @override
   void visitIndex(HIndex instruction) {
     HInstruction receiver = instruction.receiver.nonCheck();
     HInstruction existing =
@@ -3117,6 +3187,7 @@
     }
   }
 
+  @override
   void visitIndexAssign(HIndexAssign instruction) {
     HInstruction receiver = instruction.receiver.nonCheck();
     memorySet.registerKeyedValueUpdate(
@@ -3124,20 +3195,35 @@
   }
 
   // Pure operations that do not escape their inputs.
+  @override
   void visitBinaryArithmetic(HBinaryArithmetic instruction) {}
+  @override
   void visitBoundsCheck(HBoundsCheck instruction) {}
+  @override
   void visitConstant(HConstant instruction) {}
+  @override
   void visitIf(HIf instruction) {}
+  @override
   void visitInterceptor(HInterceptor instruction) {}
+  @override
   void visitIs(HIs instruction) {}
+  @override
   void visitIsViaInterceptor(HIsViaInterceptor instruction) {}
+  @override
   void visitNot(HNot instruction) {}
+  @override
   void visitParameterValue(HParameterValue instruction) {}
+  @override
   void visitRelational(HRelational instruction) {}
+  @override
   void visitStringConcat(HStringConcat instruction) {}
+  @override
   void visitTypeKnown(HTypeKnown instruction) {}
+  @override
   void visitTypeInfoReadRaw(HTypeInfoReadRaw instruction) {}
+  @override
   void visitTypeInfoReadVariable(HTypeInfoReadVariable instruction) {}
+  @override
   void visitTypeInfoExpression(HTypeInfoExpression instruction) {}
 }
 
diff --git a/pkg/compiler/lib/src/ssa/ssa.dart b/pkg/compiler/lib/src/ssa/ssa.dart
index 41360b05..cdcc910 100644
--- a/pkg/compiler/lib/src/ssa/ssa.dart
+++ b/pkg/compiler/lib/src/ssa/ssa.dart
@@ -33,12 +33,14 @@
         optimizer = new SsaOptimizerTask(backend),
         backend = backend;
 
+  @override
   void onCodegenStart() {
     _builder.onCodegenStart();
   }
 
   /// Generates JavaScript code for `work.element`.
   /// Using the ssa builder, optimizer and code generator.
+  @override
   js.Fun compile(CodegenWorkItem work, JClosedWorld closedWorld,
       GlobalTypeInferenceResults globalInferenceResults) {
     HGraph graph = _builder.build(work, closedWorld, globalInferenceResults);
@@ -62,6 +64,7 @@
     return result;
   }
 
+  @override
   Iterable<CompilerTask> get tasks {
     return <CompilerTask>[_builder, optimizer, generator];
   }
@@ -82,6 +85,7 @@
   SsaBuilderTask(this._backend, this._sourceInformationFactory)
       : super(_backend.compiler.measurer);
 
+  @override
   String get name => 'SSA builder';
 
   void onCodegenStart() {
@@ -123,11 +127,9 @@
           /// constant value.
           return true;
         }
-      } else {
-        // If the constant-handler was not able to produce a result we have to
-        // go through the builder (below) to generate the lazy initializer for
-        // the static variable.
-        // We also need to register the use of the cyclic-error helper.
+      } else if (fieldData.isLazy) {
+        // The generated initializer needs be wrapped in the cyclic-error
+        // helper.
         registry.worldImpact.registerStaticUse(new StaticUse.staticInvoke(
             closedWorld.commonElements.cyclicThrowHelper,
             CallStructure.ONE_ARG));
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index ee7bc98..40770be 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -18,6 +18,7 @@
 class HTracer extends HGraphVisitor with TracerUtil {
   final JClosedWorld closedWorld;
   final Namer namer;
+  @override
   final OutputSink output;
 
   HTracer(this.output, this.closedWorld, this.namer);
@@ -72,6 +73,7 @@
     }
   }
 
+  @override
   void visitBasicBlock(HBasicBlock block) {
     HInstructionStringifier stringifier =
         new HInstructionStringifier(block, closedWorld, namer);
@@ -168,10 +170,12 @@
     return "$prefix${instruction.id}";
   }
 
+  @override
   String visitLateValue(HLateValue node) {
     return "LateValue: ${temporaryId(node.inputs[0])}";
   }
 
+  @override
   String visitBoolify(HBoolify node) {
     return "Boolify: ${temporaryId(node.inputs[0])}";
   }
@@ -182,30 +186,38 @@
     return '$opcode: $left $right';
   }
 
+  @override
   String visitAbs(HAbs node) {
     String operand = temporaryId(node.operand);
     return "Abs: $operand";
   }
 
+  @override
   String visitAdd(HAdd node) => handleInvokeBinary(node, 'Add');
 
+  @override
   String visitBitAnd(HBitAnd node) => handleInvokeBinary(node, 'BitAnd');
 
+  @override
   String visitBitNot(HBitNot node) {
     String operand = temporaryId(node.operand);
     return "BitNot: $operand";
   }
 
+  @override
   String visitBitOr(HBitOr node) => handleInvokeBinary(node, 'BitOr');
 
+  @override
   String visitBitXor(HBitXor node) => handleInvokeBinary(node, 'BitXor');
 
+  @override
   String visitBoundsCheck(HBoundsCheck node) {
     String lengthId = temporaryId(node.length);
     String indexId = temporaryId(node.index);
     return "BoundsCheck: length = $lengthId, index = $indexId";
   }
 
+  @override
   String visitBreak(HBreak node) {
     HBasicBlock target = currentBlock.successors[0];
     if (node.label != null) {
@@ -214,8 +226,10 @@
     return "Break: (B${target.id})";
   }
 
+  @override
   String visitConstant(HConstant constant) => "Constant: ${constant.constant}";
 
+  @override
   String visitContinue(HContinue node) {
     HBasicBlock target = currentBlock.successors[0];
     if (node.label != null) {
@@ -224,18 +238,23 @@
     return "Continue: (B${target.id})";
   }
 
+  @override
   String visitCreate(HCreate node) {
     return handleGenericInvoke("Create", "${node.element.name}", node.inputs);
   }
 
+  @override
   String visitCreateBox(HCreateBox node) {
     return handleGenericInvoke("CreateBox", "", node.inputs);
   }
 
+  @override
   String visitDivide(HDivide node) => handleInvokeBinary(node, 'Divide');
 
+  @override
   String visitExit(HExit node) => "Exit";
 
+  @override
   String visitFieldGet(HFieldGet node) {
     if (node.isNullCheck) {
       return 'FieldGet: NullCheck ${temporaryId(node.receiver)}';
@@ -244,12 +263,14 @@
     return 'FieldGet: ${temporaryId(node.receiver)}.$fieldName';
   }
 
+  @override
   String visitFieldSet(HFieldSet node) {
     String valueId = temporaryId(node.value);
     String fieldName = node.element.name;
     return 'FieldSet: ${temporaryId(node.receiver)}.$fieldName to $valueId';
   }
 
+  @override
   String visitReadModifyWrite(HReadModifyWrite node) {
     String fieldName = node.element.name;
     String receiverId = temporaryId(node.receiver);
@@ -264,33 +285,41 @@
     }
   }
 
+  @override
   String visitGetLength(HGetLength node) {
     return 'GetLength: ${temporaryId(node.receiver)}';
   }
 
+  @override
   String visitLocalGet(HLocalGet node) {
     String localName = node.variable.name;
     return 'LocalGet: ${temporaryId(node.local)}.$localName';
   }
 
+  @override
   String visitLocalSet(HLocalSet node) {
     String valueId = temporaryId(node.value);
     String localName = node.variable.name;
     return 'LocalSet: ${temporaryId(node.local)}.$localName to $valueId';
   }
 
+  @override
   String visitGoto(HGoto node) {
     HBasicBlock target = currentBlock.successors[0];
     return "Goto: (B${target.id})";
   }
 
+  @override
   String visitGreater(HGreater node) => handleInvokeBinary(node, 'Greater');
+  @override
   String visitGreaterEqual(HGreaterEqual node) {
     return handleInvokeBinary(node, 'GreaterEqual');
   }
 
+  @override
   String visitIdentity(HIdentity node) => handleInvokeBinary(node, 'Identity');
 
+  @override
   String visitIf(HIf node) {
     HBasicBlock thenBlock = currentBlock.successors[0];
     HBasicBlock elseBlock = currentBlock.successors[1];
@@ -308,12 +337,14 @@
     return "$invokeType: $functionName($argumentsString)";
   }
 
+  @override
   String visitIndex(HIndex node) {
     String receiver = temporaryId(node.receiver);
     String index = temporaryId(node.index);
     return "Index: $receiver[$index]";
   }
 
+  @override
   String visitIndexAssign(HIndexAssign node) {
     String receiver = temporaryId(node.receiver);
     String index = temporaryId(node.index);
@@ -321,6 +352,7 @@
     return "IndexAssign: $receiver[$index] = $value";
   }
 
+  @override
   String visitInterceptor(HInterceptor node) {
     String value = temporaryId(node.inputs[0]);
     if (node.interceptedClasses != null) {
@@ -330,6 +362,7 @@
     return "Interceptor: $value";
   }
 
+  @override
   String visitInvokeClosure(HInvokeClosure node) =>
       handleInvokeDynamic(node, "InvokeClosure");
 
@@ -342,33 +375,41 @@
     return handleGenericInvoke(kind, target, arguments) + "(${invoke.mask})";
   }
 
+  @override
   String visitInvokeDynamicMethod(HInvokeDynamicMethod node) =>
       handleInvokeDynamic(node, "InvokeDynamicMethod");
+  @override
   String visitInvokeDynamicGetter(HInvokeDynamicGetter node) =>
       handleInvokeDynamic(node, "InvokeDynamicGetter");
+  @override
   String visitInvokeDynamicSetter(HInvokeDynamicSetter node) =>
       handleInvokeDynamic(node, "InvokeDynamicSetter");
 
+  @override
   String visitInvokeStatic(HInvokeStatic invoke) {
     String target = invoke.element.name;
     return handleGenericInvoke("InvokeStatic", target, invoke.inputs);
   }
 
+  @override
   String visitInvokeSuper(HInvokeSuper invoke) {
     String target = invoke.element.name;
     return handleGenericInvoke("InvokeSuper", target, invoke.inputs);
   }
 
+  @override
   String visitInvokeConstructorBody(HInvokeConstructorBody invoke) {
     String target = invoke.element.name;
     return handleGenericInvoke("InvokeConstructorBody", target, invoke.inputs);
   }
 
+  @override
   String visitInvokeGeneratorBody(HInvokeGeneratorBody invoke) {
     String target = invoke.element.name;
     return handleGenericInvoke("InvokeGeneratorBody", target, invoke.inputs);
   }
 
+  @override
   String visitForeignCode(HForeignCode node) {
     var template = node.codeTemplate;
     String code = '${template.ast}';
@@ -376,10 +417,13 @@
     return "ForeignCode: $code ($inputs)";
   }
 
+  @override
   String visitLess(HLess node) => handleInvokeBinary(node, 'Less');
+  @override
   String visitLessEqual(HLessEqual node) =>
       handleInvokeBinary(node, 'LessEqual');
 
+  @override
   String visitLiteralList(HLiteralList node) {
     StringBuffer elementsString = new StringBuffer();
     for (int i = 0; i < node.inputs.length; i++) {
@@ -389,6 +433,7 @@
     return "LiteralList: [$elementsString]";
   }
 
+  @override
   String visitLoopBranch(HLoopBranch branch) {
     HBasicBlock bodyBlock = currentBlock.successors[0];
     HBasicBlock exitBlock = currentBlock.successors[1];
@@ -396,23 +441,29 @@
     return "LoopBranch ($conditionId): (B${bodyBlock.id}) then (B${exitBlock.id})";
   }
 
+  @override
   String visitMultiply(HMultiply node) => handleInvokeBinary(node, 'Multiply');
 
+  @override
   String visitNegate(HNegate node) {
     String operand = temporaryId(node.operand);
     return "Negate: $operand";
   }
 
+  @override
   String visitNot(HNot node) => "Not: ${temporaryId(node.inputs[0])}";
 
+  @override
   String visitParameterValue(HParameterValue node) {
     return "ParameterValue: ${node.sourceElement.name}";
   }
 
+  @override
   String visitLocalValue(HLocalValue node) {
     return "LocalValue: ${node.sourceElement.name}";
   }
 
+  @override
   String visitPhi(HPhi phi) {
     StringBuffer buffer = new StringBuffer();
     buffer.write("Phi: ");
@@ -423,42 +474,54 @@
     return buffer.toString();
   }
 
+  @override
   String visitRef(HRef node) {
     return 'Ref: ${temporaryId(node.value)}';
   }
 
+  @override
   String visitReturn(HReturn node) => "Return: ${temporaryId(node.inputs[0])}";
 
+  @override
   String visitShiftLeft(HShiftLeft node) =>
       handleInvokeBinary(node, 'ShiftLeft');
+  @override
   String visitShiftRight(HShiftRight node) =>
       handleInvokeBinary(node, 'ShiftRight');
 
+  @override
   String visitStatic(HStatic node) => "Static: ${node.element.name}";
 
+  @override
   String visitLazyStatic(HLazyStatic node) =>
       "LazyStatic: ${node.element.name}";
 
+  @override
   String visitOneShotInterceptor(HOneShotInterceptor node) =>
       handleInvokeDynamic(node, "OneShotInterceptor");
 
+  @override
   String visitStaticStore(HStaticStore node) {
     String lhs = node.element.name;
     return "StaticStore: $lhs = ${temporaryId(node.inputs[0])}";
   }
 
+  @override
   String visitStringConcat(HStringConcat node) {
     var leftId = temporaryId(node.left);
     var rightId = temporaryId(node.right);
     return "StringConcat: $leftId + $rightId";
   }
 
+  @override
   String visitStringify(HStringify node) {
     return "Stringify: ${temporaryId(node.inputs[0])}";
   }
 
+  @override
   String visitSubtract(HSubtract node) => handleInvokeBinary(node, 'Subtract');
 
+  @override
   String visitSwitch(HSwitch node) {
     StringBuffer buf = new StringBuffer();
     buf.write("Switch: (");
@@ -475,26 +538,33 @@
     return buf.toString();
   }
 
+  @override
   String visitThis(HThis node) => "This";
 
+  @override
   String visitThrow(HThrow node) => "Throw: ${temporaryId(node.inputs[0])}";
 
+  @override
   String visitThrowExpression(HThrowExpression node) {
     return "ThrowExpression: ${temporaryId(node.inputs[0])}";
   }
 
+  @override
   String visitTruncatingDivide(HTruncatingDivide node) {
     return handleInvokeBinary(node, 'TruncatingDivide');
   }
 
+  @override
   String visitRemainder(HRemainder node) {
     return handleInvokeBinary(node, 'Remainder');
   }
 
+  @override
   String visitExitTry(HExitTry node) {
     return "ExitTry";
   }
 
+  @override
   String visitTry(HTry node) {
     List<HBasicBlock> successors = currentBlock.successors;
     String tryBlock = 'B${successors[0].id}';
@@ -512,16 +582,19 @@
         "Join: B${successors.last.id}";
   }
 
+  @override
   String visitIs(HIs node) {
     String type = node.typeExpression.toString();
     return "Is: ${temporaryId(node.expression)} is $type";
   }
 
+  @override
   String visitIsViaInterceptor(HIsViaInterceptor node) {
     String type = node.typeExpression.toString();
     return "IsViaInterceptor: ${temporaryId(node.inputs[0])} is $type";
   }
 
+  @override
   String visitTypeConversion(HTypeConversion node) {
     String checkedInput = temporaryId(node.checkedInput);
     String rest;
@@ -551,6 +624,7 @@
     return '?';
   }
 
+  @override
   String visitTypeKnown(HTypeKnown node) {
     assert(node.inputs.length <= 2);
     String result =
@@ -561,30 +635,36 @@
     return result;
   }
 
+  @override
   String visitRangeConversion(HRangeConversion node) {
     return "RangeConversion: ${node.checkedInput}";
   }
 
+  @override
   String visitTypeInfoReadRaw(HTypeInfoReadRaw node) {
     var inputs = node.inputs.map(temporaryId).join(', ');
     return "TypeInfoReadRaw: $inputs";
   }
 
+  @override
   String visitTypeInfoReadVariable(HTypeInfoReadVariable node) {
     var inputs = node.inputs.map(temporaryId).join(', ');
     return "TypeInfoReadVariable: ${node.variable}  $inputs";
   }
 
+  @override
   String visitTypeInfoExpression(HTypeInfoExpression node) {
     var inputs = node.inputs.map(temporaryId).join(', ');
     return "TypeInfoExpression: ${node.kindAsString} ${node.dartType}"
         " ($inputs)";
   }
 
+  @override
   String visitAwait(HAwait node) {
     return "Await: ${temporaryId(node.inputs[0])}";
   }
 
+  @override
   String visitYield(HYield node) {
     return "Yield${node.hasStar ? "*" : ""}: ${temporaryId(node.inputs[0])}";
   }
diff --git a/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart b/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart
index 1efc255..bebc7e6 100644
--- a/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart
+++ b/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart
@@ -10,6 +10,7 @@
     return switchCaseBody.accept(new SwitchContinueAnalysis._());
   }
 
+  @override
   bool visitContinueSwitchStatement(ir.ContinueSwitchStatement continueStmt) {
     // TODO(efortuna): Check what the target of this continue statement actually
     // IS, because depending on where the label points if we have a nested
@@ -18,6 +19,7 @@
     return true;
   }
 
+  @override
   bool visitBlock(ir.Block block) {
     for (ir.Statement statement in block.statements) {
       if (statement.accept(this)) {
@@ -27,22 +29,27 @@
     return false;
   }
 
+  @override
   bool visitLabeledStatement(ir.LabeledStatement statement) {
     return statement.body.accept(this);
   }
 
+  @override
   bool visitDoStatement(ir.DoStatement doStatement) {
     return doStatement.body.accept(this);
   }
 
+  @override
   bool visitForStatement(ir.ForStatement forStatement) {
     return forStatement.body.accept(this);
   }
 
+  @override
   bool visitForInStatement(ir.ForInStatement forInStatement) {
     return forInStatement.body.accept(this);
   }
 
+  @override
   bool visitSwitchStatement(ir.SwitchStatement switchStatement) {
     for (var switchCase in switchStatement.cases) {
       if (switchCase.accept(this)) {
@@ -52,15 +59,18 @@
     return false;
   }
 
+  @override
   bool visitSwitchCase(ir.SwitchCase switchCase) {
     return switchCase.body.accept(this);
   }
 
+  @override
   bool visitIfStatement(ir.IfStatement ifStatement) {
     return ifStatement.then.accept(this) ||
         (ifStatement.otherwise != null && ifStatement.otherwise.accept(this));
   }
 
+  @override
   bool visitTryCatch(ir.TryCatch tryCatch) {
     if (tryCatch.body.accept(this)) {
       for (var catchStatement in tryCatch.catches) {
@@ -72,26 +82,32 @@
     return false;
   }
 
+  @override
   bool visitWhileStatement(ir.WhileStatement statement) {
     return statement.body.accept(this);
   }
 
+  @override
   bool visitCatch(ir.Catch catchStatement) {
     return catchStatement.body.accept(this);
   }
 
+  @override
   bool visitTryFinally(ir.TryFinally tryFinally) {
     return tryFinally.body.accept(this) && tryFinally.finalizer.accept(this);
   }
 
+  @override
   bool visitFunctionDeclaration(ir.FunctionDeclaration declaration) {
     return declaration.function.accept(this);
   }
 
+  @override
   bool visitFunctionNode(ir.FunctionNode node) {
     return node.body.accept(this);
   }
 
+  @override
   bool defaultStatement(ir.Statement node) {
     if (node is ir.ExpressionStatement ||
         node is ir.EmptyStatement ||
@@ -106,5 +122,6 @@
         'SwitchContinueAnalysis';
   }
 
+  @override
   bool defaultNode(ir.Node node) => false;
 }
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index 0c7b575..e716108 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -41,6 +41,7 @@
   final CommonElements commonElements;
   final JClosedWorld closedWorld;
   final OptimizationTestLog _log;
+  @override
   String get name => 'SsaTypePropagator';
 
   SsaTypePropagator(this.results, this.options, this.commonElements,
@@ -66,11 +67,13 @@
     return oldType != newType;
   }
 
+  @override
   void visitGraph(HGraph graph) {
     visitDominatorTree(graph);
     processWorklist();
   }
 
+  @override
   visitBasicBlock(HBasicBlock block) {
     if (block.isLoopHeader()) {
       block.forEachPhi((HPhi phi) {
@@ -129,6 +132,7 @@
     }
   }
 
+  @override
   AbstractValue visitBinaryArithmetic(HBinaryArithmetic instruction) {
     HInstruction left = instruction.left;
     HInstruction right = instruction.right;
@@ -152,29 +156,35 @@
     return visitBinaryArithmetic(instruction);
   }
 
+  @override
   AbstractValue visitMultiply(HMultiply instruction) {
     return checkPositiveInteger(instruction);
   }
 
+  @override
   AbstractValue visitAdd(HAdd instruction) {
     return checkPositiveInteger(instruction);
   }
 
+  @override
   AbstractValue visitDivide(HDivide instruction) {
     // Always double, as initialized.
     return instruction.instructionType;
   }
 
+  @override
   AbstractValue visitTruncatingDivide(HTruncatingDivide instruction) {
     // Always as initialized.
     return instruction.instructionType;
   }
 
+  @override
   AbstractValue visitRemainder(HRemainder instruction) {
     // Always as initialized.
     return instruction.instructionType;
   }
 
+  @override
   AbstractValue visitNegate(HNegate instruction) {
     HInstruction operand = instruction.operand;
     // We have integer subclasses that represent ranges, so widen any int
@@ -185,16 +195,19 @@
     return instruction.operand.instructionType;
   }
 
+  @override
   AbstractValue visitAbs(HAbs instruction) {
     // TODO(sra): Can narrow to non-negative type for integers.
     return instruction.operand.instructionType;
   }
 
+  @override
   AbstractValue visitInstruction(HInstruction instruction) {
     assert(instruction.instructionType != null);
     return instruction.instructionType;
   }
 
+  @override
   AbstractValue visitPhi(HPhi phi) {
     AbstractValue candidateType = abstractValueDomain.emptyType;
     for (int i = 0, length = phi.inputs.length; i < length; i++) {
@@ -204,6 +217,7 @@
     return candidateType;
   }
 
+  @override
   AbstractValue visitTypeConversion(HTypeConversion instruction) {
     HInstruction input = instruction.checkedInput;
     AbstractValue inputType = input.instructionType;
@@ -261,6 +275,7 @@
     return outputType;
   }
 
+  @override
   AbstractValue visitTypeKnown(HTypeKnown instruction) {
     HInstruction input = instruction.checkedInput;
     AbstractValue inputType = input.instructionType;
@@ -392,6 +407,7 @@
     });
   }
 
+  @override
   AbstractValue visitInvokeDynamic(HInvokeDynamic instruction) {
     if (instruction.isInterceptedCall) {
       // We cannot do the following optimization now, because we have to wait
diff --git a/pkg/compiler/lib/src/ssa/validate.dart b/pkg/compiler/lib/src/ssa/validate.dart
index 1f93b4e..74a852a 100644
--- a/pkg/compiler/lib/src/ssa/validate.dart
+++ b/pkg/compiler/lib/src/ssa/validate.dart
@@ -20,6 +20,7 @@
 
   // Note that during construction of the Ssa graph the basic blocks are
   // not required to be valid yet.
+  @override
   void visitBasicBlock(HBasicBlock block) {
     currentBlock = block;
     if (!isValid) return; // Don't need to continue if we are already invalid.
@@ -164,6 +165,7 @@
     return true;
   }
 
+  @override
   void visitInstruction(HInstruction instruction) {
     // Verifies that we are in the use list of our inputs.
     bool hasCorrectInputs() {
diff --git a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
index 639c727..a0af6be 100644
--- a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
+++ b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
@@ -102,6 +102,7 @@
 
   const MarkerValue(this.positive, info) : super(info);
 
+  @override
   Value operator +(Value other) {
     if (other.isPositive && positive) return const MaxIntValue();
     if (other.isNegative && !positive) return const MinIntValue();
@@ -109,6 +110,7 @@
     return const UnknownValue();
   }
 
+  @override
   Value operator -(Value other) {
     if (other.isPositive && !positive) return const MinIntValue();
     if (other.isNegative && positive) return const MaxIntValue();
@@ -123,6 +125,7 @@
 
   const IntValue(this.value, info) : super(info);
 
+  @override
   Value operator +(dynamic other) {
     if (other.isZero) return this;
     if (other is! IntValue) return other + this;
@@ -133,6 +136,7 @@
     return info.newIntValue(constant.intValue);
   }
 
+  @override
   Value operator -(dynamic other) {
     if (other.isZero) return this;
     if (other is! IntValue) return -other + this;
@@ -143,6 +147,7 @@
     return info.newIntValue(constant.intValue);
   }
 
+  @override
   Value operator -() {
     if (isZero) return this;
     dynamic constant =
@@ -151,6 +156,7 @@
     return info.newIntValue(constant.intValue);
   }
 
+  @override
   Value operator &(dynamic other) {
     if (other is! IntValue) return const UnknownValue();
     dynamic constant = constant_system.bitAnd.fold(
@@ -159,26 +165,34 @@
     return info.newIntValue(constant.intValue);
   }
 
+  @override
   Value min(dynamic other) {
     if (other is! IntValue) return other.min(this);
     return this.value < other.value ? this : other;
   }
 
+  @override
   Value max(dynamic other) {
     if (other is! IntValue) return other.max(this);
     return this.value < other.value ? other : this;
   }
 
+  @override
   bool operator ==(other) {
     if (other is! IntValue) return false;
     return this.value == other.value;
   }
 
+  @override
   int get hashCode => throw new UnsupportedError('IntValue.hashCode');
 
+  @override
   String toString() => 'IntValue $value';
+  @override
   bool get isNegative => value < BigInt.zero;
+  @override
   bool get isPositive => value >= BigInt.zero;
+  @override
   bool get isZero => value == BigInt.zero;
 }
 
@@ -186,13 +200,21 @@
 /// which is currently +infinity.
 class MaxIntValue extends Value {
   const MaxIntValue() : super(null);
+  @override
   Value operator +(Value other) => this;
+  @override
   Value operator -(Value other) => this;
+  @override
   Value operator -() => const MinIntValue();
+  @override
   Value min(Value other) => other;
+  @override
   Value max(Value other) => this;
+  @override
   String toString() => 'Max';
+  @override
   bool get isNegative => false;
+  @override
   bool get isPositive => true;
 }
 
@@ -200,13 +222,21 @@
 /// which is currently -infinity.
 class MinIntValue extends Value {
   const MinIntValue() : super(null);
+  @override
   Value operator +(Value other) => this;
+  @override
   Value operator -(Value other) => this;
+  @override
   Value operator -() => const MaxIntValue();
+  @override
   Value min(Value other) => this;
+  @override
   Value max(Value other) => other;
+  @override
   String toString() => 'Min';
+  @override
   bool get isNegative => true;
+  @override
   bool get isPositive => false;
 }
 
@@ -214,13 +244,21 @@
 /// operation that could not be done because of too much complexity.
 class UnknownValue extends Value {
   const UnknownValue() : super(null);
+  @override
   Value operator +(Value other) => const UnknownValue();
+  @override
   Value operator -(Value other) => const UnknownValue();
+  @override
   Value operator -() => const UnknownValue();
+  @override
   Value min(Value other) => const UnknownValue();
+  @override
   Value max(Value other) => const UnknownValue();
+  @override
   bool get isNegative => false;
+  @override
   bool get isPositive => false;
+  @override
   String toString() => 'Unknown';
 }
 
@@ -229,13 +267,16 @@
   final HInstruction instruction;
   InstructionValue(this.instruction, info) : super(info);
 
+  @override
   bool operator ==(other) {
     if (other is! InstructionValue) return false;
     return this.instruction == other.instruction;
   }
 
+  @override
   int get hashCode => throw new UnsupportedError('InstructionValue.hashCode');
 
+  @override
   Value operator +(Value other) {
     if (other.isZero) return this;
     if (other is IntValue) {
@@ -250,6 +291,7 @@
     return other + this;
   }
 
+  @override
   Value operator -(Value other) {
     if (other.isZero) return this;
     if (this == other) return info.intZero;
@@ -265,19 +307,24 @@
     return -other + this;
   }
 
+  @override
   Value operator -() {
     return info.newNegateValue(this);
   }
 
+  @override
   bool get isNegative => false;
+  @override
   bool get isPositive => false;
 
+  @override
   String toString() => 'Instruction: $instruction';
 }
 
 /// Special value for instructions whose type is a positive integer.
 class PositiveValue extends InstructionValue {
   PositiveValue(HInstruction instruction, info) : super(instruction, info);
+  @override
   bool get isPositive => true;
 }
 
@@ -292,16 +339,20 @@
 class AddValue extends BinaryOperationValue {
   AddValue(left, right, info) : super(left, right, info);
 
+  @override
   bool operator ==(other) {
     if (other is! AddValue) return false;
     return (left == other.left && right == other.right) ||
         (left == other.right && right == other.left);
   }
 
+  @override
   int get hashCode => throw new UnsupportedError('AddValue.hashCode');
 
+  @override
   Value operator -() => -left - right;
 
+  @override
   Value operator +(Value other) {
     if (other.isZero) return this;
     Value value = left + other;
@@ -317,6 +368,7 @@
     return const UnknownValue();
   }
 
+  @override
   Value operator -(Value other) {
     if (other.isZero) return this;
     Value value = left - other;
@@ -332,23 +384,30 @@
     return const UnknownValue();
   }
 
+  @override
   bool get isNegative => left.isNegative && right.isNegative;
+  @override
   bool get isPositive => left.isPositive && right.isPositive;
+  @override
   String toString() => '$left + $right';
 }
 
 class SubtractValue extends BinaryOperationValue {
   SubtractValue(left, right, info) : super(left, right, info);
 
+  @override
   bool operator ==(other) {
     if (other is! SubtractValue) return false;
     return left == other.left && right == other.right;
   }
 
+  @override
   int get hashCode => throw new UnsupportedError('SubtractValue.hashCode');
 
+  @override
   Value operator -() => right - left;
 
+  @override
   Value operator +(Value other) {
     if (other.isZero) return this;
     Value value = left + other;
@@ -364,6 +423,7 @@
     return const UnknownValue();
   }
 
+  @override
   Value operator -(Value other) {
     if (other.isZero) return this;
     Value value = left - other;
@@ -379,8 +439,11 @@
     return const UnknownValue();
   }
 
+  @override
   bool get isNegative => left.isNegative && right.isPositive;
+  @override
   bool get isPositive => left.isPositive && right.isNegative;
+  @override
   String toString() => '$left - $right';
 }
 
@@ -388,13 +451,16 @@
   final Value value;
   NegateValue(this.value, info) : super(info);
 
+  @override
   bool operator ==(other) {
     if (other is! NegateValue) return false;
     return value == other.value;
   }
 
+  @override
   int get hashCode => throw new UnsupportedError('Negate.hashCode');
 
+  @override
   Value operator +(other) {
     if (other.isZero) return this;
     if (other == value) return info.intZero;
@@ -411,8 +477,10 @@
     return other - value;
   }
 
+  @override
   Value operator &(Value other) => const UnknownValue();
 
+  @override
   Value operator -(other) {
     if (other.isZero) return this;
     if (other is IntValue) {
@@ -428,10 +496,14 @@
     return -other - value;
   }
 
+  @override
   Value operator -() => value;
 
+  @override
   bool get isNegative => value.isPositive;
+  @override
   bool get isPositive => value.isNegative;
+  @override
   String toString() => '-$value';
 }
 
@@ -523,11 +595,13 @@
     }
   }
 
+  @override
   bool operator ==(other) {
     if (other is! Range) return false;
     return other.lower == lower && other.upper == upper;
   }
 
+  @override
   int get hashCode => throw new UnsupportedError('Range.hashCode');
 
   bool operator <(Range other) {
@@ -550,6 +624,7 @@
   bool get isPositive => lower.isPositive;
   bool get isSingleValue => lower == upper;
 
+  @override
   String toString() => '[$lower, $upper]';
 }
 
@@ -558,6 +633,7 @@
 /// removes unnecessary bounds checks, and comparisons that are proven
 /// to be true or false.
 class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase {
+  @override
   String get name => 'SSA value range builder';
 
   /// List of [HRangeConversion] instructions created by the phase. We
@@ -578,6 +654,7 @@
       : info = new ValueRangeInfo(),
         this.closedWorld = closedWorld;
 
+  @override
   void visitGraph(HGraph graph) {
     this.graph = graph;
     visitDominatorTree(graph);
@@ -596,6 +673,7 @@
     });
   }
 
+  @override
   void visitBasicBlock(HBasicBlock block) {
     void visit(HInstruction instruction) {
       Range range = instruction.accept(this);
@@ -611,6 +689,7 @@
     block.forEachInstruction(visit);
   }
 
+  @override
   Range visitInstruction(HInstruction instruction) {
     if (instruction
         .isPositiveInteger(closedWorld.abstractValueDomain)
@@ -627,6 +706,7 @@
     }
   }
 
+  @override
   Range visitPhi(HPhi phi) {
     if (phi.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse)
       return info.newUnboundRange();
@@ -652,6 +732,7 @@
     return range;
   }
 
+  @override
   Range visitConstant(HConstant hConstant) {
     if (hConstant
         .isInteger(closedWorld.abstractValueDomain)
@@ -679,10 +760,12 @@
     return info.newNormalizedRange(value, value);
   }
 
+  @override
   Range visitFieldGet(HFieldGet fieldGet) {
     return visitInstruction(fieldGet);
   }
 
+  @override
   Range visitGetLength(HGetLength node) {
     PositiveValue value = info.newPositiveValue(node);
     // We know this range is above zero. To simplify the analysis, we
@@ -692,6 +775,7 @@
     return info.newNormalizedRange(info.intZero, value);
   }
 
+  @override
   Range visitBoundsCheck(HBoundsCheck check) {
     // Save the next instruction, in case the check gets removed.
     HInstruction next = check.next;
@@ -761,6 +845,7 @@
     return newIndexRange;
   }
 
+  @override
   Range visitRelational(HRelational relational) {
     HInstruction right = relational.right;
     HInstruction left = relational.left;
@@ -828,6 +913,7 @@
     return info.newUnboundRange();
   }
 
+  @override
   Range visitRemainder(HRemainder instruction) {
     HInstruction left = instruction.inputs[0];
     HInstruction right = instruction.inputs[1];
@@ -862,6 +948,7 @@
     return info.newUnboundRange();
   }
 
+  @override
   Range visitInvokeDynamicMethod(HInvokeDynamicMethod invoke) {
     if ((invoke.inputs.length == 3) && (invoke.selector.name == "%"))
       return handleInvokeModulo(invoke);
@@ -879,14 +966,17 @@
         .apply(ranges[instruction.left], ranges[instruction.right]);
   }
 
+  @override
   Range visitAdd(HAdd add) {
     return handleBinaryOperation(add);
   }
 
+  @override
   Range visitSubtract(HSubtract sub) {
     return handleBinaryOperation(sub);
   }
 
+  @override
   Range visitBitAnd(HBitAnd node) {
     if (node.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse) {
       return info.newUnboundRange();
@@ -918,6 +1008,7 @@
     return info.newUnboundRange();
   }
 
+  @override
   Range visitCheck(HCheck instruction) {
     if (ranges[instruction.checkedInput] == null) {
       return visitInstruction(instruction);
@@ -986,6 +1077,7 @@
     return range.intersection(leftRange);
   }
 
+  @override
   Range visitConditionalBranch(HConditionalBranch branch) {
     dynamic condition = branch.condition;
     // TODO(ngeoffray): Handle complex conditions.
@@ -1051,6 +1143,7 @@
     return info.newUnboundRange();
   }
 
+  @override
   Range visitRangeConversion(HRangeConversion conversion) {
     return ranges[conversion];
   }
@@ -1095,6 +1188,7 @@
     return instruction.accept(this);
   }
 
+  @override
   Range visitPhi(HPhi phi) {
     // If the update of a loop phi involves another loop phi, we give
     // up.
@@ -1112,14 +1206,17 @@
     return phiRange;
   }
 
+  @override
   Range visitCheck(HCheck instruction) {
     return visit(instruction.checkedInput);
   }
 
+  @override
   Range visitAdd(HAdd operation) {
     return handleBinaryOperation(operation);
   }
 
+  @override
   Range visitSubtract(HSubtract operation) {
     return handleBinaryOperation(operation);
   }
diff --git a/pkg/compiler/lib/src/ssa/value_set.dart b/pkg/compiler/lib/src/ssa/value_set.dart
index 89dbeca..b24a560 100644
--- a/pkg/compiler/lib/src/ssa/value_set.dart
+++ b/pkg/compiler/lib/src/ssa/value_set.dart
@@ -152,6 +152,7 @@
 class ValueSetNode {
   final HInstruction value;
   final int hash;
+  @override
   int get hashCode => hash;
   ValueSetNode next;
   ValueSetNode(this.value, this.hash, this.next);
diff --git a/pkg/compiler/lib/src/ssa/variable_allocator.dart b/pkg/compiler/lib/src/ssa/variable_allocator.dart
index aca7c88..a9f6e39 100644
--- a/pkg/compiler/lib/src/ssa/variable_allocator.dart
+++ b/pkg/compiler/lib/src/ssa/variable_allocator.dart
@@ -16,6 +16,7 @@
     assert(start <= end);
   }
 
+  @override
   String toString() => '[$start $end[';
 }
 
@@ -56,6 +57,7 @@
     return false;
   }
 
+  @override
   String toString() {
     List<String> res = new List<String>();
     for (final interval in ranges) res.add(interval.toString());
@@ -148,6 +150,7 @@
   bool get isEmpty => liveInstructions.isEmpty && loopMarkers.isEmpty;
   bool contains(HInstruction instruction) =>
       liveInstructions.containsKey(instruction);
+  @override
   String toString() => liveInstructions.toString();
 }
 
@@ -174,6 +177,7 @@
       : liveInstructions = new Map<HBasicBlock, LiveEnvironment>(),
         liveIntervals = new Map<HInstruction, LiveInterval>();
 
+  @override
   void visitGraph(HGraph graph) {
     visitPostDominatorTree(graph);
     if (!liveInstructions[graph.entry].isEmpty) {
@@ -251,6 +255,7 @@
     }
   }
 
+  @override
   void visitBasicBlock(HBasicBlock block) {
     LiveEnvironment environment =
         new LiveEnvironment(liveIntervals, instructionId);
@@ -356,6 +361,7 @@
 
   Copy(this.source, this.destination);
 
+  @override
   String toString() => '$destination <- $source';
 }
 
@@ -381,6 +387,7 @@
     assignments.add(new Copy<HInstruction>(source, destination));
   }
 
+  @override
   String toString() => 'Copies: $copies, assignments: $assignments';
 
   bool get isEmpty => copies.isEmpty && assignments.isEmpty;
@@ -574,10 +581,12 @@
       this.generateAtUseSite)
       : this.names = new VariableNames();
 
+  @override
   void visitGraph(HGraph graph) {
     visitDominatorTree(graph);
   }
 
+  @override
   void visitBasicBlock(HBasicBlock block) {
     VariableNamer variableNamer =
         new VariableNamer(liveInstructions[block], names, _namer);
diff --git a/pkg/compiler/lib/src/tracer.dart b/pkg/compiler/lib/src/tracer.dart
index f4e7870..2c687bf 100644
--- a/pkg/compiler/lib/src/tracer.dart
+++ b/pkg/compiler/lib/src/tracer.dart
@@ -26,6 +26,7 @@
   final JClosedWorld closedWorld;
   final Namer namer;
   bool traceActive = false;
+  @override
   final api.OutputSink output;
   final RegExp traceFilter;
 
diff --git a/pkg/compiler/lib/src/universe/call_structure.dart b/pkg/compiler/lib/src/universe/call_structure.dart
index d40a26e..8c148c8 100644
--- a/pkg/compiler/lib/src/universe/call_structure.dart
+++ b/pkg/compiler/lib/src/universe/call_structure.dart
@@ -109,6 +109,7 @@
     return sb.toString();
   }
 
+  @override
   String toString() => 'CallStructure(${structureToString()})';
 
   Selector get callSelector => new Selector.call(Names.call, this);
@@ -122,6 +123,7 @@
   }
 
   // TODO(johnniwinther): Cache hash code?
+  @override
   int get hashCode {
     return Hashing.listHash(
         namedArguments,
@@ -129,6 +131,7 @@
             Hashing.objectHash(typeArgumentCount, namedArguments.length)));
   }
 
+  @override
   bool operator ==(other) {
     if (other is! CallStructure) return false;
     return match(other);
@@ -184,6 +187,7 @@
 
 ///
 class NamedCallStructure extends CallStructure {
+  @override
   final List<String> namedArguments;
   final List<String> _orderedNamedArguments = <String>[];
 
diff --git a/pkg/compiler/lib/src/universe/class_hierarchy.dart b/pkg/compiler/lib/src/universe/class_hierarchy.dart
index e5707ad..940d180 100644
--- a/pkg/compiler/lib/src/universe/class_hierarchy.dart
+++ b/pkg/compiler/lib/src/universe/class_hierarchy.dart
@@ -184,6 +184,7 @@
         commonElements, classHierarchyNodes, classSets);
   }
 
+  @override
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
     sink.writeInt(_classSets.length);
@@ -231,6 +232,7 @@
 
   /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an
   /// instance of [y].
+  @override
   bool isSubtypeOf(ClassEntity x, ClassEntity y) {
     ClassSet classSet = _classSets[y];
     assert(
@@ -246,12 +248,14 @@
   }
 
   /// Return `true` if [x] is a (non-strict) subclass of [y].
+  @override
   bool isSubclassOf(ClassEntity x, ClassEntity y) {
     return _classHierarchyNodes[y].hasSubclass(_classHierarchyNodes[x]);
   }
 
   /// Returns an iterable over the directly instantiated classes that extend
   /// [cls] possibly including [cls] itself, if it is live.
+  @override
   Iterable<ClassEntity> subclassesOf(ClassEntity cls) {
     ClassHierarchyNode hierarchy = _classHierarchyNodes[cls];
     if (hierarchy == null) return const <ClassEntity>[];
@@ -261,6 +265,7 @@
 
   /// Returns an iterable over the directly instantiated classes that extend
   /// [cls] _not_ including [cls] itself.
+  @override
   Iterable<ClassEntity> strictSubclassesOf(ClassEntity cls) {
     ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
     if (subclasses == null) return const <ClassEntity>[];
@@ -271,6 +276,7 @@
 
   /// Returns the number of live classes that extend [cls] _not_
   /// including [cls] itself.
+  @override
   int strictSubclassCount(ClassEntity cls) {
     ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
     if (subclasses == null) return 0;
@@ -279,6 +285,7 @@
 
   /// Applies [f] to each live class that extend [cls] _not_ including [cls]
   /// itself.
+  @override
   void forEachStrictSubclassOf(
       ClassEntity cls, IterationStep f(ClassEntity cls)) {
     ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
@@ -289,6 +296,7 @@
 
   /// Returns `true` if [predicate] applies to any live class that extend [cls]
   /// _not_ including [cls] itself.
+  @override
   bool anyStrictSubclassOf(ClassEntity cls, bool predicate(ClassEntity cls)) {
     ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
     if (subclasses == null) return false;
@@ -299,6 +307,7 @@
 
   /// Returns an iterable over the directly instantiated that implement [cls]
   /// possibly including [cls] itself, if it is live.
+  @override
   Iterable<ClassEntity> subtypesOf(ClassEntity cls) {
     ClassSet classSet = _classSets[cls];
     if (classSet == null) {
@@ -311,6 +320,7 @@
 
   /// Returns an iterable over the directly instantiated that implement [cls]
   /// _not_ including [cls].
+  @override
   Iterable<ClassEntity> strictSubtypesOf(ClassEntity cls) {
     ClassSet classSet = _classSets[cls];
     if (classSet == null) {
@@ -323,6 +333,7 @@
 
   /// Returns the number of live classes that implement [cls] _not_
   /// including [cls] itself.
+  @override
   int strictSubtypeCount(ClassEntity cls) {
     ClassSet classSet = _classSets[cls];
     if (classSet == null) return 0;
@@ -331,6 +342,7 @@
 
   /// Applies [f] to each live class that implements [cls] _not_ including [cls]
   /// itself.
+  @override
   void forEachStrictSubtypeOf(
       ClassEntity cls, IterationStep f(ClassEntity cls)) {
     ClassSet classSet = _classSets[cls];
@@ -341,6 +353,7 @@
 
   /// Returns `true` if [predicate] applies to any live class that extend [cls]
   /// _not_ including [cls] itself.
+  @override
   bool anyStrictSubtypeOf(ClassEntity cls, bool predicate(ClassEntity cls)) {
     ClassSet classSet = _classSets[cls];
     if (classSet == null) return false;
@@ -350,6 +363,7 @@
   }
 
   /// Returns `true` if [a] and [b] have any known common subtypes.
+  @override
   bool haveAnyCommonSubtypes(ClassEntity a, ClassEntity b) {
     ClassSet classSetA = _classSets[a];
     ClassSet classSetB = _classSets[b];
@@ -366,6 +380,7 @@
 
   /// Returns `true` if any directly instantiated class other than [cls] extends
   /// [cls].
+  @override
   bool hasAnyStrictSubclass(ClassEntity cls) {
     ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
     if (subclasses == null) return false;
@@ -374,12 +389,14 @@
 
   /// Returns `true` if any directly instantiated class other than [cls]
   /// implements [cls].
+  @override
   bool hasAnyStrictSubtype(ClassEntity cls) {
     return strictSubtypeCount(cls) > 0;
   }
 
   /// Returns `true` if all directly instantiated classes that implement [cls]
   /// extend it.
+  @override
   bool hasOnlySubclasses(ClassEntity cls) {
     // TODO(johnniwinther): move this to ClassSet?
     if (cls == _commonElements.objectClass) return true;
@@ -391,6 +408,7 @@
     return classSet.hasOnlyInstantiatedSubclasses;
   }
 
+  @override
   SubclassResult commonSubclasses(ClassEntity cls1, ClassQuery query1,
       ClassEntity cls2, ClassQuery query2) {
     if (query1 == ClassQuery.EXACT && query2 == ClassQuery.EXACT) {
@@ -541,6 +559,7 @@
   ///
   /// This method is only provided for testing. For queries on classes, use the
   /// methods defined in [JClosedWorld].
+  @override
   ClassHierarchyNode getClassHierarchyNode(ClassEntity cls) {
     return _classHierarchyNodes[cls];
   }
@@ -550,6 +569,7 @@
   ///
   /// This method is only provided for testing. For queries on classes, use the
   /// methods defined in [JClosedWorld].
+  @override
   ClassSet getClassSet(ClassEntity cls) {
     return _classSets[cls];
   }
@@ -1004,5 +1024,6 @@
   static const SubclassResult SUBTYPE2 =
       const SubclassResult.internal(SubclassResultKind.SUBTYPE2);
 
+  @override
   String toString() => 'SubclassResult($kind,classes=$classes)';
 }
diff --git a/pkg/compiler/lib/src/universe/class_set.dart b/pkg/compiler/lib/src/universe/class_set.dart
index fa29bf7..a2eaee0 100644
--- a/pkg/compiler/lib/src/universe/class_set.dart
+++ b/pkg/compiler/lib/src/universe/class_set.dart
@@ -448,6 +448,7 @@
     return sb.toString();
   }
 
+  @override
   String toString() => cls.toString();
 }
 
@@ -841,6 +842,7 @@
     return null;
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('[\n');
@@ -1040,6 +1042,7 @@
 
 /// Singleton map implemented as a field on the key.
 class ClassHierarchyNodesMap extends MapBase<ClassEntity, ClassHierarchyNode> {
+  @override
   ClassHierarchyNode operator [](Object cls) {
     // TODO(sra): Change the key type to `covariant ClassHierarchyNodesMapKey`.
     if (cls is ClassHierarchyNodesMapKey) {
@@ -1048,6 +1051,7 @@
     throw new UnimplementedError('ClassHierarchyNodesMap for $cls');
   }
 
+  @override
   operator []=(Object cls, ClassHierarchyNode node) {
     // TODO(sra): Change the key type to `covariant ClassHierarchyNodesMapKey`.
     if (cls is ClassHierarchyNodesMapKey) {
@@ -1057,19 +1061,23 @@
     throw new UnimplementedError('ClassHierarchyNodesMap for $cls');
   }
 
+  @override
   ClassHierarchyNode putIfAbsent(
       ClassEntity cls, ClassHierarchyNode ifAbsent()) {
     return this[cls] ??= ifAbsent();
   }
 
+  @override
   Iterable<ClassEntity> get keys {
     throw new UnimplementedError('ClassHierarchyNodesMap.keys');
   }
 
+  @override
   ClassHierarchyNode remove(Object key) {
     throw new UnimplementedError('ClassHierarchyNodesMap.remove');
   }
 
+  @override
   void clear() {
     throw new UnimplementedError('ClassHierarchyNodesMap.clear');
   }
diff --git a/pkg/compiler/lib/src/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
index 4bf8ac1..4ece571 100644
--- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
@@ -90,6 +90,7 @@
   Iterable<FieldEntity> get allReferencedStaticFields;
 
   /// Set of methods in instantiated classes that are potentially closurized.
+  @override
   Iterable<FunctionEntity> get closurizedMembers;
 
   /// Register [constant] as needed for emission.
@@ -136,13 +137,16 @@
   /// The set of all referenced static fields.
   ///
   /// Invariant: Elements are declaration elements.
+  @override
   final Set<FieldEntity> allReferencedStaticFields = new Set<FieldEntity>();
 
   /// Documentation wanted -- johnniwinther
   ///
   /// Invariant: Elements are declaration elements.
+  @override
   final Set<FunctionEntity> staticFunctionsNeedingGetter =
       new Set<FunctionEntity>();
+  @override
   final Set<FunctionEntity> methodsNeedingSuperGetter =
       new Set<FunctionEntity>();
   final Map<String, Map<Selector, SelectorConstraints>> _invokedNames =
@@ -181,6 +185,7 @@
   final Map<String, Set<MemberUsage>> _instanceFunctionsByName =
       <String, Set<MemberUsage>>{};
 
+  @override
   final Set<DartType> isChecks = new Set<DartType>();
 
   final SelectorConstraintsStrategy selectorConstraintsStrategy;
@@ -201,6 +206,7 @@
 
   GlobalLocalsMap get _globalLocalsMap => _world.globalLocalsMap;
 
+  @override
   Iterable<ClassEntity> get instantiatedClasses => _processedClasses.keys
       .where((cls) => _processedClasses[cls].isInstantiated);
 
@@ -208,6 +214,7 @@
   /// constructor that has been called directly and not only through a
   /// super-call.
   // TODO(johnniwinther): Improve semantic precision.
+  @override
   Iterable<ClassEntity> get directlyInstantiatedClasses {
     return _directlyInstantiatedClasses;
   }
@@ -217,6 +224,7 @@
   ///
   /// See [directlyInstantiatedClasses].
   // TODO(johnniwinther): Improve semantic precision.
+  @override
   Iterable<InterfaceType> get instantiatedTypes => _instantiatedTypes;
 
   /// Register [type] as (directly) instantiated.
@@ -270,11 +278,13 @@
     return _hasMatchingSelector(_invokedNames[member.name], member, _world);
   }
 
+  @override
   bool hasInvokedGetter(MemberEntity member) {
     return _hasMatchingSelector(_invokedGetters[member.name], member, _world) ||
         member.isFunction && methodsNeedingSuperGetter.contains(member);
   }
 
+  @override
   bool hasInvokedSetter(MemberEntity member) {
     return _hasMatchingSelector(_invokedSetters[member.name], member, _world);
   }
@@ -347,28 +357,34 @@
     return new UnmodifiableMapView(map);
   }
 
+  @override
   Map<Selector, SelectorConstraints> invocationsByName(String name) {
     return _asUnmodifiable(_invokedNames[name]);
   }
 
+  @override
   Map<Selector, SelectorConstraints> getterInvocationsByName(String name) {
     return _asUnmodifiable(_invokedGetters[name]);
   }
 
+  @override
   Map<Selector, SelectorConstraints> setterInvocationsByName(String name) {
     return _asUnmodifiable(_invokedSetters[name]);
   }
 
+  @override
   void forEachInvokedName(
       f(String name, Map<Selector, SelectorConstraints> selectors)) {
     _invokedNames.forEach(f);
   }
 
+  @override
   void forEachInvokedGetter(
       f(String name, Map<Selector, SelectorConstraints> selectors)) {
     _invokedGetters.forEach(f);
   }
 
+  @override
   void forEachInvokedSetter(
       f(String name, Map<Selector, SelectorConstraints> selectors)) {
     _invokedSetters.forEach(f);
@@ -723,11 +739,13 @@
     _constTypeLiterals.add(type);
   }
 
+  @override
   Iterable<DartType> get constTypeLiterals => _constTypeLiterals;
 
   void registerTypeArgument(DartType type) {
     _liveTypeArguments.add(type);
   }
 
+  @override
   Iterable<DartType> get liveTypeArguments => _liveTypeArguments;
 }
diff --git a/pkg/compiler/lib/src/universe/feature.dart b/pkg/compiler/lib/src/universe/feature.dart
index f0c29bc..484ce10 100644
--- a/pkg/compiler/lib/src/universe/feature.dart
+++ b/pkg/compiler/lib/src/universe/feature.dart
@@ -103,12 +103,14 @@
 
   MapLiteralUse(this.type, {this.isConstant: false, this.isEmpty: false});
 
+  @override
   int get hashCode {
     return type.hashCode * 13 +
         isConstant.hashCode * 17 +
         isEmpty.hashCode * 19;
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! MapLiteralUse) return false;
@@ -117,6 +119,7 @@
         isEmpty == other.isEmpty;
   }
 
+  @override
   String toString() {
     return 'MapLiteralUse($type,isConstant:$isConstant,isEmpty:$isEmpty)';
   }
@@ -130,9 +133,11 @@
 
   SetLiteralUse(this.type, {this.isConstant: false, this.isEmpty: false});
 
+  @override
   int get hashCode =>
       type.hashCode * 13 + isConstant.hashCode * 17 + isEmpty.hashCode * 19;
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! SetLiteralUse) return false;
@@ -141,6 +146,7 @@
         isEmpty == other.isEmpty;
   }
 
+  @override
   String toString() =>
       'SetLiteralUse($type,isConstant:$isConstant,isEmpty:$isEmpty)';
 }
@@ -153,12 +159,14 @@
 
   ListLiteralUse(this.type, {this.isConstant: false, this.isEmpty: false});
 
+  @override
   int get hashCode {
     return type.hashCode * 13 +
         isConstant.hashCode * 17 +
         isEmpty.hashCode * 19;
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! ListLiteralUse) return false;
@@ -167,6 +175,7 @@
         isEmpty == other.isEmpty;
   }
 
+  @override
   String toString() {
     return 'ListLiteralUse($type,isConstant:$isConstant,isEmpty:$isEmpty)';
   }
@@ -185,11 +194,13 @@
 
   RuntimeTypeUse(this.kind, this.receiverType, this.argumentType);
 
+  @override
   int get hashCode =>
       kind.hashCode * 13 +
       receiverType.hashCode * 17 +
       argumentType.hashCode * 19;
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! RuntimeTypeUse) return false;
@@ -220,6 +231,7 @@
     return sb.toString();
   }
 
+  @override
   String toString() => 'RuntimeTypeUse(kind=$kind,receiver=$receiverType'
       ',argument=$argumentType)';
 }
@@ -238,9 +250,11 @@
   /// Short textual representation use for testing.
   String get shortText => '<${typeArguments.join(',')}>';
 
+  @override
   int get hashCode =>
       Hashing.listHash(typeArguments, Hashing.objectHash(functionType));
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! GenericInstantiation) return false;
@@ -248,6 +262,7 @@
         equalElements(typeArguments, other.typeArguments);
   }
 
+  @override
   String toString() {
     return 'GenericInstantiation(functionType:$functionType,'
         'typeArguments:$typeArguments)';
diff --git a/pkg/compiler/lib/src/universe/function_set.dart b/pkg/compiler/lib/src/universe/function_set.dart
index e8edd4b..d12781c 100644
--- a/pkg/compiler/lib/src/universe/function_set.dart
+++ b/pkg/compiler/lib/src/universe/function_set.dart
@@ -96,6 +96,7 @@
 class SelectorMask {
   final Selector selector;
   final AbstractValue receiver;
+  @override
   final int hashCode;
 
   SelectorMask(this.selector, this.receiver)
@@ -119,11 +120,13 @@
         .isPotentiallyTrue;
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     return selector == other.selector && receiver == other.receiver;
   }
 
+  @override
   String toString() => '($selector,$receiver)';
 }
 
@@ -238,6 +241,7 @@
     return result;
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('FunctionSetNode(');
@@ -273,6 +277,7 @@
   @override
   Iterable<MemberEntity> get functions => const <MemberEntity>[];
 
+  @override
   String toString() => '<empty>';
 }
 
@@ -289,5 +294,6 @@
     return _receiver ??= domain.computeReceiver(functions);
   }
 
+  @override
   String toString() => '$_receiver:$functions';
 }
diff --git a/pkg/compiler/lib/src/universe/member_usage.dart b/pkg/compiler/lib/src/universe/member_usage.dart
index b0898df..50fc2dc 100644
--- a/pkg/compiler/lib/src/universe/member_usage.dart
+++ b/pkg/compiler/lib/src/universe/member_usage.dart
@@ -140,20 +140,26 @@
   @override
   EnumSet<MemberUse> get _originalUse => MemberUses.NORMAL_ONLY;
 
+  @override
   int get hashCode => entity.hashCode;
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! MemberUsage) return false;
     return entity == other.entity;
   }
 
+  @override
   String toString() => '$entity:${appliedUse.iterable(MemberUse.values)}';
 }
 
 class FieldUsage extends MemberUsage {
+  @override
   bool hasInit = false;
+  @override
   bool hasRead = false;
+  @override
   bool hasWrite = false;
 
   FieldUsage(FieldEntity field, {bool isNative: false})
@@ -221,12 +227,15 @@
     return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
   }
 
+  @override
   String toString() => 'FieldUsage($entity,hasInit=$hasInit,hasRead=$hasRead,'
       'hasWrite=$hasWrite,pendingUse=${_pendingUse.iterable(MemberUse.values)}';
 }
 
 class FinalFieldUsage extends MemberUsage {
+  @override
   bool hasInit = false;
+  @override
   bool hasRead = false;
 
   FinalFieldUsage(FieldEntity field, {bool isNative: false})
@@ -280,12 +289,15 @@
     return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
   }
 
+  @override
   String toString() => 'FinalFieldUsage($entity,hasInit=$hasInit,'
       'hasRead=$hasRead,pendingUse=${_pendingUse.iterable(MemberUse.values)}';
 }
 
 class FunctionUsage extends MemberUsage {
+  @override
   bool hasInvoke = false;
+  @override
   bool hasRead = false;
 
   FunctionUsage(FunctionEntity function) : super.internal(function) {
@@ -297,11 +309,14 @@
     }
   }
 
+  @override
   FunctionEntity get entity => super.entity;
 
+  @override
   EnumSet<MemberUse> get _originalUse =>
       entity.isInstanceMember ? MemberUses.ALL_INSTANCE : MemberUses.ALL_STATIC;
 
+  @override
   bool get hasPendingClosurizationUse => entity.isInstanceMember
       ? _pendingUse.contains(MemberUse.CLOSURIZE_INSTANCE)
       : _pendingUse.contains(MemberUse.CLOSURIZE_STATIC);
@@ -349,6 +364,7 @@
 }
 
 class ParameterTrackingFunctionUsage extends MemberUsage {
+  @override
   bool hasRead = false;
 
   final ParameterUsage _parameterUsage;
@@ -364,12 +380,15 @@
     }
   }
 
+  @override
   bool get hasInvoke => _parameterUsage.hasInvoke;
 
+  @override
   bool get hasPendingClosurizationUse => entity.isInstanceMember
       ? _pendingUse.contains(MemberUse.CLOSURIZE_INSTANCE)
       : _pendingUse.contains(MemberUse.CLOSURIZE_STATIC);
 
+  @override
   EnumSet<MemberUse> get _originalUse =>
       entity.isInstanceMember ? MemberUses.ALL_INSTANCE : MemberUses.ALL_STATIC;
 
@@ -420,6 +439,7 @@
   @override
   bool get hasPendingNormalUse => !isFullyInvoked;
 
+  @override
   bool get isFullyInvoked => _parameterUsage.isFullyUsed;
 
   @override
@@ -430,6 +450,7 @@
 }
 
 class GetterUsage extends MemberUsage {
+  @override
   bool hasRead = false;
 
   GetterUsage(FunctionEntity getter) : super.internal(getter);
@@ -454,6 +475,7 @@
 }
 
 class SetterUsage extends MemberUsage {
+  @override
   bool hasWrite = false;
 
   SetterUsage(FunctionEntity setter) : super.internal(setter);
@@ -475,12 +497,15 @@
 }
 
 class ConstructorUsage extends MemberUsage {
+  @override
   bool hasInvoke = false;
 
   ConstructorUsage(ConstructorEntity constructor) : super.internal(constructor);
 
+  @override
   ConstructorEntity get entity => super.entity;
 
+  @override
   EnumSet<MemberUse> get _originalUse => MemberUses.NORMAL_ONLY;
 
   @override
@@ -512,8 +537,10 @@
       : _parameterUsage = new ParameterUsage(constructor.parameterStructure),
         super.internal(constructor);
 
+  @override
   ConstructorEntity get entity => super.entity;
 
+  @override
   EnumSet<MemberUse> get _originalUse => MemberUses.NORMAL_ONLY;
 
   @override
@@ -548,6 +575,7 @@
   @override
   bool get hasPendingNormalUse => !isFullyInvoked;
 
+  @override
   bool get isFullyInvoked => _parameterUsage.isFullyUsed;
 
   @override
@@ -620,6 +648,7 @@
   @override
   EnumSet<ClassUse> get _originalUse => ClassUses.ALL;
 
+  @override
   String toString() => '$cls:${appliedUse.iterable(ClassUse.values)}';
 }
 
@@ -641,6 +670,7 @@
 // TODO(johnniwinther): Merge this with [MemberUsage].
 abstract class StaticMemberUsage extends AbstractUsage<MemberUse>
     implements MemberUsage {
+  @override
   final MemberEntity entity;
 
   bool hasNormalUse = false;
@@ -658,14 +688,19 @@
 
   EnumSet<MemberUse> tearOff();
 
+  @override
   EnumSet<MemberUse> init() => normalUse();
 
+  @override
   EnumSet<MemberUse> read() => tearOff();
 
+  @override
   EnumSet<MemberUse> write() => normalUse();
 
+  @override
   EnumSet<MemberUse> invoke(CallStructure callStructure) => normalUse();
 
+  @override
   EnumSet<MemberUse> fullyUse() => normalUse();
 
   @override
@@ -677,12 +712,14 @@
   @override
   EnumSet<MemberUse> get _originalUse => MemberUses.NORMAL_ONLY;
 
+  @override
   String toString() => '$entity:${appliedUse.iterable(MemberUse.values)}';
 }
 
 class GeneralStaticMemberUsage extends StaticMemberUsage {
   GeneralStaticMemberUsage(MemberEntity entity) : super.internal(entity);
 
+  @override
   EnumSet<MemberUse> tearOff() => normalUse();
 
   @override
@@ -708,15 +745,18 @@
 }
 
 class StaticFunctionUsage extends StaticMemberUsage {
+  @override
   bool hasClosurization = false;
 
   StaticFunctionUsage(FunctionEntity entity) : super.internal(entity);
 
+  @override
   FunctionEntity get entity => super.entity;
 
   @override
   bool get hasInit => true;
 
+  @override
   EnumSet<MemberUse> tearOff() {
     if (hasClosurization) {
       return MemberUses.NONE;
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index 9835da3..0111c4d 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -144,11 +144,13 @@
 
   Instance(this.type, this.kind, {this.isRedirection: false});
 
+  @override
   int get hashCode {
     return Hashing.objectHash(
         type, Hashing.objectHash(kind, Hashing.objectHash(isRedirection)));
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! Instance) return false;
@@ -157,6 +159,7 @@
         isRedirection == other.isRedirection;
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write(type);
@@ -270,6 +273,7 @@
   /// `true` if the class is abstractly instantiated.
   bool isAbstractlyInstantiated = false;
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('InstantiationInfo[');
@@ -366,11 +370,14 @@
       <String, Set<MemberUsage>>{};
 
   /// Fields set.
+  @override
   final Set<FieldEntity> fieldSetters = new Set<FieldEntity>();
+  @override
   final Set<DartType> isChecks = new Set<DartType>();
 
   /// Set of all closures in the program. Used by the mirror tracking system
   /// to find all live closure instances.
+  @override
   final Set<Local> localFunctions = new Set<Local>();
 
   /// Set of live local functions (closures) whose signatures reference type
@@ -378,12 +385,14 @@
   ///
   /// A local function is considered live if the enclosing member function is
   /// live.
+  @override
   final Set<Local> localFunctionsWithFreeTypeVariables = new Set<Local>();
 
   /// Set of live closurized members whose signatures reference type variables.
   ///
   /// A closurized method is considered live if the enclosing class has been
   /// instantiated.
+  @override
   final Set<FunctionEntity> closurizedMembersWithFreeTypeVariables =
       new Set<FunctionEntity>();
 
@@ -415,6 +424,7 @@
 
   final Set<ConstantValue> _constantValues = new Set<ConstantValue>();
 
+  @override
   final Set<Local> genericLocalFunctions = new Set<Local>();
 
   Set<MemberEntity> _processedMembers = new Set<MemberEntity>();
@@ -442,16 +452,20 @@
       this._classHierarchyBuilder,
       this._classQueries);
 
+  @override
   Iterable<ClassEntity> get processedClasses => _processedClasses.keys
       .where((cls) => _processedClasses[cls].isInstantiated);
 
+  @override
   bool isMemberProcessed(MemberEntity member) =>
       _processedMembers.contains(member);
 
+  @override
   void registerProcessedMember(MemberEntity member) {
     _processedMembers.add(member);
   }
 
+  @override
   Iterable<FunctionEntity> get genericInstanceMethods {
     List<FunctionEntity> functions = <FunctionEntity>[];
     for (MemberEntity member in processedMembers) {
@@ -464,6 +478,7 @@
     return functions;
   }
 
+  @override
   Iterable<FunctionEntity> get userNoSuchMethods {
     List<FunctionEntity> functions = <FunctionEntity>[];
     for (MemberEntity member in processedMembers) {
@@ -477,8 +492,10 @@
     return functions;
   }
 
+  @override
   Iterable<MemberEntity> get processedMembers => _processedMembers;
 
+  @override
   KClosedWorld get closedWorldForTesting {
     if (!_closed) {
       failedAt(
@@ -491,6 +508,7 @@
   /// constructor that has been called directly and not only through a
   /// super-call.
   // TODO(johnniwinther): Improve semantic precision.
+  @override
   Iterable<ClassEntity> get directlyInstantiatedClasses {
     Set<ClassEntity> classes = new Set<ClassEntity>();
     getInstantiationMap().forEach((ClassEntity cls, InstantiationInfo info) {
@@ -506,6 +524,7 @@
   ///
   /// See [directlyInstantiatedClasses].
   // TODO(johnniwinther): Improve semantic precision.
+  @override
   Iterable<InterfaceType> get instantiatedTypes {
     Set<InterfaceType> types = new Set<InterfaceType>();
     getInstantiationMap().forEach((_, InstantiationInfo info) {
@@ -520,10 +539,12 @@
     return types;
   }
 
+  @override
   bool isImplemented(ClassEntity cls) {
     return _implementedClasses.contains(cls);
   }
 
+  @override
   void registerClosurizedMember(MemberEntity element) {
     closurizedMembers.add(element);
     FunctionType type = _elementEnvironment.getFunctionType(element);
@@ -538,6 +559,7 @@
   // TODO(johnniwinther): Fully enforce the separation between exact, through
   // subclass and through subtype instantiated types/classes.
   // TODO(johnniwinther): Support unknown type arguments for generic types.
+  @override
   void registerTypeInstantiation(
       InterfaceType type, ClassUsedCallback classUsed,
       {ConstructorEntity constructor, bool isRedirection: false}) {
@@ -628,10 +650,12 @@
         member.isFunction && methodsNeedingSuperGetter.contains(member);
   }
 
+  @override
   bool hasInvokedSetter(MemberEntity member) {
     return _hasMatchingSelector(_invokedSetters[member.name], member);
   }
 
+  @override
   void registerDynamicUse(
       DynamicUse dynamicUse, MemberUsedCallback memberUsed) {
     Selector selector = dynamicUse.selector;
@@ -696,14 +720,17 @@
     return constraints.addReceiverConstraint(constraint);
   }
 
+  @override
   void registerIsCheck(covariant DartType type) {
     isChecks.add(type);
   }
 
+  @override
   bool registerConstantUse(ConstantUse use) {
     return _constantValues.add(use.value);
   }
 
+  @override
   void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed) {
     if (staticUse.kind == StaticUseKind.CLOSURE) {
       Local localFunction = staticUse.element;
@@ -828,6 +855,7 @@
 
   /// Computes usage for all members declared by [cls]. Calls [membersUsed] with
   /// the usage changes for each member.
+  @override
   void processClassMembers(ClassEntity cls, MemberUsedCallback memberUsed) {
     _elementEnvironment.forEachClassMember(cls,
         (ClassEntity cls, MemberEntity member) {
@@ -946,11 +974,13 @@
   }
 
   /// Returns an iterable over all mixin applications that mixin [cls].
+  @override
   Iterable<ClassEntity> allMixinUsesOf(ClassEntity cls) {
     Iterable<ClassEntity> uses = _classHierarchyBuilder.mixinUses[cls];
     return uses != null ? uses : const <ClassEntity>[];
   }
 
+  @override
   void registerUsedElement(MemberEntity element) {
     if (element.isInstanceMember && !element.isAbstract) {
       _liveInstanceMembers.add(element);
@@ -1011,6 +1041,7 @@
     return assignedInstanceMembers;
   }
 
+  @override
   void registerClass(ClassEntity cls) {
     _classHierarchyBuilder.registerClass(cls);
   }
diff --git a/pkg/compiler/lib/src/universe/selector.dart b/pkg/compiler/lib/src/universe/selector.dart
index f8a1dc4..2f70e16 100644
--- a/pkg/compiler/lib/src/universe/selector.dart
+++ b/pkg/compiler/lib/src/universe/selector.dart
@@ -17,6 +17,7 @@
 
 class SelectorKind {
   final String name;
+  @override
   final int hashCode;
   const SelectorKind(this.name, this.hashCode);
 
@@ -29,6 +30,7 @@
 
   int get index => hashCode;
 
+  @override
   String toString() => name;
 
   static List<SelectorKind> values = const <SelectorKind>[
@@ -50,6 +52,7 @@
   final Name memberName;
   final CallStructure callStructure;
 
+  @override
   final int hashCode;
 
   int get argumentCount => callStructure.argumentCount;
@@ -307,6 +310,7 @@
     return Hashing.mixHashCodeBits(hash, callStructure.hashCode);
   }
 
+  @override
   String toString() {
     return 'Selector($kind, $name, ${callStructure.structureToString()})';
   }
diff --git a/pkg/compiler/lib/src/universe/side_effects.dart b/pkg/compiler/lib/src/universe/side_effects.dart
index aac589a..2a63070 100644
--- a/pkg/compiler/lib/src/universe/side_effects.dart
+++ b/pkg/compiler/lib/src/universe/side_effects.dart
@@ -57,8 +57,10 @@
     sink.end(tag);
   }
 
+  @override
   bool operator ==(other) => _flags == other._flags;
 
+  @override
   int get hashCode => throw new UnsupportedError('SideEffects.hashCode');
 
   bool _getFlag(int position) {
@@ -200,6 +202,7 @@
 
   int get flags => _flags;
 
+  @override
   String toString() {
     StringBuffer buffer = new StringBuffer();
     buffer.write('SideEffects(reads');
@@ -307,6 +310,7 @@
 
   MemberEntity get member => _member;
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('SideEffectsBuilder(member=$member,');
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index ab3ffbb..6e19b31 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -85,9 +85,11 @@
 
   List<DartType> get typeArguments => const <DartType>[];
 
+  @override
   int get hashCode => Hashing.listHash(
       typeArguments, Hashing.objectsHash(selector, receiverConstraint));
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! DynamicUse) return false;
@@ -96,6 +98,7 @@
         equalElements(typeArguments, other.typeArguments);
   }
 
+  @override
   String toString() => '$selector,$receiverConstraint';
 }
 
@@ -112,6 +115,7 @@
         "${typeArguments?.length ?? 0} were passed.");
   }
 
+  @override
   List<DartType> get typeArguments => _typeArguments ?? const <DartType>[];
 }
 
@@ -120,6 +124,7 @@
 /// This is used in the codegen phase where receivers are constrained to a
 /// type mask or similar.
 class ConstrainedDynamicUse extends DynamicUse {
+  @override
   final Object receiverConstraint;
   final List<DartType> _typeArguments;
 
@@ -134,6 +139,7 @@
         "${_typeArguments?.length ?? 0} were passed.");
   }
 
+  @override
   List<DartType> get typeArguments => _typeArguments ?? const <DartType>[];
 }
 
@@ -163,6 +169,7 @@
 class StaticUse {
   final Entity element;
   final StaticUseKind kind;
+  @override
   final int hashCode;
   final InterfaceType type;
   final CallStructure callStructure;
@@ -588,6 +595,7 @@
     return new GenericStaticUse.methodInlining(element, typeArguments);
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! StaticUse) return false;
@@ -598,11 +606,13 @@
         equalElements(typeArguments, other.typeArguments);
   }
 
+  @override
   String toString() =>
       'StaticUse($element,$kind,$type,$typeArguments,$callStructure)';
 }
 
 class GenericStaticUse extends StaticUse {
+  @override
   final List<DartType> typeArguments;
 
   GenericStaticUse(Entity entity, StaticUseKind kind,
@@ -643,6 +653,7 @@
 class TypeUse {
   final DartType type;
   final TypeUseKind kind;
+  @override
   final int hashCode;
   final ImportEntity deferredImport;
 
@@ -758,12 +769,14 @@
     return new TypeUse.internal(type, TypeUseKind.TYPE_ARGUMENT);
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! TypeUse) return false;
     return type == other.type && kind == other.kind;
   }
 
+  @override
   String toString() => 'TypeUse($type,$kind)';
 }
 
@@ -778,6 +791,7 @@
 class ConstantUse {
   final ConstantValue value;
   final ConstantUseKind kind;
+  @override
   final int hashCode;
 
   ConstantUse._(this.value, this.kind)
@@ -809,11 +823,13 @@
   ConstantUse.literal(ConstantValue value)
       : this._(value, ConstantUseKind.DIRECT);
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! ConstantUse) return false;
     return value == other.value;
   }
 
+  @override
   String toString() => 'ConstantUse(${value.toStructuredText()},$kind)';
 }
diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart
index e80c180..49d452d 100644
--- a/pkg/compiler/lib/src/universe/world_builder.dart
+++ b/pkg/compiler/lib/src/universe/world_builder.dart
@@ -91,6 +91,7 @@
 class StrongModeWorldStrategy implements SelectorConstraintsStrategy {
   const StrongModeWorldStrategy();
 
+  @override
   StrongModeWorldConstraints createSelectorConstraints(
       Selector selector, Object initialConstraint) {
     return new StrongModeWorldConstraints()
@@ -151,6 +152,7 @@
     return _constraints.add(constraint);
   }
 
+  @override
   String toString() {
     if (isAll) {
       return '<all>';
@@ -190,6 +192,7 @@
 
   bool get isThis => relation == ClassRelation.thisExpression;
 
+  @override
   bool operator ==(Object other) {
     if (identical(this, other)) return true;
     return other is StrongModeConstraint &&
@@ -197,8 +200,10 @@
         relation == other.relation;
   }
 
+  @override
   int get hashCode => cls.hashCode * 13;
 
+  @override
   String toString() => 'StrongModeConstraint($cls,$relation)';
 }
 
diff --git a/pkg/compiler/lib/src/universe/world_impact.dart b/pkg/compiler/lib/src/universe/world_impact.dart
index af5eaae..cc9a92c 100644
--- a/pkg/compiler/lib/src/universe/world_impact.dart
+++ b/pkg/compiler/lib/src/universe/world_impact.dart
@@ -43,6 +43,7 @@
     constantUses.forEach(visitor.visitConstantUse);
   }
 
+  @override
   String toString() => dump(this);
 
   static String dump(WorldImpact worldImpact) {
@@ -97,42 +98,50 @@
     impact.constantUses.forEach(registerConstantUse);
   }
 
+  @override
   void registerDynamicUse(DynamicUse dynamicUse) {
     assert(dynamicUse != null);
     _dynamicUses ??= new Setlet<DynamicUse>();
     _dynamicUses.add(dynamicUse);
   }
 
+  @override
   Iterable<DynamicUse> get dynamicUses {
     return _dynamicUses != null ? _dynamicUses : const <DynamicUse>[];
   }
 
+  @override
   void registerTypeUse(TypeUse typeUse) {
     assert(typeUse != null);
     _typeUses ??= new Setlet<TypeUse>();
     _typeUses.add(typeUse);
   }
 
+  @override
   Iterable<TypeUse> get typeUses {
     return _typeUses != null ? _typeUses : const <TypeUse>[];
   }
 
+  @override
   void registerStaticUse(StaticUse staticUse) {
     assert(staticUse != null);
     _staticUses ??= new Setlet<StaticUse>();
     _staticUses.add(staticUse);
   }
 
+  @override
   Iterable<StaticUse> get staticUses {
     return _staticUses != null ? _staticUses : const <StaticUse>[];
   }
 
+  @override
   void registerConstantUse(ConstantUse constantUse) {
     assert(constantUse != null);
     _constantUses ??= new Setlet<ConstantUse>();
     _constantUses.add(constantUse);
   }
 
+  @override
   Iterable<ConstantUse> get constantUses {
     return _constantUses != null ? _constantUses : const <ConstantUse>[];
   }
@@ -221,6 +230,7 @@
     return _dynamicUses != null ? _dynamicUses : worldImpact.dynamicUses;
   }
 
+  @override
   void registerDynamicUse(DynamicUse dynamicUse) {
     if (_dynamicUses == null) {
       _dynamicUses = new Setlet<DynamicUse>();
@@ -229,6 +239,7 @@
     _dynamicUses.add(dynamicUse);
   }
 
+  @override
   void registerTypeUse(TypeUse typeUse) {
     if (_typeUses == null) {
       _typeUses = new Setlet<TypeUse>();
@@ -242,6 +253,7 @@
     return _typeUses != null ? _typeUses : worldImpact.typeUses;
   }
 
+  @override
   void registerStaticUse(StaticUse staticUse) {
     if (_staticUses == null) {
       _staticUses = new Setlet<StaticUse>();
@@ -260,6 +272,7 @@
     return _constantUses != null ? _constantUses : worldImpact.constantUses;
   }
 
+  @override
   void registerConstantUse(ConstantUse constantUse) {
     if (_constantUses == null) {
       _constantUses = new Setlet<ConstantUse>();
@@ -268,6 +281,7 @@
     _constantUses.add(constantUse);
   }
 
+  @override
   void apply(WorldImpactVisitor visitor) {
     staticUses.forEach(visitor.visitStaticUse);
     dynamicUses.forEach(visitor.visitDynamicUse);
@@ -275,6 +289,7 @@
     constantUses.forEach(visitor.visitConstantUse);
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('TransformedWorldImpact($worldImpact)');
@@ -289,6 +304,7 @@
 
   const ImpactUseCase(this.name);
 
+  @override
   String toString() => 'ImpactUseCase($name)';
 }
 
diff --git a/pkg/compiler/lib/src/util/emptyset.dart b/pkg/compiler/lib/src/util/emptyset.dart
index 796498b..6fe644c 100644
--- a/pkg/compiler/lib/src/util/emptyset.dart
+++ b/pkg/compiler/lib/src/util/emptyset.dart
@@ -9,37 +9,59 @@
 class ImmutableEmptySet<E> extends IterableBase<E> implements Set<E> {
   const ImmutableEmptySet();
 
+  @override
   Set<R> cast<R>() => new ImmutableEmptySet<R>();
+  @override
   get iterator => const _EmptySetIterator();
+  @override
   int get length => 0;
+  @override
   bool get isEmpty => true;
 
   get _immutableError => throw new UnsupportedError("EmptySet is immutable");
 
+  @override
   bool add(E element) => _immutableError;
+  @override
   void addAll(Iterable<E> elements) => _immutableError;
 
+  @override
   E lookup(Object element) => null;
+  @override
   bool remove(Object element) => false;
+  @override
   void removeAll(Iterable<Object> elements) {}
+  @override
   void removeWhere(bool test(E element)) {}
+  @override
   void retainAll(Iterable<Object> elements) {}
+  @override
   void retainWhere(bool test(E element)) {}
+  @override
   void forEach(void action(E element)) {}
+  @override
   void clear() {}
 
+  @override
   bool contains(Object element) => false;
+  @override
   bool containsAll(Iterable<Object> other) => other.isEmpty;
 
+  @override
   Set<E> union(Set<E> other) => new Set.from(other);
+  @override
   Set<E> intersection(Set<Object> other) => this;
+  @override
   Set<E> difference(Set<Object> other) => this;
+  @override
   Set<E> toSet() => new Set<E>();
 }
 
 class _EmptySetIterator implements Iterator<Null> {
   const _EmptySetIterator();
 
+  @override
   Null get current => null;
+  @override
   bool moveNext() => false;
 }
diff --git a/pkg/compiler/lib/src/util/enumset.dart b/pkg/compiler/lib/src/util/enumset.dart
index e292aa6..587b00064 100644
--- a/pkg/compiler/lib/src/util/enumset.dart
+++ b/pkg/compiler/lib/src/util/enumset.dart
@@ -98,14 +98,17 @@
   /// Returns `true` if this set is not empty.
   bool get isNotEmpty => value != 0;
 
+  @override
   int get hashCode => value.hashCode * 19;
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! EnumSet<E>) return false;
     return value == other.value;
   }
 
+  @override
   String toString() {
     if (value == 0) return '0';
     int index = value.bitLength - 1;
@@ -172,6 +175,7 @@
 
 /// Immutable implementation of [EnumSet].
 class _ConstEnumSet<E> extends EnumSet<E> {
+  @override
   final int value;
 
   const _ConstEnumSet(this.value) : super._();
@@ -188,6 +192,7 @@
     return new _ConstEnumSet(value);
   }
 
+  @override
   void set value(int mask) {
     throw new UnsupportedError('EnumSet.value=');
   }
diff --git a/pkg/compiler/lib/src/util/features.dart b/pkg/compiler/lib/src/util/features.dart
index d0547d3..bf98932 100644
--- a/pkg/compiler/lib/src/util/features.dart
+++ b/pkg/compiler/lib/src/util/features.dart
@@ -62,6 +62,7 @@
     return sb.toString();
   }
 
+  @override
   String toString() => 'Features(${getText()})';
 
   /// Creates a [Features] object by parse the [text] encoding.
diff --git a/pkg/compiler/lib/src/util/maplet.dart b/pkg/compiler/lib/src/util/maplet.dart
index b9dc6744..329853c 100644
--- a/pkg/compiler/lib/src/util/maplet.dart
+++ b/pkg/compiler/lib/src/util/maplet.dart
@@ -34,6 +34,7 @@
     });
   }
 
+  @override
   bool get isEmpty {
     if (_extra == null) {
       return _MARKER == _key;
@@ -44,6 +45,7 @@
     }
   }
 
+  @override
   int get length {
     if (_extra == null) {
       return (_MARKER == _key) ? 0 : 1;
@@ -54,6 +56,7 @@
     }
   }
 
+  @override
   bool containsKey(Object key) {
     if (_extra == null) {
       return _key == key;
@@ -70,6 +73,7 @@
     }
   }
 
+  @override
   V operator [](Object key) {
     if (_extra == null) {
       return (_key == key) ? _value : null;
@@ -86,6 +90,7 @@
     }
   }
 
+  @override
   void operator []=(K key, V value) {
     if (_extra == null) {
       if (_MARKER == _key) {
@@ -166,6 +171,7 @@
     }
   }
 
+  @override
   V remove(Object key) {
     if (_extra == null) {
       if (_key != key) return null;
@@ -193,6 +199,7 @@
     }
   }
 
+  @override
   void forEach(void action(K key, V value)) {
     if (_extra == null) {
       if (_MARKER != _key) action(_key, _value);
@@ -208,11 +215,13 @@
     }
   }
 
+  @override
   void clear() {
     _key = _MARKER;
     _value = _extra = null;
   }
 
+  @override
   Iterable<K> get keys => new _MapletKeyIterable<K>(this);
 }
 
@@ -225,6 +234,7 @@
 
   _MapletKeyIterable(this.maplet);
 
+  @override
   Iterator<K> get iterator {
     if (maplet._extra == null) {
       return new _MapletSingleIterator<K>(maplet._key);
@@ -242,8 +252,10 @@
 
   _MapletSingleIterator(this._element);
 
+  @override
   K get current => _current;
 
+  @override
   bool moveNext() {
     if (Maplet._MARKER == _element) {
       _current = null;
@@ -263,8 +275,10 @@
 
   _MapletListIterator(this._list, this._remaining);
 
+  @override
   K get current => _current;
 
+  @override
   bool moveNext() {
     while (_remaining > 0) {
       var candidate = _list[_index++];
diff --git a/pkg/compiler/lib/src/util/setlet.dart b/pkg/compiler/lib/src/util/setlet.dart
index ab1911b..e35c12b 100644
--- a/pkg/compiler/lib/src/util/setlet.dart
+++ b/pkg/compiler/lib/src/util/setlet.dart
@@ -29,7 +29,9 @@
 
   static Set<R> _newSet<R>() => new Setlet<R>();
 
+  @override
   Set<R> cast<R>() => Set.castFrom<E, R>(this, newSet: _newSet);
+  @override
   Iterator<E> get iterator {
     if (_extra == null) {
       return new _SetletSingleIterator<E>(_contents);
@@ -40,6 +42,7 @@
     }
   }
 
+  @override
   int get length {
     if (_extra == null) {
       return (_MARKER == _contents) ? 0 : 1;
@@ -50,6 +53,7 @@
     }
   }
 
+  @override
   bool get isEmpty {
     if (_extra == null) {
       return _MARKER == _contents;
@@ -60,6 +64,7 @@
     }
   }
 
+  @override
   bool contains(Object element) {
     if (_extra == null) {
       return _contents == element;
@@ -76,6 +81,7 @@
     }
   }
 
+  @override
   bool add(E element) {
     if (_extra == null) {
       if (_MARKER == _contents) {
@@ -142,10 +148,12 @@
     }
   }
 
+  @override
   void addAll(Iterable<E> elements) {
     elements.forEach((each) => add(each));
   }
 
+  @override
   E lookup(Object element) {
     if (_extra == null) {
       return _contents == element ? _contents : null;
@@ -162,6 +170,7 @@
     }
   }
 
+  @override
   bool remove(Object element) {
     if (_extra == null) {
       if (_contents == element) {
@@ -187,10 +196,12 @@
     }
   }
 
+  @override
   void removeAll(Iterable<Object> other) {
     other.forEach(remove);
   }
 
+  @override
   void removeWhere(bool test(E element)) {
     if (_extra == null) {
       if (test(_contents)) {
@@ -211,15 +222,18 @@
     }
   }
 
+  @override
   void retainWhere(bool test(E element)) {
     removeWhere((E element) => !test(element));
   }
 
+  @override
   void retainAll(Iterable<Object> elements) {
     Set set = elements is Set ? elements : elements.toSet();
     removeWhere((E element) => !set.contains(element));
   }
 
+  @override
   void forEach(void action(E element)) {
     if (_extra == null) {
       if (_MARKER != _contents) action(_contents);
@@ -235,6 +249,7 @@
     }
   }
 
+  @override
   bool containsAll(Iterable<Object> other) {
     for (E e in other) {
       if (!this.contains(e)) return false;
@@ -242,19 +257,24 @@
     return true;
   }
 
+  @override
   clear() {
     _contents = _MARKER;
     _extra = null;
   }
 
+  @override
   Set<E> union(Set<E> other) => new Set<E>.from(this)..addAll(other);
 
+  @override
   Setlet<E> intersection(Set<Object> other) =>
       new Setlet<E>.from(this.where((e) => other.contains(e)));
 
+  @override
   Setlet<E> difference(Set<Object> other) =>
       new Setlet<E>.from(this.where((e) => !other.contains(e)));
 
+  @override
   Setlet<E> toSet() {
     Setlet<E> result = new Setlet<E>();
     if (_extra == null) {
@@ -272,6 +292,7 @@
 
 class _SetletMarker {
   const _SetletMarker();
+  @override
   toString() => "-";
 }
 
@@ -280,8 +301,10 @@
   E _current;
   _SetletSingleIterator(this._element);
 
+  @override
   E get current => _current;
 
+  @override
   bool moveNext() {
     if (Setlet._MARKER == _element) {
       _current = null;
@@ -300,8 +323,10 @@
   E _current;
   _SetletListIterator(this._list, this._remaining);
 
+  @override
   E get current => _current;
 
+  @override
   bool moveNext() {
     while (_remaining > 0) {
       var candidate = _list[_index++];
diff --git a/pkg/compiler/lib/src/util/util.dart b/pkg/compiler/lib/src/util/util.dart
index 785253d..3dfee4b 100644
--- a/pkg/compiler/lib/src/util/util.dart
+++ b/pkg/compiler/lib/src/util/util.dart
@@ -234,14 +234,17 @@
 
   Pair(this.a, this.b);
 
+  @override
   int get hashCode => 13 * a.hashCode + 17 * b.hashCode;
 
+  @override
   bool operator ==(var other) {
     if (identical(this, other)) return true;
     if (other is! Pair) return false;
     return a == other.a && b == other.b;
   }
 
+  @override
   String toString() => '($a,$b)';
 }
 
diff --git a/pkg/compiler/pubspec.yaml b/pkg/compiler/pubspec.yaml
index fed2fe2..b34280b 100644
--- a/pkg/compiler/pubspec.yaml
+++ b/pkg/compiler/pubspec.yaml
@@ -3,7 +3,7 @@
 name: compiler
 publish_to: none
 environment:
-  sdk: '>=2.1.0 <3.0.0'
+  sdk: '>=2.2.0 <3.0.0'
 
 # NOTE: `pub get / pub upgrade` are generally not needed when working on this
 # package. The `.packages` file in the repository root will be used by default.
diff --git a/pkg/compiler/testing.json b/pkg/compiler/testing.json
index d5fb717..498a45c 100644
--- a/pkg/compiler/testing.json
+++ b/pkg/compiler/testing.json
@@ -14,7 +14,9 @@
     ],
 
     "exclude": [
-      "^tests/compiler/dart2js/inference/data/super_invoke\\.dart"
+      "^tests/compiler/dart2js/.*/data/.*",
+      "^tests/compiler/dart2js/.*/model_data/.*",
+      "^tests/compiler/dart2js/deferred_loading/libs/.*"
     ]
   }
 }
diff --git a/pkg/compiler/tool/status_files/log_parser.dart b/pkg/compiler/tool/status_files/log_parser.dart
deleted file mode 100644
index 43df6f4..0000000
--- a/pkg/compiler/tool/status_files/log_parser.dart
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) 2017, 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.
-
-library status_files.log_parser;
-
-import 'record.dart';
-
-final RegExp _stackRE = new RegExp('#[0-9]* ');
-final RegExp _assertionFileRE = new RegExp(r"'file:[^']*/sdk/pkg/");
-final String _assertionFileReplacement = r"'file:*/pkg/";
-
-/// Extracts test records from a test.py [log].
-List<Record> parse(String log) {
-  var records = <Record>[];
-  var suite;
-  var test;
-  var config;
-  var expected;
-  var actual;
-  var reason;
-  var fullReason; // lines before stack, usually multiline reason.
-  var stack = <String>[];
-  var paragraph = []; // collector of lines for fullReason.
-  bool reproIsNext = false;
-  for (var line in log.split('\n')) {
-    if (line.startsWith("FAILED: ")) {
-      int lastSlash = line.lastIndexOf('/');
-      // Some tests (particularly the html tests) have "group names" with spaces
-      // in them. So we find the test name by the space just before the last
-      // slash.
-      int space = line.substring(0, lastSlash).lastIndexOf(' ');
-      test = line.substring(space + 1).trim();
-      suite = '';
-      var slash = test.indexOf('/');
-      if (slash > 0) {
-        suite = test.substring(0, slash).trim();
-        test = test.substring(slash + 1).trim();
-      }
-      config = line
-          .substring("FAILED: ".length, space)
-          .replaceAll('release_ia32', '')
-          .replaceAll('release_x64', '');
-    }
-    if (line.startsWith("Expected: ")) {
-      expected = line.substring("Expected: ".length).trim();
-    }
-    if (line.startsWith("Actual: ")) {
-      actual = line.substring("Actual: ".length).trim();
-    }
-    if (line.startsWith("The compiler crashed:")) {
-      reason = line.substring("The compiler crashed:".length).trim();
-      reason = reason.replaceFirst(_assertionFileRE, _assertionFileReplacement);
-      paragraph.clear();
-    }
-
-    if (line.startsWith(_stackRE)) {
-      stack.add(line);
-      fullReason ??= paragraph.take(5).join('\n');
-      paragraph.clear();
-    } else {
-      paragraph.add(line);
-    }
-
-    if (reproIsNext) {
-      records.add(new Record(suite, test, config, expected, actual, reason,
-          line.trim(), fullReason, stack));
-      suite = test = config = expected = actual = reason = null;
-      stack = [];
-      fullReason = null;
-      paragraph.clear();
-      reproIsNext = false;
-    }
-    if (line.startsWith("--- Re-run this test:")) {
-      reproIsNext = true;
-    }
-  }
-  return records;
-}
diff --git a/pkg/compiler/tool/status_files/rank_stacks.dart b/pkg/compiler/tool/status_files/rank_stacks.dart
deleted file mode 100644
index 27cf37b..0000000
--- a/pkg/compiler/tool/status_files/rank_stacks.dart
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright (c) 2017, 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.
-
-/*
-Usage:
-
-  $ tools/test.py -m release                         \
-      -c dart2js -r d8 --dart2js-batch --report      \
-      --host-checked                                 \
-      --dart2js_options="--library-root=out/ReleaseX64/dart-sdk/ --use-kernel" \
-      language language_2 corelib corelib_2          \
-      dart2js_native dart2js_extra                   \
-      2>&1 > LOG
-
-  $ sdk/bin/dart pkg/compiler/tool/status_files/rank_stacks.dart LOG > STACKS.txt
-*/
-
-import 'dart:io';
-
-import 'package:args/args.dart';
-
-import 'log_parser.dart';
-import 'record.dart';
-
-int stackPrintLength;
-int howManyStacks;
-
-void die(String why) {
-  print(why);
-  print('Usage:\n'
-      'dart rank_stacks.dart [options] test-logs\n\n'
-      '${argParser.usage}');
-  exit(1);
-}
-
-ArgParser argParser = new ArgParser()
-  ..addOption('stacks',
-      abbr: 's',
-      defaultsTo: '0',
-      help: 'Number of highest ranking stacks to print (0 for all).')
-  ..addOption('length',
-      abbr: 'l', defaultsTo: '12', help: 'Number of stack frames printed.');
-
-int intOption(ArgResults args, String name) {
-  onError(String text) {
-    die("Value '$text' is not an integer. "
-        "Option '$name' requires an integer value.");
-  }
-
-  return int.parse(args[name], onError: onError);
-}
-
-main(args) {
-  List<String> rest;
-  try {
-    var argResults = argParser.parse(args);
-    howManyStacks = intOption(argResults, 'stacks');
-    stackPrintLength = intOption(argResults, 'length');
-    rest = argResults.rest;
-  } catch (e) {
-    die('$e');
-  }
-
-  if (rest.isEmpty) die('No input file.');
-  var records = <Record>[];
-  for (String input in rest) {
-    var uri = Uri.base.resolve(input);
-    var file = new File.fromUri(uri);
-    if (!file.existsSync()) {
-      die("File not found: '$input'.");
-    }
-    String text = file.readAsStringSync();
-    records.addAll(parse(text));
-  }
-
-  var trie = new TrieNode(null, 0);
-  for (var record in records) {
-    enter(record, 0, trie);
-  }
-
-  var leaves = trieLeaves(trie).toList();
-  leaves.sort(compareNodesByCountAndStack);
-  for (var leaf in howManyStacks == 0 ? leaves : leaves.take(howManyStacks)) {
-    print('');
-    var examples = leaf.members.map(fullReasonOf).toSet().toList();
-    examples.sort();
-    print('${leaf.length} of:');
-    for (var example in examples) {
-      var count = leaf.members.where((r) => fullReasonOf(r) == example).length;
-      var countAligned = '$count'.padLeft(6);
-      if (examples.length == 1) countAligned = '     .';
-      var indentedExample = '\t' + example.replaceAll('\n', '\n\t');
-      print('${countAligned}${indentedExample}');
-    }
-
-    for (var line in leaf.members.first.stack.take(stackPrintLength)) {
-      print('  $line');
-    }
-  }
-}
-
-String fullReasonOf(Record r) {
-  // Some records have no matched reason, so default to test status.
-  return r.fullReason ?? r.actual;
-}
-
-int compareNodesByCountAndStack(TrieNode a, TrieNode b) {
-  int r = b.length.compareTo(a.length);
-  if (r != 0) return r;
-  List<String> stackA = a.members.first.stack;
-  List<String> stackB = b.members.first.stack;
-  int lengthA = stackA.length;
-  int lengthB = stackB.length;
-  for (int i = 0; i < lengthA && i < lengthB; i++) {
-    r = stackA[i].compareTo(stackB[i]);
-    if (r != 0) return r;
-  }
-  return lengthA.compareTo(lengthB);
-}
-
-class TrieNode {
-  final int depth;
-  final String key;
-  final Map<String, TrieNode> map = <String, TrieNode>{};
-  final List<Record> members = <Record>[];
-
-  int get length => members.length;
-
-  TrieNode(this.key, this.depth);
-
-  String toString() => 'TrieNode(#$length)';
-}
-
-void enter(Record record, int depth, TrieNode root) {
-  // Cluster on printed stack.
-  if (depth >= stackPrintLength || depth >= record.stack.length) {
-    root.members.add(record);
-    return;
-  }
-  var key = record.stack[depth];
-  var node = root.map[key] ??= new TrieNode(key, depth + 1);
-  enter(record, depth + 1, node);
-}
-
-void printTrie(TrieNode node) {
-  var indent = '  ' * node.depth;
-  print('${indent} ${node.length} ${node.key}');
-  for (var key in node.map.keys) {
-    printTrie(node.map[key]);
-  }
-}
-
-trieLeaves(node) sync* {
-  if (node.members.isNotEmpty) {
-    yield node;
-  }
-  for (var v in node.map.values) {
-    yield* trieLeaves(v);
-  }
-}
diff --git a/pkg/compiler/tool/status_files/record.dart b/pkg/compiler/tool/status_files/record.dart
deleted file mode 100644
index f2a6e97..0000000
--- a/pkg/compiler/tool/status_files/record.dart
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2017, 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.
-
-/// An entry found in the test.py logs corresponding to a test failure.
-///
-/// It stores what suite, test, and configuration was the failure seen at.
-library status_files.record;
-
-class Record implements Comparable<Record> {
-  final String suite;
-  final String test;
-  final String config;
-  final String expected;
-  final String actual;
-  final String repro;
-  final String reason;
-  final String fullReason;
-  final List<String> stack;
-
-  // TODO(sigmund): extract also a failure reason if any (e.g. a stack trace or
-  // error message for crashes).
-
-  bool get isPassing => actual == 'Pass';
-
-  Record(this.suite, this.test, this.config, this.expected, this.actual,
-      this.reason, this.repro, this.fullReason, this.stack);
-
-  int compareTo(Record other) {
-    if (suite == null && other.suite != null) return -1;
-    if (suite != null && other.suite == null) return 1;
-    if (test == null && other.test != null) return -1;
-    if (test != null && other.test == null) return 1;
-
-    var suiteDiff = suite.compareTo(other.suite);
-    if (suiteDiff != 0) return suiteDiff;
-
-    if (isPassing && !other.isPassing) return -1;
-    if (!isPassing && other.isPassing) return 1;
-
-    var testDiff = test.compareTo(other.test);
-    if (testDiff != 0) return testDiff;
-    return repro.compareTo(other.repro);
-  }
-
-  bool operator ==(covariant Record other) =>
-      suite == other.suite &&
-      test == other.test &&
-      config == other.config &&
-      expected == other.expected &&
-      actual == other.actual &&
-      repro == other.repro;
-}
diff --git a/pkg/compiler/tool/status_files/update_all.dart b/pkg/compiler/tool/status_files/update_all.dart
deleted file mode 100644
index bf09b28..0000000
--- a/pkg/compiler/tool/status_files/update_all.dart
+++ /dev/null
@@ -1,124 +0,0 @@
-// 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.
-
-// Script to update the dart2js status lines for all tests running with the
-// $dart2js_with_kernel test configuration.
-
-import 'dart:io';
-import 'package:args/args.dart';
-import 'update_from_log.dart' as update_script;
-
-const List<String> strongSuites = const <String>[
-  'language_2',
-  'corelib_2',
-];
-
-const List<String> nonStrongSuites = const <String>[
-  'dart2js_native',
-  'dart2js_extra',
-];
-
-main(List<String> args) {
-  ArgParser argParser = new ArgParser(allowTrailingOptions: true)
-    ..addFlag('with-fast-startup')
-    ..addFlag('fast-startup')
-    ..addFlag('strong')
-    ..addFlag('with-checked-mode')
-    ..addFlag('checked-mode')
-    ..addFlag('checked');
-  ArgResults argResults = argParser.parse(args);
-  bool fastStartup =
-      argResults['with-fast-startup'] || argResults['fast-startup'];
-  bool strong = argResults['strong'];
-  bool checkedMode = argResults['with-checked-mode'] ||
-      argResults['checked-mode'] ||
-      argResults['checked'];
-  List<String> suites = argResults.rest;
-  if (suites.isEmpty) {
-    if (strong) {
-      suites = strongSuites;
-    } else {
-      suites = nonStrongSuites;
-    }
-    if (Platform.isWindows) {
-      // TODO(johnniwinther): Running drt seems to be broken on Windows.
-      suites = new List<String>.from(suites)..remove('html');
-    }
-  } else {
-    bool failure = false;
-    for (String suite in suites) {
-      if (strongSuites.contains(suite) && nonStrongSuites.contains(suite)) {
-        print("Unknown suite '$suite'");
-        failure = true;
-      }
-    }
-    if (failure) {
-      exit(1);
-    }
-  }
-
-  Directory tmp = Directory.systemTemp.createTempSync('update_all');
-
-  String python = Platform.isWindows ? 'python.exe' : 'python';
-
-  updateSuiteWithFlags(
-      String name, String suite, String runtime, List<String> args) {
-    if (strong) {
-      name = "$name-strong";
-      args.add('--strong');
-    }
-
-    print("  - $name tests");
-    List<String> testArgs = [
-      './tools/test.py',
-      '-m',
-      'release',
-      '-c',
-      'dart2js',
-      '-r',
-      runtime,
-      '--dart2js-batch',
-      '--dart2js-with-kernel'
-    ];
-    testArgs.addAll(args);
-    testArgs.add(suite);
-    String temp = '${tmp.path}/$suite-$name.txt';
-    ProcessResult result = Process.runSync(python, testArgs);
-    String stdout = result.stdout.toString();
-    new File(temp).writeAsStringSync(stdout);
-    print(temp);
-    update_script.main([name, temp]);
-  }
-
-  updateSuite(String suite) {
-    String runtime = "d8";
-    if (suite == "html") {
-      runtime = "drt";
-    }
-    print("update suite: \u001b[32m$suite\u001b[0m");
-
-    updateSuiteWithFlags(
-        'minified', suite, runtime, ["--minified", "--use-sdk"]);
-    updateSuiteWithFlags('host-checked', suite, runtime, ["--host-checked"]);
-    if (fastStartup) {
-      updateSuiteWithFlags('fast-startup', suite, runtime, ["--fast-startup"]);
-    }
-    if (checkedMode) {
-      updateSuiteWithFlags('checked-mode', suite, runtime, ["--checked"]);
-    }
-  }
-
-  print('build create_sdk');
-  ProcessResult result = Process.runSync(
-      python, ['./tools/build.py', '-m', 'release', 'create_sdk']);
-  if (result.exitCode != 0) {
-    print(result.stdout);
-    print(result.stderr);
-    exit(1);
-  }
-
-  suites.forEach(updateSuite);
-
-  tmp.deleteSync(recursive: true);
-}
diff --git a/pkg/compiler/tool/status_files/update_from_log.dart b/pkg/compiler/tool/status_files/update_from_log.dart
deleted file mode 100644
index 26a6dd0..0000000
--- a/pkg/compiler/tool/status_files/update_from_log.dart
+++ /dev/null
@@ -1,281 +0,0 @@
-// Copyright (c) 2017, 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.
-
-/// Script that updates dart2js status lines automatically for tests under the
-/// '$fasta' configuration.
-///
-/// This script is hardcoded to only support this configuration and relies on
-/// a convention for how the status files are structured, In particular,
-/// every status file for dart2js should have 3 sections:
-///
-///     [ $compiler == dart2js && $fasta && $host_checked ]
-///
-/// and:
-///
-///     [ $compiler == dart2js && $fasta && $minified ]
-///
-/// and:
-///
-///     [ $compiler == dart2js && $fasta && $fast_startup ]
-///
-/// and:
-///
-///     [ $compiler == dart2js && $checked && $fasta ]
-library compiler.status_files.update_from_log;
-
-import 'dart:io';
-
-import 'record.dart';
-import 'log_parser.dart';
-
-final dart2jsConfigurations = {
-  'host-checked': r'[ $compiler == dart2js && $fasta && $host_checked ]',
-  'minified': r'[ $compiler == dart2js && $fasta && $minified ]',
-  'host-checked-strong':
-      r'[ $compiler == dart2js && $fasta && $host_checked && $strong ]',
-  'minified-strong':
-      r'[ $compiler == dart2js && $fasta && $minified && $strong ]',
-  'fast-startup': r'[ $compiler == dart2js && $fast_startup && $fasta ]',
-  'fast-startup-strong':
-      r'[ $compiler == dart2js && $fast_startup && $fasta && $strong ]',
-  'checked-mode': r'[ $compiler == dart2js && $checked && $fasta ]',
-  'checked-mode-strong':
-      r'[ $compiler == dart2js && $checked && $fasta && $strong ]',
-};
-
-final dart2jsStatusFiles = {
-  'language_2': 'tests/language_2/language_2_dart2js.status',
-  // TODO(sigmund,rnystrom): update when corelib_2 gets split into multiple
-  // status files.
-  'corelib_2': 'tests/corelib_2/corelib_2.status',
-  'dart2js_extra': 'tests/compiler/dart2js_extra/dart2js_extra.status',
-  'dart2js_native': 'tests/compiler/dart2js_native/dart2js_native.status',
-};
-
-main(args) {
-  mainInternal(args, dart2jsConfigurations, dart2jsStatusFiles);
-}
-
-/// Note: this is called above and also from
-/// pkg/front_end/tool/status_files/update_from_log.dart
-mainInternal(List<String> args, Map<String, String> configurations,
-    Map<String, String> statusFiles) {
-  if (args.length < 2) {
-    print('usage: update_from_log.dart <mode> log.txt [message-in-quotes]');
-    print('  where mode is one of these values: ${configurations.keys}');
-    exit(1);
-  }
-  var mode = args[0];
-  if (!configurations.containsKey(mode)) {
-    print('invalid mode: $mode, expected one in ${configurations.keys}');
-    exit(1);
-  }
-
-  var uri =
-      Uri.base.resolveUri(new Uri.file(args[1], windows: Platform.isWindows));
-  var file = new File.fromUri(uri);
-  if (!file.existsSync()) {
-    print('file not found: $file');
-    exit(1);
-  }
-
-  var globalReason = args.length > 2 ? args[2] : null;
-  updateLogs(
-      mode, file.readAsStringSync(), configurations, statusFiles, globalReason);
-}
-
-/// Update all status files based on the [log] records when running the compiler
-/// in [mode]. If provided [globalReason] is added as a comment to new test
-/// failures. If not, an automated reason might be extracted from the test
-/// failure message.
-void updateLogs(String mode, String log, Map<String, String> configurations,
-    Map<String, String> statusFiles, String globalReason) {
-  List<Record> records = parse(log);
-  records.sort();
-  var last;
-  ConfigurationInSuiteSection section;
-  for (var record in records) {
-    if (last == record) continue; // ignore duplicates
-    if (section?.suite != record.suite) {
-      section?.update(globalReason);
-      var statusFile = statusFiles[record.suite];
-      if (statusFile == null) {
-        print("No status file for suite '${record.suite}'.");
-        continue;
-      }
-      var condition = configurations[mode];
-      section = ConfigurationInSuiteSection.create(
-          record.suite, mode, statusFile, condition);
-    }
-    section.add(record);
-    last = record;
-  }
-  section?.update(globalReason);
-}
-
-/// Represents an existing entry in the logs.
-class ExistingEntry {
-  final String test;
-  final String status;
-  final bool hasComment;
-
-  ExistingEntry(this.test, this.status, this.hasComment);
-
-  static parse(String line) {
-    var colonIndex = line.indexOf(':');
-    var test = line.substring(0, colonIndex);
-    var status = line.substring(colonIndex + 1).trim();
-    var commentIndex = status.indexOf("#");
-    if (commentIndex != -1) {
-      status = status.substring(0, commentIndex);
-    }
-    return new ExistingEntry(test, status, commentIndex != -1);
-  }
-}
-
-/// Represents a section in a .status file that corresponds to a specific suite
-/// and configuration.
-class ConfigurationInSuiteSection {
-  final String suite;
-  final String _statusFile;
-  final String _contents;
-  final int _begin;
-  final int _end;
-  final List<Record> _records = [];
-
-  ConfigurationInSuiteSection(
-      this.suite, this._statusFile, this._contents, this._begin, this._end);
-
-  /// Add a new test record, indicating that the test status should be updated.
-  void add(Record record) => _records.add(record);
-
-  /// Update the section in the file.
-  ///
-  /// This will reflect the new status lines as recorded in [_records].
-  void update(String providedReason) {
-    int changes = 0;
-    int ignored = 0;
-    var originalEntries = _contents.substring(_begin, _end).split('\n');
-
-    // The algorithm below walks entries in the file and from the log in the
-    // same order: preserving entries that didn't change, and updating entries
-    // where the logs show that the test status changed.
-
-    // Sort the file contents in case the file has been tampered with.
-    originalEntries.sort();
-
-    /// Re-sort records by name (they came sorted by suite and status first, so
-    /// it may be wrong for the merging below).
-    _records.sort((a, b) => a.test.compareTo(b.test));
-
-    var newContents = new StringBuffer();
-    newContents.write(_contents.substring(0, _begin));
-    addFromRecord(Record record) {
-      var reason = providedReason ?? record.reason;
-      var comment = reason != null && reason.isNotEmpty ? ' # ${reason}' : '';
-      newContents.writeln('${record.test}: ${record.actual}$comment');
-    }
-
-    int i = 0, j = 0;
-    while (i < originalEntries.length && j < _records.length) {
-      var existingLine = originalEntries[i];
-      if (existingLine.trim().isEmpty) {
-        i++;
-        continue;
-      }
-      var existing = ExistingEntry.parse(existingLine);
-      var record = _records[j];
-      var compare = existing.test.compareTo(record.test);
-      if (compare < 0) {
-        // Existing test was unaffected, copy the status line.
-        newContents.writeln(existingLine);
-        i++;
-      } else if (compare > 0) {
-        // New entry, if it's a failure, we haven't seen this before and must
-        // add it. If the status says it is passing, we ignore it. We do this
-        // to support making this script idempotent if the patching has already
-        // been done.
-        if (!record.isPassing) {
-          // New failure never seen before
-          addFromRecord(record);
-          changes++;
-        }
-        j++;
-      } else if (existing.status == record.actual) {
-        if (!existing.hasComment && record.reason != null) {
-          addFromRecord(record);
-          changes++;
-        } else {
-          // This also should only happen if the patching has already been done.
-          // We don't complain to make this script idempotent.
-          newContents.writeln(existingLine);
-        }
-        ignored++;
-        i++;
-        j++;
-      } else {
-        changes++;
-        // The status changed, if it is now passing, we omit the entry entirely,
-        // otherwise we use the status from the logs.
-        if (!record.isPassing) {
-          addFromRecord(record);
-        }
-        i++;
-        j++;
-      }
-    }
-
-    for (; i < originalEntries.length; i++) {
-      newContents.writeln(originalEntries[i]);
-    }
-
-    for (; j < _records.length; j++) {
-      changes++;
-      addFromRecord(_records[j]);
-    }
-
-    newContents.write('\n');
-    newContents.write(_contents.substring(_end));
-    new File(_statusFile).writeAsStringSync('$newContents');
-    print("updated '$_statusFile' with $changes changes");
-    if (ignored > 0) {
-      print('  $ignored changes were already applied in the status file.');
-    }
-  }
-
-  static ConfigurationInSuiteSection create(
-      String suite, String mode, String statusFile, String condition) {
-    var contents = new File(statusFile).readAsStringSync();
-    int sectionDeclaration = contents.indexOf(condition);
-    if (sectionDeclaration == -1) {
-      print('error: unable to find condition $condition in $statusFile');
-      exit(1);
-    }
-    int begin = contents.indexOf('\n', sectionDeclaration) + 1;
-    assert(begin != 0);
-    int newlinePos = contents.indexOf('\n', begin + 1);
-    int end = newlinePos;
-    while (true) {
-      if (newlinePos == -1) break;
-      if (newlinePos + 1 < contents.length) {
-        if (contents[newlinePos + 1] == '[') {
-          // We've found the end of the section
-          break;
-        } else if (contents[newlinePos + 1] == '#') {
-          // We've found a commented out line.  This line might belong to the
-          // next section.
-          newlinePos = contents.indexOf('\n', newlinePos + 1);
-          continue;
-        }
-      }
-      // We've found an ordinary line.  It's part of this section, so update
-      // end.
-      newlinePos = contents.indexOf('\n', newlinePos + 1);
-      end = newlinePos;
-    }
-    end = end == -1 ? contents.length : end + 1;
-    return new ConfigurationInSuiteSection(
-        suite, statusFile, contents, begin, end);
-  }
-}
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index cbb7d34..6e08dfb 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -200,6 +200,11 @@
 
   final DeclaredVariables declaredVariables;
 
+  /// Tracks the temporary variable used to build collections containing
+  /// control flow [IfElement] and [ForElement] nodes. Should be saved when
+  /// visiting a new control flow tree and restored after.
+  JS.Expression _currentCollectionVariable;
+
   CodeGenerator(LinkedAnalysisDriver driver, this.types, this.summaryData,
       this.options, this._extensionTypes, this.errors)
       : rules = Dart2TypeSystem(types),
@@ -5432,8 +5437,11 @@
     return JS.Do(_visitScope(node.body), _visitTest(node.condition));
   }
 
-  JS.Statement _emitAwaitFor(SimpleIdentifier identifier,
-      DeclaredIdentifier loopVariable, Expression iterable, Statement body) {
+  JS.Statement _emitAwaitFor(
+      SimpleIdentifier identifier,
+      DeclaredIdentifier loopVariable,
+      Expression iterable,
+      JS.Statement jsBody) {
     // Emits `await for (var value in stream) ...`, which desugars as:
     //
     // let iter = new StreamIterator(stream);
@@ -5478,7 +5486,7 @@
           JS.Yield(js.call('#.moveNext()', iter))
             ..sourceInformation = _nodeStart(variable),
           init,
-          _visitStatement(body),
+          jsBody,
           JS.Yield(js.call('#.cancel()', iter))
             ..sourceInformation = _nodeStart(variable)
         ]);
@@ -5716,29 +5724,29 @@
   @override
   JS.Expression visitListLiteral(ListLiteral node) {
     var elementType = (node.staticType as InterfaceType).typeArguments[0];
+    var elements = _visitCollectionElementList(node.elements2, elementType);
     if (!node.isConst) {
-      return _emitList(elementType, _visitExpressionList(node.elements2));
+      return _emitList(elementType, elements);
     }
-    return _cacheConst(() =>
-        _emitConstList(elementType, _visitExpressionList(node.elements2)));
+
+    return _cacheConst(() => _emitConstList(elementType, elements));
   }
 
   // TODO(nshahan) Cleanup after control flow collections experiments are removed.
   JS.Expression _emitSetLiteral(
       Iterable<CollectionElement> elements, SetOrMapLiteral node) {
     var type = node.staticType as InterfaceType;
+    var elementType = type.typeArguments[0];
+    var jsElements = _visitCollectionElementList(elements, elementType);
     if (!node.isConst) {
       var setType = _emitType(type);
       if (elements.isEmpty) {
         return js.call('#.new()', [setType]);
       }
-      return js.call(
-          '#.from([#])', [setType, _visitCollectionElementList(elements)]);
+      return js.call('#.from([#])', [setType, jsElements]);
     }
-    return _cacheConst(() => runtimeCall('constSet(#, [#])', [
-          _emitType((node.staticType as InterfaceType).typeArguments[0]),
-          _visitCollectionElementList(elements)
-        ]));
+    return _cacheConst(() =>
+        runtimeCall('constSet(#, [#])', [_emitType(elementType), jsElements]));
   }
 
   JS.Expression _emitConstList(
@@ -5764,16 +5772,16 @@
   JS.Expression _emitMapLiteral(
       Iterable<CollectionElement> elements, SetOrMapLiteral node) {
     var type = node.staticType as InterfaceType;
+    var elementType = type.typeArguments[0];
+    var jsElements = _visitCollectionElementList(elements, elementType);
     if (!node.isConst) {
       var mapType = _emitMapImplType(type);
       if (elements.isEmpty) {
         return js.call('new #.new()', [mapType]);
       }
-      return js.call(
-          'new #.from([#])', [mapType, _visitCollectionElementList(elements)]);
+      return js.call('new #.from([#])', [mapType, jsElements]);
     }
-    return _cacheConst(
-        () => _emitConstMap(type, _visitCollectionElementList(elements)));
+    return _cacheConst(() => _emitConstMap(type, jsElements));
   }
 
   JS.Expression _emitConstMap(InterfaceType type, List<JS.Expression> entries) {
@@ -5864,13 +5872,50 @@
     return nodes?.map(_visitStatement)?.toList();
   }
 
-  /// Visits [nodes] with [_visitColelctionElement].
+  /// Returns a [JS.Expression] for each [CollectionElement] in [nodes].
+  ///
+  /// Visits all [nodes] in order and nested [CollectionElement]s depth first
+  /// to produce [JS.Expresison]s intended to be used when outputing a
+  /// collection literal.
+  ///
+  /// [IfElement]s and [ForElement]s will be transformed into a spread of a
+  /// self invoking function that reutrns a list.
+  ///
+  /// Example Dart:
+  ///     [1, if(true) for (var i=2; i<10; i++) i, 10]
+  ///
+  /// JS:
+  ///     [1, ...(() => {
+  ///       let temp = JSArrayOfint().of([]);
+  ///       if (true) for (let i = 2; i < 10; i++) temp.push(i);
+  ///       return temp;
+  ///     })(), 10]
   List<JS.Expression> _visitCollectionElementList(
-      Iterable<CollectionElement> nodes) {
+      Iterable<CollectionElement> nodes, DartType elementType) {
     var expressions = <JS.Expression>[];
     for (var node in nodes) {
-      //TODO(nshahan) Handle [IfElement] and [ForElement].
-      if (node is MapLiteralEntry) {
+      if (_isUiAsCodeElement(node)) {
+        // Create a temporary variable to build a new collection from.
+        var previousCollectionVariable = _currentCollectionVariable;
+        var temporaryIdentifier =
+            _createTemporary('items', _jsArray.type.instantiate([elementType]));
+        _currentCollectionVariable = _emitSimpleIdentifier(temporaryIdentifier);
+        var items = js.statement('let # = #',
+            [_currentCollectionVariable, _emitList(elementType, [])]);
+
+        // Build up a list for the control-flow-collections element and wrap in
+        // a function call that returns the list.
+        var functionBody = JS.Block([
+          items,
+          node.accept<JS.Node>(this),
+          JS.Return(_currentCollectionVariable)
+        ]);
+        var functionCall = JS.Call(JS.ArrowFun([], functionBody), []);
+
+        // Finally, spread the temporary control-flow-collections list.
+        expressions.add(JS.Spread(functionCall));
+        _currentCollectionVariable = previousCollectionVariable;
+      } else if (node is MapLiteralEntry) {
         expressions.add(_visitExpression(node.key));
         expressions.add(_visitExpression(node.value));
       } else {
@@ -5880,6 +5925,26 @@
     return expressions;
   }
 
+  /// Visits [node] with [_visitExpression] and wraps the result in a call to
+  /// append it to the list tracked by [_currentCollectionVariable].
+  JS.Statement _visitNestedCollectionElement(CollectionElement node) {
+    JS.Statement pushToCurrentCollection(Expression value) => js.statement(
+        '#.push(#)', [_currentCollectionVariable, _visitExpression(value)]);
+
+    if (node is MapLiteralEntry) {
+      return JS.Block([
+        pushToCurrentCollection(node.key),
+        pushToCurrentCollection(node.value)
+      ]);
+    }
+
+    return pushToCurrentCollection(node);
+  }
+
+  /// Returns `true` if [node] is a UI-as-Code [CollectionElement].
+  bool _isUiAsCodeElement(node) =>
+      node is IfElement || node is ForElement || node is SpreadElement;
+
   /// Gets the start position of [node] for use in source mapping.
   ///
   /// This is the most common kind of marking, and is used for most expressions
@@ -6430,7 +6495,7 @@
   // TODO(nshahan) Simplify when control-flow-collections experiments are removed.
   // Should just accept a ForParts as an arg with fewer casts.
   JS.For _emitFor(Expression initialization, VariableDeclarationList variables,
-      Expression condition, Iterable<Expression> updaters, Statement body) {
+      Expression condition, Iterable<Expression> updaters, JS.Statement body) {
     var init = _visitExpression(initialization) ??
         visitVariableDeclarationList(variables);
     JS.Expression update;
@@ -6440,17 +6505,18 @@
               .toVoidExpression();
     }
 
-    return JS.For(init, _visitTest(condition), update, _visitScope(body));
+    return JS.For(init, _visitTest(condition), update, body);
   }
 
   // TODO(nshahan) Simplify when control-flow-collections experiments are removed.
   // Should just accept a ForEachParts as an arg with fewer casts.
-  JS.Statement _emitForEach(SimpleIdentifier identifier,
-      DeclaredIdentifier loopVariable, Expression iterable, Statement body) {
+  JS.Statement _emitForEach(
+      SimpleIdentifier identifier,
+      DeclaredIdentifier loopVariable,
+      Expression iterable,
+      JS.Statement jsBody) {
     var jsLeftExpression = _visitExpression(identifier);
     var jsIterable = _visitExpression(iterable);
-
-    var jsBody = _visitScope(body);
     if (jsLeftExpression == null) {
       var id = _emitVariableDef(loopVariable.identifier);
       jsLeftExpression = js.call('let #', id);
@@ -6470,10 +6536,33 @@
   }
 
   @override
-  visitForElement(ForElement node) => _unreachable(node);
+  JS.Statement visitForElement(ForElement node) {
+    // TODO(nshahan) Need to support await for in collections.
+    if (node.awaitKeyword != null) return _unreachable(node);
+    var jsBody = _isUiAsCodeElement(node.body)
+        ? node.body.accept(this)
+        : _visitNestedCollectionElement(node.body);
+
+    return _forAdaptor(node.forLoopParts, node.awaitKeyword, jsBody);
+  }
 
   @override
-  visitIfElement(IfElement node) => _unreachable(node);
+  JS.Statement visitIfElement(IfElement node) {
+    var thenElement = _isUiAsCodeElement(node.thenElement)
+        ? node.thenElement.accept(this)
+        : _visitNestedCollectionElement(node.thenElement);
+
+    JS.Statement elseElement;
+    if (node.elseElement != null) {
+      if (_isUiAsCodeElement(node.elseElement)) {
+        elseElement = node.elseElement.accept<JS.Node>(this);
+      } else {
+        elseElement = _visitNestedCollectionElement(node.elseElement);
+      }
+    }
+
+    return JS.If(_visitTest(node.condition), thenElement, elseElement);
+  }
 
   @override
   visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) =>
@@ -6484,31 +6573,34 @@
       _unreachable(node);
 
   @override
-  JS.Statement visitForStatement2(ForStatement2 node) {
-    // TODO(nshahan) Simplify when control-flow-collections experiments are removed.
-    var forParts = node.forLoopParts;
+  JS.Statement visitForStatement2(ForStatement2 node) =>
+      _forAdaptor(node.forLoopParts, node.awaitKeyword, _visitScope(node.body));
+
+  // TODO(nshahan) Simplify when control-flow-collections experiment is removed.
+  JS.Statement _forAdaptor(
+      ForLoopParts forParts, Token awaitKeyword, JS.Statement jsBody) {
     if (forParts is ForPartsWithExpression) {
       return _emitFor(forParts.initialization, null, forParts.condition,
-          forParts.updaters, node.body);
+          forParts.updaters, jsBody);
     } else if (forParts is ForPartsWithDeclarations) {
       return _emitFor(null, forParts.variables, forParts.condition,
-          forParts.updaters, node.body);
-    } else if (node.awaitKeyword == null) {
+          forParts.updaters, jsBody);
+    } else if (awaitKeyword == null) {
       if (forParts is ForEachPartsWithIdentifier) {
         return _emitForEach(
-            forParts.identifier, null, forParts.iterable, node.body);
+            forParts.identifier, null, forParts.iterable, jsBody);
       } else if (forParts is ForEachPartsWithDeclaration) {
         return _emitForEach(
-            null, forParts.loopVariable, forParts.iterable, node.body);
+            null, forParts.loopVariable, forParts.iterable, jsBody);
       }
     } else if (forParts is ForEachPartsWithIdentifier) {
       return _emitAwaitFor(
-          forParts.identifier, null, forParts.iterable, node.body);
+          forParts.identifier, null, forParts.iterable, jsBody);
     } else if (forParts is ForEachPartsWithDeclaration) {
       return _emitAwaitFor(
-          null, forParts.loopVariable, forParts.iterable, node.body);
+          null, forParts.loopVariable, forParts.iterable, jsBody);
     }
-    return _unreachable(node);
+    return _unreachable(forParts);
   }
 
   @deprecated
diff --git a/pkg/dev_compiler/lib/src/analyzer/driver.dart b/pkg/dev_compiler/lib/src/analyzer/driver.dart
index cec419b..a4fd216 100644
--- a/pkg/dev_compiler/lib/src/analyzer/driver.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/driver.dart
@@ -77,8 +77,6 @@
       {SummaryDataStore summaryData,
       List<String> summaryPaths = const [],
       Map<String, bool> experiments = const {}}) {
-    AnalysisEngine.instance.processRequiredPlugins();
-
     var resourceProvider = options.resourceProvider;
     var contextBuilder = options.createContextBuilder();
 
@@ -235,7 +233,8 @@
         libraryUris.toSet(),
         (uri) => summaryData.linkedMap[uri],
         (uri) => summaryData.unlinkedMap[uri] ?? uriToUnit[uri],
-        declaredVariables.get);
+        declaredVariables,
+        analysisOptions);
     linkResult.forEach(assembler.addLinkedLibrary);
 
     var summaryBytes = assembler.assemble().toBuffer();
diff --git a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
index 65cfe52..e911dca 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
@@ -4,7 +4,7 @@
 
 // TODO(jmesserly): import from its own package
 import '../js_ast/js_ast.dart';
-
+import 'shared_compiler.dart' show YieldFinder;
 import 'js_names.dart' show TemporaryId;
 
 /// A synthetic `let*` node, similar to that found in Scheme.
@@ -181,7 +181,7 @@
   }
 
   Expression _toInvokedFunction(Block block) {
-    var finder = _YieldFinder();
+    var finder = YieldFinder();
     block.accept(finder);
     if (!finder.hasYield) {
       return Call(ArrowFun([], block), []);
@@ -353,34 +353,3 @@
     if (!found) super.visitNode(node);
   }
 }
-
-class _YieldFinder extends BaseVisitor {
-  bool hasYield = false;
-  bool hasThis = false;
-  bool _nestedFunction = false;
-
-  @override
-  visitThis(This node) {
-    hasThis = true;
-  }
-
-  @override
-  visitFunctionExpression(FunctionExpression node) {
-    var savedNested = _nestedFunction;
-    _nestedFunction = true;
-    super.visitFunctionExpression(node);
-    _nestedFunction = savedNested;
-  }
-
-  @override
-  visitYield(Yield node) {
-    if (!_nestedFunction) hasYield = true;
-    super.visitYield(node);
-  }
-
-  @override
-  visitNode(Node node) {
-    if (hasYield && hasThis) return; // found both, nothing more to do.
-    super.visitNode(node);
-  }
-}
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
index 66e0628..be9b13f 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -192,3 +192,34 @@
     if (!found) super.visitNode(node);
   }
 }
+
+class YieldFinder extends JS.BaseVisitor {
+  bool hasYield = false;
+  bool hasThis = false;
+  bool _nestedFunction = false;
+
+  @override
+  visitThis(JS.This node) {
+    hasThis = true;
+  }
+
+  @override
+  visitFunctionExpression(JS.FunctionExpression node) {
+    var savedNested = _nestedFunction;
+    _nestedFunction = true;
+    super.visitFunctionExpression(node);
+    _nestedFunction = savedNested;
+  }
+
+  @override
+  visitYield(JS.Yield node) {
+    if (!_nestedFunction) hasYield = true;
+    super.visitYield(node);
+  }
+
+  @override
+  visitNode(JS.Node node) {
+    if (hasYield && hasThis) return; // found both, nothing more to do.
+    super.visitNode(node);
+  }
+}
diff --git a/pkg/dev_compiler/lib/src/flutter/track_widget_constructor_locations.dart b/pkg/dev_compiler/lib/src/flutter/track_widget_constructor_locations.dart
new file mode 100644
index 0000000..e44eb59
--- /dev/null
+++ b/pkg/dev_compiler/lib/src/flutter/track_widget_constructor_locations.dart
@@ -0,0 +1,573 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO(jmesserly): this file was copied from:
+// https://github.com/flutter/engine/blob/4b01d795feec3ba8231a397a4ec2759954d8216e/flutter_kernel_transformers/lib/track_widget_constructor_locations.dart
+//
+// Longer term, this transform should be injected by Flutter when they building
+// the Flutter-specific `dartdevc` script.
+//
+// The following modifications were made:
+// - remove "package:vm" dependency (only used for one interface)
+// - pass in the class hierarchy that DDC already has available.
+library track_widget_constructor_locations;
+
+// The kernel/src import below that requires lint `ignore_for_file`
+// is a temporary state of things until kernel team builds better api that would
+// replace api used below. This api was made private in an effort to discourage
+// further use.
+// ignore_for_file: implementation_imports
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:meta/meta.dart';
+
+// Parameter name used to track were widget constructor calls were made from.
+//
+// The parameter name contains a randomly generate hex string to avoid collision
+// with user generated parameters.
+const String _creationLocationParameterName =
+    r'$creationLocationd_0dea112b090073317d4';
+
+/// Name of private field added to the Widget class and any other classes that
+/// implement Widget.
+///
+/// Regardless of what library a class implementing Widget is defined in, the
+/// private field will always be defined in the context of the widget_inspector
+/// library ensuring no name conflicts with regular fields.
+const String _locationFieldName = r'_location';
+
+bool _hasNamedParameter(FunctionNode function, String name) {
+  return function.namedParameters
+      .any((VariableDeclaration parameter) => parameter.name == name);
+}
+
+bool _hasNamedArgument(Arguments arguments, String argumentName) {
+  return arguments.named
+      .any((NamedExpression argument) => argument.name == argumentName);
+}
+
+VariableDeclaration _getNamedParameter(
+  FunctionNode function,
+  String parameterName,
+) {
+  for (VariableDeclaration parameter in function.namedParameters) {
+    if (parameter.name == parameterName) {
+      return parameter;
+    }
+  }
+  return null;
+}
+
+// TODO(jacobr): find a solution that supports optional positional parameters.
+/// Add the creation location to the arguments list if possible.
+///
+/// Returns whether the creation location argument could be added. We cannot
+/// currently add the named argument for functions with optional positional
+/// parameters as the current scheme requires adding the creation location as a
+/// named parameter. Fortunately that is not a significant issue in practice as
+/// no Widget classes in package:flutter have optional positional parameters.
+/// This code degrades gracefully for constructors with optional positional
+/// parameters by skipping adding the creation location argument rather than
+/// failing.
+void _maybeAddCreationLocationArgument(
+  Arguments arguments,
+  FunctionNode function,
+  Expression creationLocation,
+  Class locationClass,
+) {
+  if (_hasNamedArgument(arguments, _creationLocationParameterName)) {
+    return;
+  }
+  if (!_hasNamedParameter(function, _creationLocationParameterName)) {
+    return;
+  }
+
+  final NamedExpression namedArgument =
+      new NamedExpression(_creationLocationParameterName, creationLocation);
+  namedArgument.parent = arguments;
+  arguments.named.add(namedArgument);
+}
+
+/// Adds a named parameter to a function if the function does not already have
+/// a named parameter with the name or optional positional parameters.
+bool _maybeAddNamedParameter(
+  FunctionNode function,
+  VariableDeclaration variable,
+) {
+  if (_hasNamedParameter(function, _creationLocationParameterName)) {
+    // Gracefully handle if this method is called on a function that has already
+    // been transformed.
+    return false;
+  }
+  // Function has optional positional parameters so cannot have optional named
+  // parameters.
+  if (function.requiredParameterCount != function.positionalParameters.length) {
+    return false;
+  }
+  variable.parent = function;
+  function.namedParameters.add(variable);
+  return true;
+}
+
+/// Transformer that modifies all calls to Widget constructors to include
+/// a [DebugLocation] parameter specifying the location where the constructor
+/// call was made.
+///
+/// This transformer requires that all Widget constructors have already been
+/// transformed to have a named parameter with the name specified by
+/// `_locationParameterName`.
+class _WidgetCallSiteTransformer extends Transformer {
+  final ClassHierarchy _hierarchy;
+
+  /// The [Widget] class defined in the `package:flutter` library.
+  ///
+  /// Used to perform instanceof checks to determine whether Dart constructor
+  /// calls are creating [Widget] objects.
+  Class _widgetClass;
+
+  /// The [DebugLocation] class defined in the `package:flutter` library.
+  Class _locationClass;
+
+  /// Current factory constructor that node being transformed is inside.
+  ///
+  /// Used to flow the location passed in as an argument to the factory to the
+  /// actual constructor call within the factory.
+  Procedure _currentFactory;
+
+  _WidgetCallSiteTransformer(
+    this._hierarchy, {
+    @required Class widgetClass,
+    @required Class locationClass,
+  })  : _widgetClass = widgetClass,
+        _locationClass = locationClass;
+
+  /// Builds a call to the const constructor of the [DebugLocation]
+  /// object specifying the location where a constructor call was made and
+  /// optionally the locations for all parameters passed in.
+  ///
+  /// Specifying the parameters passed in is an experimental feature. With
+  /// access to the source code of an application you could determine the
+  /// locations of the parameters passed in from the source location of the
+  /// constructor call but it is convenient to bundle the location and names
+  /// of the parameters passed in so that tools can show parameter locations
+  /// without re-parsing the source code.
+  ConstructorInvocation _constructLocation(
+    Location location, {
+    String name,
+    ListLiteral parameterLocations,
+    bool showFile: true,
+  }) {
+    final List<NamedExpression> arguments = <NamedExpression>[
+      new NamedExpression('line', new IntLiteral(location.line)),
+      new NamedExpression('column', new IntLiteral(location.column)),
+    ];
+    if (showFile) {
+      arguments.add(new NamedExpression(
+          'file', new StringLiteral(location.file.toString())));
+    }
+    if (name != null) {
+      arguments.add(new NamedExpression('name', new StringLiteral(name)));
+    }
+    if (parameterLocations != null) {
+      arguments
+          .add(new NamedExpression('parameterLocations', parameterLocations));
+    }
+    return new ConstructorInvocation(
+      _locationClass.constructors.first,
+      new Arguments(<Expression>[], named: arguments),
+      isConst: true,
+    );
+  }
+
+  @override
+  Procedure visitProcedure(Procedure node) {
+    if (node.isFactory) {
+      _currentFactory = node;
+      node.transformChildren(this);
+      _currentFactory = null;
+      return node;
+    }
+    return defaultTreeNode(node);
+  }
+
+  bool _isSubclassOfWidget(Class clazz) {
+    // TODO(jacobr): use hierarchy.isSubclassOf once we are using the
+    // non-deprecated ClassHierarchy constructor.
+    return _hierarchy.isSubclassOf(clazz, _widgetClass);
+  }
+
+  @override
+  StaticInvocation visitStaticInvocation(StaticInvocation node) {
+    node.transformChildren(this);
+    final Procedure target = node.target;
+    if (!target.isFactory) {
+      return node;
+    }
+    final Class constructedClass = target.enclosingClass;
+    if (!_isSubclassOfWidget(constructedClass)) {
+      return node;
+    }
+
+    _addLocationArgument(node, target.function, constructedClass);
+    return node;
+  }
+
+  void _addLocationArgument(InvocationExpression node, FunctionNode function,
+      Class constructedClass) {
+    _maybeAddCreationLocationArgument(
+      node.arguments,
+      function,
+      _computeLocation(node, function, constructedClass),
+      _locationClass,
+    );
+  }
+
+  @override
+  ConstructorInvocation visitConstructorInvocation(ConstructorInvocation node) {
+    node.transformChildren(this);
+
+    final Constructor constructor = node.target;
+    final Class constructedClass = constructor.enclosingClass;
+    if (!_isSubclassOfWidget(constructedClass)) {
+      return node;
+    }
+
+    _addLocationArgument(node, constructor.function, constructedClass);
+    return node;
+  }
+
+  Expression _computeLocation(InvocationExpression node, FunctionNode function,
+      Class constructedClass) {
+    // For factory constructors we need to use the location specified as an
+    // argument to the factory constructor rather than the location
+    // TODO(jacobr): use hierarchy.isSubclassOf once we are using the
+    // non-deprecated ClassHierarchy constructor.
+    if (_currentFactory != null &&
+        _hierarchy.isSubclassOf(
+            constructedClass, _currentFactory.enclosingClass)) {
+      final VariableDeclaration creationLocationParameter = _getNamedParameter(
+        _currentFactory.function,
+        _creationLocationParameterName,
+      );
+      if (creationLocationParameter != null) {
+        return new VariableGet(creationLocationParameter);
+      }
+    }
+
+    final Arguments arguments = node.arguments;
+    final Location location = node.location;
+    final List<ConstructorInvocation> parameterLocations =
+        <ConstructorInvocation>[];
+    final List<VariableDeclaration> parameters = function.positionalParameters;
+    for (int i = 0; i < arguments.positional.length; ++i) {
+      final Expression expression = arguments.positional[i];
+      final VariableDeclaration parameter = parameters[i];
+      parameterLocations.add(_constructLocation(
+        expression.location,
+        name: parameter.name,
+        showFile: false,
+      ));
+    }
+    for (NamedExpression expression in arguments.named) {
+      parameterLocations.add(_constructLocation(
+        expression.location,
+        name: expression.name,
+        showFile: false,
+      ));
+    }
+    return _constructLocation(
+      location,
+      parameterLocations: new ListLiteral(
+        parameterLocations,
+        typeArgument: _locationClass.thisType,
+        isConst: true,
+      ),
+    );
+  }
+}
+
+/// Rewrites all widget constructors and constructor invocations to add a
+/// parameter specifying the location the constructor was called from.
+///
+/// The creation location is stored as a private field named `_location`
+/// on the base widget class and flowed through the constructors using a named
+/// parameter.
+class WidgetCreatorTracker {
+  Class _widgetClass;
+  Class _locationClass;
+
+  /// Marker interface indicating that a private _location field is
+  /// available.
+  Class _hasCreationLocationClass;
+
+  /// The [ClassHierarchy] that should be used after applying this transformer.
+  /// If any class was updated, in general we need to create a new
+  /// [ClassHierarchy] instance, with new dispatch targets; or at least let
+  /// the existing instance know that some of its dispatch tables are not
+  /// valid anymore.
+  final ClassHierarchy hierarchy;
+
+  WidgetCreatorTracker(this.hierarchy);
+
+  void _resolveFlutterClasses(Iterable<Library> libraries) {
+    // If the Widget or Debug location classes have been updated we need to get
+    // the latest version
+    for (Library library in libraries) {
+      final Uri importUri = library.importUri;
+      if (!library.isExternal &&
+          importUri != null &&
+          importUri.scheme == 'package') {
+        if (importUri.path == 'flutter/src/widgets/framework.dart') {
+          for (Class class_ in library.classes) {
+            if (class_.name == 'Widget') {
+              _widgetClass = class_;
+            }
+          }
+        } else {
+          if (importUri.path == 'flutter/src/widgets/widget_inspector.dart') {
+            for (Class class_ in library.classes) {
+              if (class_.name == '_HasCreationLocation') {
+                _hasCreationLocationClass = class_;
+              } else if (class_.name == '_Location') {
+                _locationClass = class_;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  /// Modify [clazz] to add a field named [_locationFieldName] that is the
+  /// first parameter of all constructors of the class.
+  ///
+  /// This method should only be called for classes that implement but do not
+  /// extend [Widget].
+  void _transformClassImplementingWidget(Class clazz) {
+    if (clazz.fields
+        .any((Field field) => field.name.name == _locationFieldName)) {
+      // This class has already been transformed. Skip
+      return;
+    }
+    clazz.implementedTypes
+        .add(new Supertype(_hasCreationLocationClass, <DartType>[]));
+    // We intentionally use the library context of the _HasCreationLocation
+    // class for the private field even if [clazz] is in a different library
+    // so that all classes implementing Widget behave consistently.
+    final Field locationField = new Field(
+      new Name(
+        _locationFieldName,
+        _hasCreationLocationClass.enclosingLibrary,
+      ),
+      isFinal: true,
+    );
+    clazz.addMember(locationField);
+
+    final Set<Constructor> _handledConstructors =
+        new Set<Constructor>.identity();
+
+    void handleConstructor(Constructor constructor) {
+      if (!_handledConstructors.add(constructor)) {
+        return;
+      }
+      assert(!_hasNamedParameter(
+        constructor.function,
+        _creationLocationParameterName,
+      ));
+      final VariableDeclaration variable = new VariableDeclaration(
+        _creationLocationParameterName,
+        type: _locationClass.thisType,
+      );
+      if (!_maybeAddNamedParameter(constructor.function, variable)) {
+        return;
+      }
+
+      bool hasRedirectingInitializer = false;
+      for (Initializer initializer in constructor.initializers) {
+        if (initializer is RedirectingInitializer) {
+          if (initializer.target.enclosingClass == clazz) {
+            // We need to handle this constructor first or the call to
+            // addDebugLocationArgument bellow will fail due to the named
+            // parameter not yet existing on the constructor.
+            handleConstructor(initializer.target);
+          }
+          _maybeAddCreationLocationArgument(
+            initializer.arguments,
+            initializer.target.function,
+            new VariableGet(variable),
+            _locationClass,
+          );
+          hasRedirectingInitializer = true;
+          break;
+        }
+      }
+      if (!hasRedirectingInitializer) {
+        constructor.initializers.add(new FieldInitializer(
+          locationField,
+          new VariableGet(variable),
+        ));
+        // TODO(jacobr): add an assert verifying the locationField is not
+        // null. Currently, we cannot safely add this assert because we do not
+        // handle Widget classes with optional positional arguments. There are
+        // no Widget classes in the flutter repo with optional positional
+        // arguments but it is possible users could add classes with optional
+        // positional arguments.
+        //
+        // constructor.initializers.add(new AssertInitializer(new AssertStatement(
+        //   new IsExpression(
+        //       new VariableGet(variable), _locationClass.thisType),
+        //   conditionStartOffset: constructor.fileOffset,
+        //   conditionEndOffset: constructor.fileOffset,
+        // )));
+      }
+    }
+
+    // Add named parameters to all constructors.
+    clazz.constructors.forEach(handleConstructor);
+  }
+
+  /// Transform the given [module].
+  void transform(Component module) {
+    final List<Library> libraries = module.libraries;
+
+    if (libraries.isEmpty) {
+      return;
+    }
+
+    _resolveFlutterClasses(libraries);
+
+    if (_widgetClass == null) {
+      // This application doesn't actually use the package:flutter library.
+      return;
+    }
+
+    final Set<Class> transformedClasses = new Set<Class>.identity();
+    final Set<Library> librariesToTransform = new Set<Library>.identity()
+      ..addAll(module.libraries);
+
+    for (Library library in module.libraries) {
+      if (library.isExternal) {
+        continue;
+      }
+      for (Class class_ in library.classes) {
+        _transformWidgetConstructors(
+          librariesToTransform,
+          transformedClasses,
+          class_,
+        );
+      }
+    }
+
+    // Transform call sites to pass the location parameter.
+    final _WidgetCallSiteTransformer callsiteTransformer =
+        new _WidgetCallSiteTransformer(
+      hierarchy,
+      widgetClass: _widgetClass,
+      locationClass: _locationClass,
+    );
+
+    for (Library library in module.libraries) {
+      if (library.isExternal) {
+        continue;
+      }
+      library.transformChildren(callsiteTransformer);
+    }
+  }
+
+  bool _isSubclassOfWidget(Class clazz) {
+    if (clazz == null) {
+      return false;
+    }
+    // TODO(jacobr): use hierarchy.isSubclassOf once we are using the
+    // non-deprecated ClassHierarchy constructor.
+    return hierarchy.isSubclassOf(clazz, _widgetClass);
+  }
+
+  void _transformWidgetConstructors(Set<Library> librariesToBeTransformed,
+      Set<Class> transformedClasses, Class clazz) {
+    if (!_isSubclassOfWidget(clazz) ||
+        !librariesToBeTransformed.contains(clazz.enclosingLibrary) ||
+        !transformedClasses.add(clazz)) {
+      return;
+    }
+
+    // Ensure super classes have been transformed before this class.
+    if (clazz.superclass != null &&
+        !transformedClasses.contains(clazz.superclass)) {
+      _transformWidgetConstructors(
+        librariesToBeTransformed,
+        transformedClasses,
+        clazz.superclass,
+      );
+    }
+
+    for (Procedure procedure in clazz.procedures) {
+      if (procedure.isFactory) {
+        _maybeAddNamedParameter(
+          procedure.function,
+          new VariableDeclaration(
+            _creationLocationParameterName,
+            type: _locationClass.thisType,
+          ),
+        );
+      }
+    }
+
+    // Handle the widget class and classes that implement but do not extend the
+    // widget class.
+    if (!_isSubclassOfWidget(clazz.superclass)) {
+      _transformClassImplementingWidget(clazz);
+      return;
+    }
+
+    final Set<Constructor> _handledConstructors =
+        new Set<Constructor>.identity();
+
+    void handleConstructor(Constructor constructor) {
+      if (!_handledConstructors.add(constructor)) {
+        return;
+      }
+
+      final VariableDeclaration variable = new VariableDeclaration(
+        _creationLocationParameterName,
+        type: _locationClass.thisType,
+      );
+      if (_hasNamedParameter(
+          constructor.function, _creationLocationParameterName)) {
+        // Constructor was already rewritten. TODO(jacobr): is this case actually hit?
+        return;
+      }
+      if (!_maybeAddNamedParameter(constructor.function, variable)) {
+        return;
+      }
+      for (Initializer initializer in constructor.initializers) {
+        if (initializer is RedirectingInitializer) {
+          if (initializer.target.enclosingClass == clazz) {
+            // We need to handle this constructor first or the call to
+            // addDebugLocationArgument could fail due to the named parameter
+            // not existing.
+            handleConstructor(initializer.target);
+          }
+
+          _maybeAddCreationLocationArgument(
+            initializer.arguments,
+            initializer.target.function,
+            new VariableGet(variable),
+            _locationClass,
+          );
+        } else if (initializer is SuperInitializer &&
+            _isSubclassOfWidget(initializer.target.enclosingClass)) {
+          _maybeAddCreationLocationArgument(
+            initializer.arguments,
+            initializer.target.function,
+            new VariableGet(variable),
+            _locationClass,
+          );
+        }
+      }
+    }
+
+    clazz.constructors.forEach(handleConstructor);
+  }
+}
diff --git a/pkg/dev_compiler/lib/src/js_ast/nodes.dart b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
index 6b78736..4b39d7e 100644
--- a/pkg/dev_compiler/lib/src/js_ast/nodes.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
@@ -1124,7 +1124,6 @@
 // it is for simplicity's sake.
 class Spread extends Prefix {
   Spread(Expression operand) : super('...', operand);
-  int get precedenceLevel => SPREAD;
 
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitSpread(this);
   Spread _clone() => Spread(argument);
diff --git a/pkg/dev_compiler/lib/src/js_ast/precedence.dart b/pkg/dev_compiler/lib/src/js_ast/precedence.dart
index b10bac6..f149dc2 100644
--- a/pkg/dev_compiler/lib/src/js_ast/precedence.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/precedence.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 const EXPRESSION = 0;
+// TODO(nshahan) No longer used for the spread operator.
+// All precedence levels need to be updated to be more accurate.
 const SPREAD = EXPRESSION + 1;
 const YIELD = SPREAD + 1;
 
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index b3852c9..e7a764c 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -9,6 +9,7 @@
 import 'package:args/args.dart';
 import 'package:build_integration/file_system/multi_root.dart';
 import 'package:cli_util/cli_util.dart' show getSdkPath;
+import 'package:dev_compiler/src/flutter/track_widget_constructor_locations.dart';
 import 'package:front_end/src/api_unstable/ddc.dart' as fe;
 import 'package:kernel/kernel.dart' hide MapEntry;
 import 'package:kernel/text/ast_to_text.dart' as kernel show Printer;
@@ -72,6 +73,8 @@
         help: 'emit API summary in a .js.txt file',
         defaultsTo: false,
         hide: true)
+    ..addFlag('track-widget-creation',
+        help: 'enable inspecting of Flutter widgets', hide: true)
     // TODO(jmesserly): add verbose help to show hidden options
     ..addOption('dart-sdk-summary',
         help: 'The path to the Dart SDK summary file.', hide: true)
@@ -252,8 +255,16 @@
     outFiles.add(File(output + '.txt').writeAsString(sb.toString()));
   }
   var target = compilerState.options.target as DevCompilerTarget;
+  var hierarchy = target.hierarchy;
+
+  // TODO(jmesserly): remove this hack once Flutter SDK has a `dartdevc` with
+  // support for the widget inspector.
+  if (argResults['track-widget-creation'] as bool) {
+    WidgetCreatorTracker(hierarchy).transform(component);
+  }
+
   var compiler =
-      ProgramCompiler(component, target.hierarchy, options, declaredVariables);
+      ProgramCompiler(component, hierarchy, options, declaredVariables);
 
   var jsModule = compiler.emitModule(component, result.inputSummaries,
       compilerState.options.inputSummaries, summaryModules);
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 6c5ccc6..a2cba73 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -4775,6 +4775,24 @@
   }
 
   @override
+  visitListConcatenation(ListConcatenation node) {
+    // Only occurs inside unevaluated constants.
+    throw new UnsupportedError("List concatenation");
+  }
+
+  @override
+  visitSetConcatenation(SetConcatenation node) {
+    // Only occurs inside unevaluated constants.
+    throw new UnsupportedError("Set concatenation");
+  }
+
+  @override
+  visitMapConcatenation(MapConcatenation node) {
+    // Only occurs inside unevaluated constants.
+    throw new UnsupportedError("Map concatenation");
+  }
+
+  @override
   visitIsExpression(IsExpression node) {
     return _emitIsExpression(node.operand, node.type);
   }
@@ -5038,7 +5056,25 @@
 
   @override
   visitBlockExpression(BlockExpression node) {
-    throw UnimplementedError('ProgramCompiler.visitBlockExpression');
+    var jsExpr = _visitExpression(node.value);
+    List<JS.Statement> jsStmts = node.body.statements
+        .map(_visitStatement)
+        .toList()
+          ..add(JS.Return(jsExpr));
+    var jsBlock = JS.Block(jsStmts);
+    // BlockExpressions with async operations must be constructed
+    // with a generator instead of a lambda.
+    var finder = YieldFinder();
+    jsBlock.accept(finder);
+    if (finder.hasYield) {
+      var genFn = JS.Fun([], jsBlock, isGenerator: true);
+      var asyncLibrary = emitLibraryName(coreTypes.asyncLibrary);
+      var returnType = _emitType(node.getStaticType(types));
+      var asyncCall =
+          js.call('#.async(#, #)', [asyncLibrary, returnType, genFn]);
+      return JS.Yield(asyncCall);
+    }
+    return JS.Call(JS.ArrowFun([], jsBlock), []);
   }
 
   @override
@@ -5144,9 +5180,12 @@
   }
 
   @override
-  visitListConstant(node) {
-    return _cacheConst(() => _emitConstList(
-        node.typeArgument, node.entries.map(visitConstant).toList()));
+  visitListConstant(node) => visitConstantList(node.typeArgument, node.entries);
+
+  /// Visits [Constant] with [_visitConstant].
+  visitConstantList(DartType typeArgument, List<Constant> entries) {
+    return _cacheConst(() =>
+        _emitConstList(typeArgument, entries.map(visitConstant).toList()));
   }
 
   @override
@@ -5154,7 +5193,10 @@
     // Set literals are currently desugared in the frontend.
     // Implement this method before flipping the supportsSetLiterals flag
     // in DevCompilerTarget to true.
-    throw "Set literal constants not supported.";
+    return _cacheConst(() => runtimeCall('constSet(#, #)', [
+          _emitType(node.typeArgument),
+          visitConstantList(node.typeArgument, node.entries)
+        ]));
   }
 
   @override
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index 1227ed7..db69224 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -69,6 +69,9 @@
   bool get errorOnUnexactWebIntLiterals => true;
 
   @override
+  bool get supportsSetLiterals => true;
+
+  @override
   bool get enableNoSuchMethodForwarders => true;
 
   @override
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
index 9027893..368d5e7 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
@@ -2634,7 +2634,9 @@
     var resultBits = Uint8List(8);
 
     var length = _digitBits * (_used - 1) + _digits[_used - 1].bitLength;
-    if (length - 53 > maxDoubleExponent) return double.infinity;
+    if (length > maxDoubleExponent + 53) {
+      return _isNegative ? double.negativeInfinity : double.infinity;
+    }
 
     // The most significant bit is for the sign.
     if (_isNegative) resultBits[7] = 0x80;
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/math_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/math_patch.dart
index 1e2c7dd..869c705 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/math_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/math_patch.dart
@@ -67,14 +67,14 @@
 
 @patch
 class Random {
-  static final _secureRandom = _JSSecureRandom();
+  static Random _secureRandom;
 
   @patch
   factory Random([int seed]) =>
       (seed == null) ? const _JSRandom() : _Random(seed);
 
   @patch
-  factory Random.secure() => _secureRandom;
+  factory Random.secure() => _secureRandom ??= _JSSecureRandom();
 }
 
 class _JSRandom implements Random {
diff --git a/pkg/dev_compiler/tool/input_sdk/private/string_helper.dart b/pkg/dev_compiler/tool/input_sdk/private/string_helper.dart
index 41a51d6..aeb4e2f 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/string_helper.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/string_helper.dart
@@ -162,9 +162,7 @@
         return result.toString();
       }
     } else {
-      var quoted = quoteStringForRegExp(pattern);
-      var replacer = JS('', "new RegExp(#, 'g')", quoted);
-      return stringReplaceJS(receiver, replacer, replacement);
+      return JS('String', '#.split(#).join(#)', receiver, pattern, replacement);
     }
   } else if (pattern is JSSyntaxRegExp) {
     var re = regExpGetGlobalNative(pattern);
diff --git a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
index 9ff093c..ce04a71 100644
--- a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
@@ -19,11 +19,12 @@
 
 abstract class IncrementalKernelGenerator {
   factory IncrementalKernelGenerator(CompilerOptions options, Uri entryPoint,
-      [Uri initializeFromDillUri]) {
+      [Uri initializeFromDillUri, bool outlineOnly]) {
     return new IncrementalCompiler(
         new CompilerContext(
             new ProcessedOptions(options: options, inputs: [entryPoint])),
-        initializeFromDillUri);
+        initializeFromDillUri,
+        outlineOnly);
   }
 
   /// Initialize the incremental compiler from a component.
@@ -31,11 +32,13 @@
   /// Notice that the component has to include the platform, and that no other
   /// platform will be loaded.
   factory IncrementalKernelGenerator.fromComponent(
-      CompilerOptions options, Uri entryPoint, Component component) {
+      CompilerOptions options, Uri entryPoint, Component component,
+      [bool outlineOnly]) {
     return new IncrementalCompiler.fromComponent(
         new CompilerContext(
             new ProcessedOptions(options: options, inputs: [entryPoint])),
-        component);
+        component,
+        outlineOnly);
   }
 
   /// Returns a component whose libraries are the recompiled libraries,
@@ -47,6 +50,26 @@
   /// next call to [computeDelta]).
   void invalidate(Uri uri);
 
+  /// Invalidate all libraries that were build from source.
+  ///
+  /// This is equivalent to a number of calls to [invalidate]: One for each URI
+  /// that happens to have been read from source.
+  /// Said another way, this invalidates everything not loaded from dill
+  /// (at startup) or via [setModulesToLoadOnNextComputeDelta].
+  void invalidateAllSources();
+
+  /// Set the given [components] as components to load on the next iteration
+  /// of [computeDelta].
+  ///
+  /// If specified, all libraries not compiled from source and not included in
+  /// these components will be invalidated and the libraries inside these
+  /// components will be loaded instead.
+  ///
+  /// Useful for, for instance, modular compilation, where modules
+  /// (created externally) via this functionality can be added, changed or
+  /// removed.
+  void setModulesToLoadOnNextComputeDelta(List<Component> components);
+
   /// Compile [expression] as an [Expression]. A function returning that
   /// expression is compiled.
   ///
diff --git a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
index 6196ba7..5555840 100644
--- a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
+++ b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
@@ -37,6 +37,7 @@
 Future<InitializedCompilerState> initializeCompiler(
     InitializedCompilerState oldState,
     Uri sdkSummary,
+    Uri librariesSpecificationUri,
     Uri packagesFile,
     List<Uri> summaryInputs,
     List<Uri> linkedInputs,
@@ -50,6 +51,7 @@
   CompilerOptions options = new CompilerOptions()
     ..sdkSummary = sdkSummary
     ..packagesFileUri = packagesFile
+    ..librariesSpecificationUri = librariesSpecificationUri
     ..inputSummaries = summaryInputs
     ..linkedDependencies = linkedInputs
     ..target = target
diff --git a/pkg/front_end/lib/src/fasta/builder/declaration.dart b/pkg/front_end/lib/src/fasta/builder/declaration.dart
index 1584102..392b3e6 100644
--- a/pkg/front_end/lib/src/fasta/builder/declaration.dart
+++ b/pkg/front_end/lib/src/fasta/builder/declaration.dart
@@ -64,6 +64,10 @@
 
   bool get isNamedMixinApplication => false;
 
+  bool get isAnonymousMixinApplication {
+    return isMixinApplication && !isNamedMixinApplication;
+  }
+
   /// Applies [patch] to this declaration.
   void applyPatch(Declaration patch) {
     unsupported("${runtimeType}.applyPatch", charOffset, fileUri);
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 37cff6c..574152c 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -520,6 +520,28 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCantDisambiguateAmbiguousInformation =
+    messageCantDisambiguateAmbiguousInformation;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCantDisambiguateAmbiguousInformation = const MessageCode(
+    "CantDisambiguateAmbiguousInformation",
+    message:
+        r"""Both Iterable and Map spread elements encountered in ambiguous literal.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCantDisambiguateNotEnoughInformation =
+    messageCantDisambiguateNotEnoughInformation;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCantDisambiguateNotEnoughInformation = const MessageCode(
+    "CantDisambiguateNotEnoughInformation",
+    message:
+        r"""Not enough type information to disambiguate between literal set and literal map.""",
+    tip:
+        r"""Try providing type arguments for the literal explicitly to disambiguate it.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeCantInferPackagesFromManyInputs =
     messageCantInferPackagesFromManyInputs;
 
@@ -568,30 +590,31 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)>
+const Template<Message Function(String name)>
     templateCantInferTypeDueToInconsistentOverrides =
-    const Template<Message Function(String string)>(
+    const Template<Message Function(String name)>(
         messageTemplate:
-            r"""Can't infer the type of '#string': overridden members must all have the same type.""",
-        tipTemplate: r"""Specify the type explicitly.""",
+            r"""Can't infer a type for '#name' as some of the inherited members have different types.""",
+        tipTemplate: r"""Try adding an explicit type.""",
         withArguments: _withArgumentsCantInferTypeDueToInconsistentOverrides);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string)>
+const Code<Message Function(String name)>
     codeCantInferTypeDueToInconsistentOverrides =
-    const Code<Message Function(String string)>(
+    const Code<Message Function(String name)>(
         "CantInferTypeDueToInconsistentOverrides",
         templateCantInferTypeDueToInconsistentOverrides,
         analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsCantInferTypeDueToInconsistentOverrides(String string) {
-  if (string.isEmpty) throw 'No string provided';
+Message _withArgumentsCantInferTypeDueToInconsistentOverrides(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
   return new Message(codeCantInferTypeDueToInconsistentOverrides,
       message:
-          """Can't infer the type of '${string}': overridden members must all have the same type.""",
-      tip: """Specify the type explicitly.""",
-      arguments: {'string': string});
+          """Can't infer a type for '${name}' as some of the inherited members have different types.""",
+      tip: """Try adding an explicit type.""",
+      arguments: {'name': name});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2781,6 +2804,15 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExpectedElseOrComma = messageExpectedElseOrComma;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExpectedElseOrComma = const MessageCode(
+    "ExpectedElseOrComma",
+    index: 94,
+    message: r"""Expected 'else' or comma.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(Token token)> templateExpectedEnumBody = const Template<
         Message Function(Token token)>(
@@ -3297,7 +3329,10 @@
 
   -Dname
   -Dname=value
-    Ignored for now.
+    Define an environment variable in the compile-time environment.
+
+  --no-defines
+    Ignore all -D options and leave environment constants unevaluated.
 
   --
     Stop option parsing, the rest of the command line is assumed to be
@@ -6890,6 +6925,14 @@
     message: r"""Can only use type variables in instance methods.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNonNullAwareSpreadIsNull = messageNonNullAwareSpreadIsNull;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNonNullAwareSpreadIsNull = const MessageCode(
+    "NonNullAwareSpreadIsNull",
+    message: r"""Can't spread a value with static type Null.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeNonPartOfDirectiveInPart = messageNonPartOfDirectiveInPart;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7342,29 +7385,35 @@
         String name,
         String name2,
         DartType _type,
-        DartType
-            _type2)> templateOverrideTypeMismatchParameter = const Template<
-        Message Function(String name, String name2, DartType _type,
-            DartType _type2)>(
+        DartType _type2,
+        String
+            name3)> templateOverrideTypeMismatchParameter = const Template<
+        Message Function(
+            String name,
+            String name2,
+            DartType _type,
+            DartType _type2,
+            String
+                name3)>(
     messageTemplate:
-        r"""The parameter '#name' of the method '#name2' has type '#type', which does not match the corresponding type in the overridden method, '#type2'.""",
+        r"""The parameter '#name' of the method '#name2' has type '#type', which does not match the corresponding type, '#type2', in the overridden method, '#name3'.""",
     tipTemplate:
         r"""Change to a supertype of '#type2', or, for a covariant parameter, a subtype.""",
     withArguments: _withArgumentsOverrideTypeMismatchParameter);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<
-        Message Function(
-            String name, String name2, DartType _type, DartType _type2)>
-    codeOverrideTypeMismatchParameter = const Code<
-            Message Function(
-                String name, String name2, DartType _type, DartType _type2)>(
+        Message Function(String name, String name2, DartType _type,
+            DartType _type2, String name3)> codeOverrideTypeMismatchParameter =
+    const Code<
+            Message Function(String name, String name2, DartType _type,
+                DartType _type2, String name3)>(
         "OverrideTypeMismatchParameter", templateOverrideTypeMismatchParameter,
         analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsOverrideTypeMismatchParameter(
-    String name, String name2, DartType _type, DartType _type2) {
+    String name, String name2, DartType _type, DartType _type2, String name3) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
   if (name2.isEmpty) throw 'No name provided';
@@ -7372,18 +7421,21 @@
   TypeLabeler labeler = new TypeLabeler();
   List<Object> typeParts = labeler.labelType(_type);
   List<Object> type2Parts = labeler.labelType(_type2);
+  if (name3.isEmpty) throw 'No name provided';
+  name3 = demangleMixinApplicationName(name3);
   String type = typeParts.join();
   String type2 = type2Parts.join();
   return new Message(codeOverrideTypeMismatchParameter,
       message:
-          """The parameter '${name}' of the method '${name2}' has type '${type}', which does not match the corresponding type in the overridden method, '${type2}'.""" +
+          """The parameter '${name}' of the method '${name2}' has type '${type}', which does not match the corresponding type, '${type2}', in the overridden method, '${name3}'.""" +
               labeler.originMessages,
       tip: """Change to a supertype of '${type2}', or, for a covariant parameter, a subtype.""",
       arguments: {
         'name': name,
         'name2': name2,
         'type': _type,
-        'type2': _type2
+        'type2': _type2,
+        'name3': name3
       });
 }
 
@@ -7392,38 +7444,50 @@
     Message Function(
         String name,
         DartType _type,
-        DartType
-            _type2)> templateOverrideTypeMismatchReturnType = const Template<
-        Message Function(String name, DartType _type, DartType _type2)>(
+        DartType _type2,
+        String
+            name2)> templateOverrideTypeMismatchReturnType = const Template<
+        Message Function(
+            String name, DartType _type, DartType _type2, String name2)>(
     messageTemplate:
-        r"""The return type of the method '#name' is '#type', which does not match the return type of the overridden method, '#type2'.""",
+        r"""The return type of the method '#name' is '#type', which does not match the return type, '#type2', of the overridden method, '#name2'.""",
     tipTemplate: r"""Change to a subtype of '#type2'.""",
     withArguments: _withArgumentsOverrideTypeMismatchReturnType);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, DartType _type, DartType _type2)>
-    codeOverrideTypeMismatchReturnType =
-    const Code<Message Function(String name, DartType _type, DartType _type2)>(
+const Code<
+        Message Function(
+            String name, DartType _type, DartType _type2, String name2)>
+    codeOverrideTypeMismatchReturnType = const Code<
+            Message Function(
+                String name, DartType _type, DartType _type2, String name2)>(
         "OverrideTypeMismatchReturnType",
         templateOverrideTypeMismatchReturnType,
         analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsOverrideTypeMismatchReturnType(
-    String name, DartType _type, DartType _type2) {
+    String name, DartType _type, DartType _type2, String name2) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
   TypeLabeler labeler = new TypeLabeler();
   List<Object> typeParts = labeler.labelType(_type);
   List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
   String type = typeParts.join();
   String type2 = type2Parts.join();
   return new Message(codeOverrideTypeMismatchReturnType,
       message:
-          """The return type of the method '${name}' is '${type}', which does not match the return type of the overridden method, '${type2}'.""" +
+          """The return type of the method '${name}' is '${type}', which does not match the return type, '${type2}', of the overridden method, '${name2}'.""" +
               labeler.originMessages,
       tip: """Change to a subtype of '${type2}'.""",
-      arguments: {'name': name, 'type': _type, 'type2': _type2});
+      arguments: {
+        'name': name,
+        'type': _type,
+        'type2': _type2,
+        'name2': name2
+      });
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -8225,6 +8289,13 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSpreadElement = messageSpreadElement;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSpreadElement = const MessageCode("SpreadElement",
+    severity: Severity.context, message: r"""Iterable spread.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
         DartType _type,
@@ -8258,6 +8329,109 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSpreadMapElement = messageSpreadMapElement;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSpreadMapElement = const MessageCode(
+    "SpreadMapElement",
+    severity: Severity.context,
+    message: r"""Map spread.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateSpreadMapEntryElementKeyTypeMismatch = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""Can't assign spread entry keys of type '#type' to map entry keys of type '#type2'.""",
+    withArguments: _withArgumentsSpreadMapEntryElementKeyTypeMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeSpreadMapEntryElementKeyTypeMismatch =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "SpreadMapEntryElementKeyTypeMismatch",
+        templateSpreadMapEntryElementKeyTypeMismatch,
+        analyzerCodes: <String>["MAP_KEY_TYPE_NOT_ASSIGNABLE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSpreadMapEntryElementKeyTypeMismatch(
+    DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeSpreadMapEntryElementKeyTypeMismatch,
+      message:
+          """Can't assign spread entry keys of type '${type}' to map entry keys of type '${type2}'.""" +
+              labeler.originMessages,
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(DartType _type, DartType _type2)>
+    templateSpreadMapEntryElementValueTypeMismatch =
+    const Template<Message Function(DartType _type, DartType _type2)>(
+        messageTemplate:
+            r"""Can't assign spread entry values of type '#type' to map entry values of type '#type2'.""",
+        withArguments: _withArgumentsSpreadMapEntryElementValueTypeMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeSpreadMapEntryElementValueTypeMismatch =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "SpreadMapEntryElementValueTypeMismatch",
+        templateSpreadMapEntryElementValueTypeMismatch,
+        analyzerCodes: <String>["MAP_VALUE_TYPE_NOT_ASSIGNABLE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSpreadMapEntryElementValueTypeMismatch(
+    DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeSpreadMapEntryElementValueTypeMismatch,
+      message:
+          """Can't assign spread entry values of type '${type}' to map entry values of type '${type2}'.""" +
+              labeler.originMessages,
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType
+            _type)> templateSpreadMapEntryTypeMismatch = const Template<
+        Message Function(DartType _type)>(
+    messageTemplate:
+        r"""Unexpected type '#type' of a map spread entry.  Expected 'dynamic' or a Map.""",
+    withArguments: _withArgumentsSpreadMapEntryTypeMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type)> codeSpreadMapEntryTypeMismatch =
+    const Code<Message Function(DartType _type)>(
+  "SpreadMapEntryTypeMismatch",
+  templateSpreadMapEntryTypeMismatch,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSpreadMapEntryTypeMismatch(DartType _type) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  String type = typeParts.join();
+  return new Message(codeSpreadMapEntryTypeMismatch,
+      message:
+          """Unexpected type '${type}' of a map spread entry.  Expected 'dynamic' or a Map.""" +
+              labeler.originMessages,
+      arguments: {'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
         DartType
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index a8245b2..e938d69 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -84,6 +84,8 @@
 
   final Ticker ticker;
 
+  final bool outlineOnly;
+
   Set<Uri> invalidatedUris = new Set<Uri>();
 
   DillTarget dillLoadedData;
@@ -96,17 +98,25 @@
   bool hasToCheckPackageUris = false;
   Map<Uri, List<DiagnosticMessageFromJson>> remainingComponentProblems =
       new Map<Uri, List<DiagnosticMessageFromJson>>();
+  List<Component> modulesToLoad;
+
+  static final Uri debugExprUri =
+      new Uri(scheme: "org-dartlang-debug", path: "synthetic_debug_expression");
 
   KernelTarget userCode;
 
   IncrementalCompiler.fromComponent(
-      this.context, Component this.componentToInitializeFrom)
+      this.context, Component this.componentToInitializeFrom,
+      [bool outlineOnly])
       : ticker = context.options.ticker,
-        initializeFromDillUri = null;
+        initializeFromDillUri = null,
+        this.outlineOnly = outlineOnly ?? false;
 
-  IncrementalCompiler(this.context, [this.initializeFromDillUri])
+  IncrementalCompiler(this.context,
+      [this.initializeFromDillUri, bool outlineOnly])
       : ticker = context.options.ticker,
-        componentToInitializeFrom = null;
+        componentToInitializeFrom = null,
+        this.outlineOnly = outlineOnly ?? false;
 
   @override
   Future<Component> computeDelta(
@@ -315,22 +325,39 @@
     });
   }
 
+  /// Internal method.
+  void invalidateNotKeptUserBuilders(Set<Uri> invalidatedUris) {
+    throw UnimplementedError("Not implemented yet.");
+  }
+
+  /// Internal method.
+  Future loadEnsureLoadedComponents(
+      Set<Uri> reusedLibraryUris, List<LibraryBuilder> reusedLibraries) async {
+    throw UnimplementedError("Not implemented yet.");
+  }
+
+  /// Internal method.
   void reissueLibraryProblems(
       Set<Library> allLibraries, List<Library> compiledLibraries) {
     // The newly-compiled libraries have issued problems already. Re-issue
-    // problems for the libraries that weren't re-compiled.
+    // problems for the libraries that weren't re-compiled (ignore compile
+    // expression problems)
     allLibraries.removeAll(compiledLibraries);
     for (Library library in allLibraries) {
       if (library.problemsAsJson?.isNotEmpty == true) {
         for (String jsonString in library.problemsAsJson) {
           DiagnosticMessageFromJson message =
               new DiagnosticMessageFromJson.fromJson(jsonString);
+          if (message.uri == debugExprUri) {
+            continue;
+          }
           context.options.reportDiagnosticMessage(message);
         }
       }
     }
   }
 
+  /// Internal method.
   /// Re-issue problems on the component and return the filtered list.
   List<String> reissueComponentProblems(Component componentWithDill) {
     // These problems have already been reported.
@@ -364,6 +391,7 @@
     return new List<String>.from(issuedProblems);
   }
 
+  /// Internal method.
   Uri getPartFileUri(
       Uri parentFileUri, LibraryPart part, UriTranslator uriTranslator) {
     Uri fileUri = parentFileUri.resolve(part.partUri);
@@ -376,6 +404,7 @@
     return fileUri;
   }
 
+  /// Internal method.
   /// Compute the transitive closure.
   ///
   /// As a side-effect, this also cleans-up now-unreferenced builders as well as
@@ -448,6 +477,7 @@
     return result;
   }
 
+  /// Internal method.
   void removeLibraryFromRemainingComponentProblems(
       Library lib, UriTranslator uriTranslator) {
     remainingComponentProblems.remove(lib.fileUri);
@@ -458,6 +488,7 @@
     }
   }
 
+  /// Internal method.
   int prepareSummary(List<int> summaryBytes, UriTranslator uriTranslator,
       CompilerContext c, IncrementalCompilerData data) {
     dillLoadedData = new DillTarget(ticker, uriTranslator, c.options.target);
@@ -475,6 +506,7 @@
     return bytesLength;
   }
 
+  /// Internal method.
   // This procedure will try to load the dill file and will crash if it cannot.
   Future<int> initializeFromDill(UriTranslator uriTranslator, CompilerContext c,
       IncrementalCompilerData data) async {
@@ -515,6 +547,7 @@
     return bytesLength;
   }
 
+  /// Internal method.
   void saveComponentProblems(IncrementalCompilerData data) {
     if (data.component.problemsAsJson != null) {
       for (String jsonString in data.component.problemsAsJson) {
@@ -528,6 +561,7 @@
     }
   }
 
+  /// Internal method.
   // This procedure will set up compiler from [componentToInitializeFrom].
   void initializeFromComponent(UriTranslator uriTranslator, CompilerContext c,
       IncrementalCompilerData data) {
@@ -559,6 +593,7 @@
     ticker.logMs("Ran initializeFromComponent");
   }
 
+  /// Internal method.
   void appendLibraries(IncrementalCompilerData data, int bytesLength) {
     if (data.component != null) {
       dillLoadedData.loader
@@ -597,9 +632,6 @@
         if (!isLegalIdentifier(name)) return null;
       }
 
-      Uri debugExprUri = new Uri(
-          scheme: "org-dartlang-debug", path: "synthetic_debug_expression");
-
       KernelLibraryBuilder debugLibrary = new KernelLibraryBuilder(
           libraryUri,
           debugExprUri,
@@ -673,6 +705,7 @@
     });
   }
 
+  /// Internal method.
   List<LibraryBuilder> computeReusedLibraries(
       Set<Uri> invalidatedUris, UriTranslator uriTranslator,
       {Set<LibraryBuilder> notReused}) {
@@ -796,7 +829,20 @@
     invalidatedUris.add(uri);
   }
 
+  @override
+  void invalidateAllSources() {
+    throw UnimplementedError("Not implemented yet.");
+  }
+
+  @override
+  void setModulesToLoadOnNextComputeDelta(List<Component> components) {
+    throw UnimplementedError("Not implemented yet.");
+  }
+
+  /// Internal method.
   void recordInvalidatedImportUrisForTesting(List<Uri> uris) {}
+
+  /// Internal method.
   void recordTemporaryFileForTesting(Uri uri) {}
 }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 123e9f2..7655108 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -2554,7 +2554,7 @@
         if (entry is MapEntry) {
           entries.add(entry);
         } else if (entry is SpreadElement) {
-          entries.add(new SpreadMapEntry(entry.expression));
+          entries.add(new SpreadMapEntry(entry.expression, entry.isNullAware));
         } else {
           addProblem(
             fasta.templateExpectedAfterButGot.withArguments(':'),
@@ -3655,13 +3655,10 @@
   @override
   void endIfControlFlow(Token token) {
     debugEvent("endIfControlFlow");
-    // TODO(danrubel) implement control flow support
-
     var entry = pop();
-    pop(); // parenthesized expression
+    var condition = pop(); // parenthesized expression
     Token ifToken = pop();
-    if (entry != invalidCollectionElement) {
-      // TODO(danrubel): Replace this with control flow structure
+    if (!library.loader.target.enableControlFlowCollections) {
       // TODO(danrubel): Report a more user friendly error message
       // when an experiment is not enabled
       handleRecoverableError(
@@ -3669,24 +3666,28 @@
           ifToken,
           ifToken);
       push(invalidCollectionElement);
-    } else {
-      // TODO(danrubel): Remove this when unified collections enabled
+      return;
+    }
+    if (entry == invalidCollectionElement) {
       push(invalidCollectionElement);
+      return;
+    }
+    transformCollections = true;
+    if (entry is MapEntry) {
+      push(forest.ifMapEntry(toValue(condition), entry, null, ifToken));
+    } else {
+      push(forest.ifElement(toValue(condition), toValue(entry), null, ifToken));
     }
   }
 
   @override
   void endIfElseControlFlow(Token token) {
     debugEvent("endIfElseControlFlow");
-    // TODO(danrubel) implement control flow support
-
     var elseEntry = pop(); // else entry
     var thenEntry = pop(); // then entry
-    pop(); // parenthesized expression
+    var condition = pop(); // parenthesized expression
     Token ifToken = pop();
-    if (thenEntry != invalidCollectionElement &&
-        elseEntry != invalidCollectionElement) {
-      // TODO(danrubel): Replace this with control flow support
+    if (!library.loader.target.enableControlFlowCollections) {
       // TODO(danrubel): Report a more user friendly error message
       // when an experiment is not enabled
       handleRecoverableError(
@@ -3694,23 +3695,57 @@
           ifToken,
           ifToken);
       push(invalidCollectionElement);
-    } else {
-      // TODO(danrubel): Remove when unified collections enabled
+      return;
+    }
+    if (thenEntry == invalidCollectionElement ||
+        elseEntry == invalidCollectionElement) {
       push(invalidCollectionElement);
+      return;
+    }
+    transformCollections = true;
+    if (thenEntry is MapEntry) {
+      if (elseEntry is MapEntry) {
+        push(forest.ifMapEntry(
+            toValue(condition), thenEntry, elseEntry, ifToken));
+      } else if (elseEntry is SpreadElement) {
+        push(forest.ifMapEntry(
+            toValue(condition),
+            thenEntry,
+            new SpreadMapEntry(elseEntry.expression, elseEntry.isNullAware),
+            ifToken));
+      } else {
+        push(invalidCollectionElement);
+      }
+    } else if (elseEntry is MapEntry) {
+      if (thenEntry is SpreadElement) {
+        push(forest.ifMapEntry(
+            toValue(condition),
+            new SpreadMapEntry(thenEntry.expression, thenEntry.isNullAware),
+            elseEntry,
+            ifToken));
+      } else {
+        push(invalidCollectionElement);
+      }
+    } else {
+      push(forest.ifElement(
+          toValue(condition), toValue(thenEntry), toValue(elseEntry), ifToken));
     }
   }
 
   @override
   void handleSpreadExpression(Token spreadToken) {
     debugEvent("SpreadExpression");
+    var expression = pop();
     if (!library.loader.target.enableSpreadCollections) {
-      return handleRecoverableError(
+      handleRecoverableError(
           fasta.templateUnexpectedToken.withArguments(spreadToken),
           spreadToken,
           spreadToken);
+      push(invalidCollectionElement);
+      return;
     }
     transformCollections = true;
-    push(forest.spreadElement(popForValue(), spreadToken));
+    push(forest.spreadElement(toValue(expression), spreadToken));
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/kernel/collections.dart b/pkg/front_end/lib/src/fasta/kernel/collections.dart
index b830d4b..74f6789 100644
--- a/pkg/front_end/lib/src/fasta/kernel/collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/collections.dart
@@ -204,11 +204,14 @@
 /// A spread element in a map literal.
 class SpreadMapEntry extends TreeNode with _FakeMapEntryMixin {
   Expression expression;
+  bool isNullAware;
 
-  SpreadMapEntry(this.expression) {
+  SpreadMapEntry(this.expression, this.isNullAware) {
     expression?.parent = this;
   }
 
+  accept(TreeVisitor<Object> v) => v.defaultTreeNode(this);
+
   @override
   visitChildren(Visitor<Object> v) {
     expression?.accept(v);
diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
index eee9401..005376d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
@@ -53,7 +53,7 @@
 
 import 'body_builder.dart' show LabelTarget;
 
-import 'collections.dart' show SpreadElement;
+import 'collections.dart' show IfElement, IfMapEntry, SpreadElement;
 
 import 'kernel_expression_generator.dart'
     show
@@ -283,6 +283,20 @@
   }
 
   @override
+  Expression ifElement(Expression condition, Expression then,
+      Expression otherwise, Token token) {
+    return new IfElement(condition, then, otherwise)
+      ..fileOffset = offsetForToken(token);
+  }
+
+  @override
+  MapEntry ifMapEntry(
+      Expression condition, MapEntry then, MapEntry otherwise, Token token) {
+    return new IfMapEntry(condition, then, otherwise)
+      ..fileOffset = offsetForToken(token);
+  }
+
+  @override
   AssertInitializer assertInitializer(
       Token assertKeyword,
       Token leftParenthesis,
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index e024458..8cf916f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -190,6 +190,12 @@
 
   Expression spreadElement(Expression expression, Token token);
 
+  Expression ifElement(
+      Expression condition, Expression then, Expression otherwise, Token token);
+
+  MapEntry ifMapEntry(
+      Expression condition, MapEntry then, MapEntry otherwise, Token token);
+
   /// Return a representation of an assert that appears in a constructor's
   /// initializer list.
   Object assertInitializer(Token assertKeyword, Token leftParenthesis,
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index d108638..a678e10 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -11,6 +11,10 @@
 
   @override
   void defaultExpression(Expression node, DartType typeContext) {
+    if (node is IfElement) {
+      visitIfElement(node, typeContext);
+      return;
+    }
     unhandled("${node.runtimeType}", "InferenceVisitor", node.fileOffset,
         inferrer.helper.uri);
   }
@@ -21,6 +25,11 @@
         inferrer.helper.uri);
   }
 
+  visitIfElement(IfElement node, DartType typeContext) {
+    node.parent.replaceChild(node,
+        new InvalidExpression('unhandled if element in collection literal'));
+  }
+
   @override
   void visitInvalidExpression(InvalidExpression node, DartType typeContext) {}
 
@@ -165,11 +174,13 @@
         node.arguments,
         isConst: node.isConst);
     inferrer.storeInferredType(node, inferenceResult.type);
-    KernelLibraryBuilder inferrerLibrary = inferrer.library;
-    if (!hasExplicitTypeArguments && inferrerLibrary is KernelLibraryBuilder) {
-      inferrerLibrary.checkBoundsInConstructorInvocation(
-          node, inferrer.typeSchemaEnvironment,
-          inferred: true);
+    if (!inferrer.isTopLevel) {
+      KernelLibraryBuilder library = inferrer.library;
+      if (!hasExplicitTypeArguments) {
+        library.checkBoundsInConstructorInvocation(
+            node, inferrer.typeSchemaEnvironment,
+            inferred: true);
+      }
     }
   }
 
@@ -224,11 +235,13 @@
         node.argumentJudgments,
         isConst: node.isConst);
     node.inferredType = inferenceResult.type;
-    KernelLibraryBuilder inferrerLibrary = inferrer.library;
-    if (!hadExplicitTypeArguments && inferrerLibrary is KernelLibraryBuilder) {
-      inferrerLibrary.checkBoundsInFactoryInvocation(
-          node, inferrer.typeSchemaEnvironment,
-          inferred: true);
+    if (!inferrer.isTopLevel) {
+      KernelLibraryBuilder library = inferrer.library;
+      if (!hadExplicitTypeArguments) {
+        library.checkBoundsInFactoryInvocation(
+            node, inferrer.typeSchemaEnvironment,
+            inferred: true);
+      }
     }
     return null;
   }
@@ -638,12 +651,15 @@
     inferrer.inferStatement(node.body);
   }
 
-  DartType getSpreadElementType(DartType spreadType) {
+  DartType getSpreadElementType(DartType spreadType, bool isNullAware) {
     if (spreadType is InterfaceType) {
       InterfaceType supertype = inferrer.typeSchemaEnvironment
           .getTypeAsInstanceOf(spreadType, inferrer.coreTypes.iterableClass);
-      if (supertype == null) return null;
-      return supertype.typeArguments[0];
+      if (supertype != null) return supertype.typeArguments[0];
+      if (spreadType.classNode == inferrer.coreTypes.nullClass && isNullAware) {
+        return spreadType;
+      }
+      return null;
     }
     if (spreadType is DynamicType) return const DynamicType();
     return null;
@@ -691,8 +707,9 @@
             spreadTypes[i] = spreadType;
           }
           // Use 'dynamic' for error recovery.
-          actualTypes
-              .add(getSpreadElementType(spreadType) ?? const DynamicType());
+          actualTypes.add(
+              getSpreadElementType(spreadType, judgment.isNullAware) ??
+                  const DynamicType());
         } else {
           inferrer.inferExpression(judgment, inferredTypeArgument,
               inferenceNeeded || typeChecksNeeded,
@@ -725,34 +742,39 @@
         Expression item = node.expressions[i];
         if (item is SpreadElement) {
           DartType spreadType = spreadTypes[i];
-          DartType spreadElementType = getSpreadElementType(spreadType);
+          DartType spreadElementType =
+              getSpreadElementType(spreadType, item.isNullAware);
           if (spreadElementType == null) {
-            node.replaceChild(
-                node.expressions[i],
-                inferrer.helper.desugarSyntheticExpression(inferrer.helper
-                    .buildProblem(
-                        templateSpreadTypeMismatch.withArguments(spreadType),
-                        item.expression.fileOffset,
-                        1)));
+            if (spreadType is InterfaceType &&
+                spreadType.classNode == inferrer.coreTypes.nullClass &&
+                !item.isNullAware) {
+              node.replaceChild(
+                  node.expressions[i],
+                  inferrer.helper.desugarSyntheticExpression(inferrer.helper
+                      .buildProblem(messageNonNullAwareSpreadIsNull,
+                          item.expression.fileOffset, 1)));
+            } else {
+              node.replaceChild(
+                  node.expressions[i],
+                  inferrer.helper.desugarSyntheticExpression(inferrer.helper
+                      .buildProblem(
+                          templateSpreadTypeMismatch.withArguments(spreadType),
+                          item.expression.fileOffset,
+                          1)));
+            }
           } else if (spreadType is DynamicType) {
             inferrer.ensureAssignable(inferrer.coreTypes.iterableClass.rawType,
                 spreadType, item.expression, item.expression.fileOffset);
           } else if (spreadType is InterfaceType) {
-            if (spreadType.classNode == inferrer.coreTypes.nullClass) {
-              // TODO(dmitryas):  Handle this case when null-aware spreads are
-              // supported by the parser.
-            } else {
-              if (!inferrer.isAssignable(
-                  node.typeArgument, spreadElementType)) {
-                node.replaceChild(
-                    node.expressions[i],
-                    inferrer.helper.desugarSyntheticExpression(inferrer.helper
-                        .buildProblem(
-                            templateSpreadElementTypeMismatch.withArguments(
-                                spreadElementType, node.typeArgument),
-                            item.expression.fileOffset,
-                            1)));
-              }
+            if (!inferrer.isAssignable(node.typeArgument, spreadElementType)) {
+              node.replaceChild(
+                  node.expressions[i],
+                  inferrer.helper.desugarSyntheticExpression(inferrer.helper
+                      .buildProblem(
+                          templateSpreadElementTypeMismatch.withArguments(
+                              spreadElementType, node.typeArgument),
+                          item.expression.fileOffset,
+                          1)));
             }
           }
         } else {
@@ -763,11 +785,12 @@
       }
     }
     node.inferredType = new InterfaceType(listClass, [inferredTypeArgument]);
-    KernelLibraryBuilder inferrerLibrary = inferrer.library;
-    if (inferenceNeeded && inferrerLibrary is KernelLibraryBuilder) {
-      inferrerLibrary.checkBoundsInListLiteral(
-          node, inferrer.typeSchemaEnvironment,
-          inferred: true);
+    if (!inferrer.isTopLevel) {
+      KernelLibraryBuilder library = inferrer.library;
+      if (inferenceNeeded) {
+        library.checkBoundsInListLiteral(node, inferrer.typeSchemaEnvironment,
+            inferred: true);
+      }
     }
 
     return null;
@@ -787,6 +810,28 @@
     return null;
   }
 
+  // Calculates the key and the value type of a spread map entry of type
+  // spreadMapEntryType and stores them in output in positions offset and offset
+  // + 1.  If the types can't be calculated, for example, if spreadMapEntryType
+  // is a function type, the original values in output are preserved.
+  void storeSpreadMapEntryElementTypes(DartType spreadMapEntryType,
+      bool isNullAware, List<DartType> output, int offset) {
+    if (spreadMapEntryType is InterfaceType) {
+      InterfaceType supertype = inferrer.typeSchemaEnvironment
+          .getTypeAsInstanceOf(spreadMapEntryType, inferrer.coreTypes.mapClass);
+      if (supertype != null) {
+        output[offset] = supertype.typeArguments[0];
+        output[offset + 1] = supertype.typeArguments[1];
+      } else if (spreadMapEntryType.classNode == inferrer.coreTypes.nullClass &&
+          isNullAware) {
+        output[offset] = output[offset + 1] = spreadMapEntryType;
+      }
+    }
+    if (spreadMapEntryType is DynamicType) {
+      output[offset] = output[offset + 1] = const DynamicType();
+    }
+  }
+
   void visitMapLiteralJudgment(MapLiteralJudgment node, DartType typeContext) {
     var mapClass = inferrer.coreTypes.mapClass;
     var mapType = mapClass.thisType;
@@ -799,26 +844,31 @@
         (node.valueType is ImplicitTypeArgument));
     bool inferenceNeeded = node.keyType is ImplicitTypeArgument;
     KernelLibraryBuilder library = inferrer.library;
-    if (library != null &&
-        library.loader.target.enableSetLiterals &&
-        inferenceNeeded &&
-        node.entries.isEmpty) {
-      // Ambiguous set/map literal
-      DartType context =
-          inferrer.typeSchemaEnvironment.unfutureType(typeContext);
-      if (context is InterfaceType) {
-        if (inferrer.classHierarchy.isSubtypeOf(
-                context.classNode, inferrer.coreTypes.iterableClass) &&
-            !inferrer.classHierarchy
-                .isSubtypeOf(context.classNode, inferrer.coreTypes.mapClass)) {
-          // Set literal
-          SetLiteralJudgment setLiteral = new SetLiteralJudgment([],
-              typeArgument: const ImplicitTypeArgument(), isConst: node.isConst)
-            ..fileOffset = node.fileOffset;
-          node.parent.replaceChild(node, setLiteral);
-          visitSetLiteralJudgment(setLiteral, typeContext);
-          node.inferredType = setLiteral.inferredType;
-          return;
+    bool typeContextIsMap = false;
+    bool typeContextIsIterable = false;
+    if (!inferrer.isTopLevel) {
+      if (library.loader.target.enableSetLiterals && inferenceNeeded) {
+        // Ambiguous set/map literal
+        DartType context =
+            inferrer.typeSchemaEnvironment.unfutureType(typeContext);
+        if (context is InterfaceType) {
+          typeContextIsMap = inferrer.classHierarchy
+              .isSubtypeOf(context.classNode, inferrer.coreTypes.mapClass);
+          typeContextIsIterable = inferrer.classHierarchy
+              .isSubtypeOf(context.classNode, inferrer.coreTypes.iterableClass);
+          if (node.entries.isEmpty &&
+              typeContextIsIterable &&
+              !typeContextIsMap) {
+            // Set literal
+            SetLiteralJudgment setLiteral = new SetLiteralJudgment([],
+                typeArgument: const ImplicitTypeArgument(),
+                isConst: node.isConst)
+              ..fileOffset = node.fileOffset;
+            node.parent.replaceChild(node, setLiteral);
+            visitSetLiteralJudgment(setLiteral, typeContext);
+            node.inferredType = setLiteral.inferredType;
+            return;
+          }
         }
       }
     }
@@ -840,34 +890,137 @@
     }
     List<Expression> cachedKeys = new List(node.entries.length);
     List<Expression> cachedValues = new List(node.entries.length);
+    List<DartType> spreadMapEntryTypes =
+        typeChecksNeeded ? new List<DartType>(node.entries.length) : null;
     for (int i = 0; i < node.entries.length; i++) {
       MapEntry entry = node.entries[i];
-      if (entry is! SpreadMapEntry) {
+      if (entry is! SpreadMapEntry && entry is! IfMapEntry) {
         cachedKeys[i] = node.entries[i].key;
         cachedValues[i] = node.entries[i].value;
       }
     }
+    int iterableSpreadOffset = -1;
+    int mapSpreadOffset = -1;
+    int mapEntryOffset = -1;
     if (inferenceNeeded || typeChecksNeeded) {
-      for (MapEntry entry in node.entries) {
+      DartType spreadTypeContext = const UnknownType();
+      if (typeContextIsIterable && !typeContextIsMap) {
+        spreadTypeContext = inferrer.typeSchemaEnvironment
+            .getTypeAsInstanceOf(typeContext, inferrer.coreTypes.iterableClass);
+      } else if (!typeContextIsIterable && typeContextIsMap) {
+        spreadTypeContext =
+            new InterfaceType(inferrer.coreTypes.mapClass, inferredTypes);
+      }
+      for (int i = 0; i < node.entries.length; ++i) {
+        MapEntry entry = node.entries[i];
         if (entry is SpreadMapEntry) {
-          actualTypes.add(const BottomType());
-          actualTypes.add(inferrer.coreTypes.nullClass.rawType);
-          continue;
-        }
-        Expression key = entry.key;
-        inferrer.inferExpression(key, inferredKeyType, true,
-            isVoidAllowed: true);
-        actualTypes.add(getInferredType(key, inferrer));
-        Expression value = entry.value;
-        inferrer.inferExpression(value, inferredValueType, true,
-            isVoidAllowed: true);
-        actualTypes.add(getInferredType(value, inferrer));
-        if (inferenceNeeded) {
-          formalTypes.addAll(mapType.typeArguments);
+          DartType spreadMapEntryType = inferrer.inferExpression(
+              entry.expression,
+              spreadTypeContext,
+              inferenceNeeded || typeChecksNeeded,
+              isVoidAllowed: true);
+          if (inferenceNeeded) {
+            formalTypes.add(mapType.typeArguments[0]);
+            formalTypes.add(mapType.typeArguments[1]);
+          }
+          if (typeChecksNeeded) {
+            spreadMapEntryTypes[i] = spreadMapEntryType;
+          }
+
+          bool isMap = inferrer.typeSchemaEnvironment.isSubtypeOf(
+              spreadMapEntryType, inferrer.coreTypes.mapClass.rawType);
+          bool isSet = inferrer.typeSchemaEnvironment.isSubtypeOf(
+              spreadMapEntryType, inferrer.coreTypes.iterableClass.rawType);
+
+          if (isMap && !isSet) {
+            mapSpreadOffset = entry.expression.fileOffset;
+          }
+          if (!isMap && isSet) {
+            iterableSpreadOffset = entry.expression.fileOffset;
+          }
+
+          // Use 'dynamic' for error recovery.
+          int length = actualTypes.length;
+          actualTypes.add(const DynamicType());
+          actualTypes.add(const DynamicType());
+          storeSpreadMapEntryElementTypes(
+              spreadMapEntryType, entry.isNullAware, actualTypes, length);
+        } else if (entry is IfMapEntry) {
+          node.entries[i] = new MapEntry(
+              new InvalidExpression('unimplemented spread entry')
+                ..fileOffset = node.fileOffset,
+              new NullLiteral());
+          actualTypes.add(const DynamicType());
+          actualTypes.add(const DynamicType());
+        } else {
+          Expression key = entry.key;
+          inferrer.inferExpression(key, inferredKeyType, true,
+              isVoidAllowed: true);
+          actualTypes.add(getInferredType(key, inferrer));
+          Expression value = entry.value;
+          inferrer.inferExpression(value, inferredValueType, true,
+              isVoidAllowed: true);
+          actualTypes.add(getInferredType(value, inferrer));
+          if (inferenceNeeded) {
+            formalTypes.addAll(mapType.typeArguments);
+          }
+
+          mapEntryOffset = entry.fileOffset;
         }
       }
     }
     if (inferenceNeeded) {
+      bool canBeSet =
+          mapSpreadOffset == -1 && mapEntryOffset == -1 && !typeContextIsMap;
+      bool canBeMap = iterableSpreadOffset == -1 && !typeContextIsIterable;
+      if (canBeSet && !canBeMap) {
+        List<Expression> setElements = <Expression>[];
+        for (int i = 0; i < node.entries.length; ++i) {
+          SpreadMapEntry entry = node.entries[i];
+          setElements
+              .add(new SpreadElement(entry.expression, entry.isNullAware));
+        }
+        SetLiteralJudgment setLiteral = new SetLiteralJudgment(setElements,
+            typeArgument: const ImplicitTypeArgument(), isConst: node.isConst)
+          ..fileOffset = node.fileOffset;
+        node.parent.replaceChild(node, setLiteral);
+        visitSetLiteralJudgment(setLiteral, typeContext);
+        node.inferredType = setLiteral.inferredType;
+        return;
+      }
+      if (canBeSet && canBeMap && node.entries.isNotEmpty) {
+        node.parent.replaceChild(
+            node,
+            inferrer.helper.desugarSyntheticExpression(inferrer.helper
+                .buildProblem(messageCantDisambiguateNotEnoughInformation,
+                    node.fileOffset, 1)));
+        node.inferredType = const BottomType();
+        return;
+      }
+      if (!canBeSet && !canBeMap) {
+        if (!inferrer.isTopLevel) {
+          LocatedMessage iterableContextMessage = messageSpreadElement
+              .withLocation(library.uri, iterableSpreadOffset, 1);
+          LocatedMessage mapContextMessage = messageSpreadMapElement
+              .withLocation(library.uri, mapSpreadOffset, 1);
+          List<LocatedMessage> context = <LocatedMessage>[];
+          if (iterableSpreadOffset < mapSpreadOffset) {
+            context.add(iterableContextMessage);
+            context.add(mapContextMessage);
+          } else {
+            context.add(mapContextMessage);
+            context.add(iterableContextMessage);
+          }
+          node.parent.replaceChild(
+              node,
+              inferrer.helper.desugarSyntheticExpression(inferrer.helper
+                  .buildProblem(messageCantDisambiguateAmbiguousInformation,
+                      node.fileOffset, 1,
+                      context: context)));
+        }
+        node.inferredType = const BottomType();
+        return;
+      }
       inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
           mapType,
           mapClass.typeParameters,
@@ -888,33 +1041,97 @@
     }
     if (typeChecksNeeded) {
       for (int i = 0; i < node.entries.length; ++i) {
-        Expression keyJudgment = cachedKeys[i];
-        if (keyJudgment == null) {
-          node.entries[i] = new MapEntry(
-              new InvalidExpression('unimplemented spread entry')
-                ..fileOffset = node.fileOffset,
-              new NullLiteral()..parent = node);
-          continue;
-        }
-        inferrer.ensureAssignable(node.keyType, actualTypes[2 * i], keyJudgment,
-            keyJudgment.fileOffset,
-            isVoidAllowed: node.keyType is VoidType);
+        MapEntry entry = node.entries[i];
+        List<DartType> spreadMapEntryElementTypes = new List<DartType>(2);
+        if (entry is SpreadMapEntry) {
+          DartType spreadMapEntryType = spreadMapEntryTypes[i];
+          spreadMapEntryElementTypes[0] = spreadMapEntryElementTypes[1] = null;
+          storeSpreadMapEntryElementTypes(spreadMapEntryType, entry.isNullAware,
+              spreadMapEntryElementTypes, 0);
+          if (spreadMapEntryElementTypes[0] == null) {
+            if (spreadMapEntryType is InterfaceType &&
+                spreadMapEntryType.classNode == inferrer.coreTypes.nullClass &&
+                !entry.isNullAware) {
+              node.replaceChild(
+                  node.entries[i],
+                  new MapEntry(
+                      inferrer.helper.desugarSyntheticExpression(inferrer.helper
+                          .buildProblem(messageNonNullAwareSpreadIsNull,
+                              entry.expression.fileOffset, 1)),
+                      new NullLiteral()));
+            } else {
+              node.replaceChild(
+                  node.entries[i],
+                  new MapEntry(
+                      inferrer.helper.desugarSyntheticExpression(inferrer.helper
+                          .buildProblem(
+                              templateSpreadMapEntryTypeMismatch
+                                  .withArguments(spreadMapEntryType),
+                              entry.expression.fileOffset,
+                              1)),
+                      new NullLiteral()));
+            }
+          } else if (spreadMapEntryType is DynamicType) {
+            inferrer.ensureAssignable(
+                inferrer.coreTypes.mapClass.rawType,
+                spreadMapEntryType,
+                entry.expression,
+                entry.expression.fileOffset);
+          } else if (spreadMapEntryType is InterfaceType) {
+            Expression keyError;
+            Expression valueError;
+            if (!inferrer.isAssignable(
+                node.keyType, spreadMapEntryElementTypes[0])) {
+              keyError = inferrer.helper.desugarSyntheticExpression(
+                  inferrer.helper.buildProblem(
+                      templateSpreadMapEntryElementKeyTypeMismatch
+                          .withArguments(
+                              spreadMapEntryElementTypes[0], node.keyType),
+                      entry.expression.fileOffset,
+                      1));
+            }
+            if (!inferrer.isAssignable(
+                node.valueType, spreadMapEntryElementTypes[1])) {
+              valueError = inferrer.helper.desugarSyntheticExpression(
+                  inferrer.helper.buildProblem(
+                      templateSpreadMapEntryElementValueTypeMismatch
+                          .withArguments(
+                              spreadMapEntryElementTypes[1], node.valueType),
+                      entry.expression.fileOffset,
+                      1));
+            }
+            if (keyError != null || valueError != null) {
+              keyError ??= new NullLiteral();
+              valueError ??= new NullLiteral();
+              node.replaceChild(
+                  node.entries[i], new MapEntry(keyError, valueError));
+            }
+          }
+        } else {
+          Expression keyJudgment = cachedKeys[i];
+          if (keyJudgment != null) {
+            inferrer.ensureAssignable(node.keyType, actualTypes[2 * i],
+                keyJudgment, keyJudgment.fileOffset,
+                isVoidAllowed: node.keyType is VoidType);
 
-        Expression valueJudgment = cachedValues[i];
-        inferrer.ensureAssignable(node.valueType, actualTypes[2 * i + 1],
-            valueJudgment, valueJudgment.fileOffset,
-            isVoidAllowed: node.valueType is VoidType);
+            Expression valueJudgment = cachedValues[i];
+            inferrer.ensureAssignable(node.valueType, actualTypes[2 * i + 1],
+                valueJudgment, valueJudgment.fileOffset,
+                isVoidAllowed: node.valueType is VoidType);
+          }
+        }
       }
     }
     node.inferredType =
         new InterfaceType(mapClass, [inferredKeyType, inferredValueType]);
-    KernelLibraryBuilder inferrerLibrary = inferrer.library;
-    // Either both [_declaredKeyType] and [_declaredValueType] are omitted or
-    // none of them, so we may just check one.
-    if (inferenceNeeded && inferrerLibrary is KernelLibraryBuilder) {
-      inferrerLibrary.checkBoundsInMapLiteral(
-          node, inferrer.typeSchemaEnvironment,
-          inferred: true);
+    if (!inferrer.isTopLevel) {
+      KernelLibraryBuilder library = inferrer.library;
+      // Either both [_declaredKeyType] and [_declaredValueType] are omitted or
+      // none of them, so we may just check one.
+      if (inferenceNeeded) {
+        library.checkBoundsInMapLiteral(node, inferrer.typeSchemaEnvironment,
+            inferred: true);
+      }
     }
   }
 
@@ -1173,8 +1390,9 @@
             spreadTypes[i] = spreadType;
           }
           // Use 'dynamic' for error recovery.
-          actualTypes
-              .add(getSpreadElementType(spreadType) ?? const DynamicType());
+          actualTypes.add(
+              getSpreadElementType(spreadType, judgment.isNullAware) ??
+                  const DynamicType());
         } else {
           inferrer.inferExpression(judgment, inferredTypeArgument,
               inferenceNeeded || typeChecksNeeded,
@@ -1207,34 +1425,39 @@
         Expression item = node.expressions[i];
         if (item is SpreadElement) {
           DartType spreadType = spreadTypes[i];
-          DartType spreadElementType = getSpreadElementType(spreadType);
+          DartType spreadElementType =
+              getSpreadElementType(spreadType, item.isNullAware);
           if (spreadElementType == null) {
-            node.replaceChild(
-                node.expressions[i],
-                inferrer.helper.desugarSyntheticExpression(inferrer.helper
-                    .buildProblem(
-                        templateSpreadTypeMismatch.withArguments(spreadType),
-                        item.expression.fileOffset,
-                        1)));
+            if (spreadType is InterfaceType &&
+                spreadType.classNode == inferrer.coreTypes.nullClass &&
+                !item.isNullAware) {
+              node.replaceChild(
+                  node.expressions[i],
+                  inferrer.helper.desugarSyntheticExpression(inferrer.helper
+                      .buildProblem(messageNonNullAwareSpreadIsNull,
+                          item.expression.fileOffset, 1)));
+            } else {
+              node.replaceChild(
+                  node.expressions[i],
+                  inferrer.helper.desugarSyntheticExpression(inferrer.helper
+                      .buildProblem(
+                          templateSpreadTypeMismatch.withArguments(spreadType),
+                          item.expression.fileOffset,
+                          1)));
+            }
           } else if (spreadType is DynamicType) {
             inferrer.ensureAssignable(inferrer.coreTypes.iterableClass.rawType,
                 spreadType, item.expression, item.expression.fileOffset);
           } else if (spreadType is InterfaceType) {
-            if (spreadType.classNode == inferrer.coreTypes.nullClass) {
-              // TODO(dmitryas):  Handle this case when null-aware spreads are
-              // supported by the parser.
-            } else {
-              if (!inferrer.isAssignable(
-                  node.typeArgument, spreadElementType)) {
-                node.replaceChild(
-                    node.expressions[i],
-                    inferrer.helper.desugarSyntheticExpression(inferrer.helper
-                        .buildProblem(
-                            templateSpreadElementTypeMismatch.withArguments(
-                                spreadElementType, node.typeArgument),
-                            item.expression.fileOffset,
-                            1)));
-              }
+            if (!inferrer.isAssignable(node.typeArgument, spreadElementType)) {
+              node.replaceChild(
+                  node.expressions[i],
+                  inferrer.helper.desugarSyntheticExpression(inferrer.helper
+                      .buildProblem(
+                          templateSpreadElementTypeMismatch.withArguments(
+                              spreadElementType, node.typeArgument),
+                          item.expression.fileOffset,
+                          1)));
             }
           }
         } else {
@@ -1245,17 +1468,16 @@
       }
     }
     node.inferredType = new InterfaceType(setClass, [inferredTypeArgument]);
-    KernelLibraryBuilder inferrerLibrary = inferrer.library;
-    if (inferenceNeeded && inferrerLibrary is KernelLibraryBuilder) {
-      inferrerLibrary.checkBoundsInSetLiteral(
-          node, inferrer.typeSchemaEnvironment,
-          inferred: true);
-    }
+    if (!inferrer.isTopLevel) {
+      KernelLibraryBuilder library = inferrer.library;
+      if (inferenceNeeded) {
+        library.checkBoundsInSetLiteral(node, inferrer.typeSchemaEnvironment,
+            inferred: true);
+      }
 
-    KernelLibraryBuilder library = inferrer.library;
-    if (library != null &&
-        !library.loader.target.backendTarget.supportsSetLiterals) {
-      inferrer.helper.transformSetLiterals = true;
+      if (!library.loader.target.backendTarget.supportsSetLiterals) {
+        inferrer.helper.transformSetLiterals = true;
+      }
     }
   }
 
@@ -1273,10 +1495,7 @@
     if (write is StaticSet) {
       writeContext = write.target.setterType;
       writeMember = write.target;
-      if (writeMember is ShadowField && writeMember.inferenceNode != null) {
-        writeMember.inferenceNode.resolve();
-        writeMember.inferenceNode = null;
-      }
+      TypeInferenceEngine.resolveInferenceNode(writeMember);
     }
     node._inferRhs(inferrer, readType, writeContext);
     node._replaceWithDesugared();
@@ -1286,10 +1505,7 @@
   @override
   void visitStaticGet(StaticGet node, DartType typeContext) {
     var target = node.target;
-    if (target is ShadowField && target.inferenceNode != null) {
-      target.inferenceNode.resolve();
-      target.inferenceNode = null;
-    }
+    TypeInferenceEngine.resolveInferenceNode(target);
     var type = target.getterType;
     if (target is Procedure && target.kind == ProcedureKind.Method) {
       type = inferrer.instantiateTearOff(type, typeContext, node);
@@ -1516,11 +1732,13 @@
         node.initializer = replacedInitializer;
       }
     }
-    KernelLibraryBuilder inferrerLibrary = inferrer.library;
-    if (node._implicitlyTyped && inferrerLibrary is KernelLibraryBuilder) {
-      inferrerLibrary.checkBoundsInVariableDeclaration(
-          node, inferrer.typeSchemaEnvironment,
-          inferred: true);
+    if (!inferrer.isTopLevel) {
+      KernelLibraryBuilder library = inferrer.library;
+      if (node._implicitlyTyped) {
+        library.checkBoundsInVariableDeclaration(
+            node, inferrer.typeSchemaEnvironment,
+            inferred: true);
+      }
     }
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart
index 05513ad..91ae51b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart
@@ -28,11 +28,18 @@
 
   @override
   DartType defaultExpression(Expression node, TypeInferrerImpl inferrer) {
+    if (node is IfElement) {
+      return visitIfElement(node, inferrer);
+    }
     unhandled("${node.runtimeType}", "getInferredType", node.fileOffset,
         inferrer.uri);
     return const InvalidType();
   }
 
+  DartType visitIfElement(IfElement node, TypeInferrerImpl inferrer) {
+    return const BottomType();
+  }
+
   @override
   DartType visitIntLiteral(IntLiteral node, TypeInferrerImpl inferrer) {
     return inferrer.coreTypes.intClass.rawType;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index e43378a..80b38e4 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -1025,18 +1025,24 @@
       // Report an error.
       String declaredMemberName =
           '${declaredMember.enclosingClass.name}.${declaredMember.name.name}';
+      String interfaceMemberName =
+          '${interfaceMember.enclosingClass.name}.${interfaceMember.name.name}';
       Message message;
       int fileOffset;
       if (declaredParameter == null) {
         message = templateOverrideTypeMismatchReturnType.withArguments(
-            declaredMemberName, declaredType, interfaceType);
+            declaredMemberName,
+            declaredType,
+            interfaceType,
+            interfaceMemberName);
         fileOffset = declaredMember.fileOffset;
       } else {
         message = templateOverrideTypeMismatchParameter.withArguments(
             declaredParameter.name,
             declaredMemberName,
             declaredType,
-            interfaceType);
+            interfaceType,
+            interfaceMemberName);
         fileOffset = declaredParameter.fileOffset;
       }
       library.addProblem(message, fileOffset, noLength, declaredMember.fileUri,
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 b85bee7..56c6840 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
@@ -35,6 +35,12 @@
 
 import '../fasta_codes.dart'
     show
+        LocatedMessage,
+        messageCantDisambiguateAmbiguousInformation,
+        messageCantDisambiguateNotEnoughInformation,
+        messageNonNullAwareSpreadIsNull,
+        messageSpreadElement,
+        messageSpreadMapElement,
         messageSwitchExpressionNotAssignableCause,
         messageVoidExpression,
         noLength,
@@ -43,6 +49,9 @@
         templateForInLoopTypeNotIterable,
         templateIntegerLiteralIsOutOfRange,
         templateSpreadElementTypeMismatch,
+        templateSpreadMapEntryElementKeyTypeMismatch,
+        templateSpreadMapEntryElementValueTypeMismatch,
+        templateSpreadMapEntryTypeMismatch,
         templateSpreadTypeMismatch,
         templateSwitchExpressionNotAssignable,
         templateWebLiteralCannotBeRepresentedExactly;
@@ -73,7 +82,8 @@
 
 import 'body_builder.dart' show combineStatements;
 
-import 'collections.dart' show SpreadElement, SpreadMapEntry;
+import 'collections.dart'
+    show IfElement, SpreadElement, IfMapEntry, SpreadMapEntry;
 
 import 'implicit_type_argument.dart' show ImplicitTypeArgument;
 
@@ -994,15 +1004,6 @@
 
   void setInferredType(
       TypeInferenceEngine engine, Uri uri, DartType inferredType);
-
-  static void resolveInferenceNode(Member member) {
-    if (member is ShadowMember) {
-      if (member.inferenceNode != null) {
-        member.inferenceNode.resolve();
-        member.inferenceNode = null;
-      }
-    }
-  }
 }
 
 /// Shadow object for [MethodInvocation].
diff --git a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
index 27244cd..1afd831 100644
--- a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
@@ -4,25 +4,32 @@
 
 library fasta.transform_collections;
 
+import 'dart:core' hide MapEntry;
+
 import 'package:kernel/ast.dart'
     show
         Arguments,
         Block,
         BlockExpression,
+        Class,
         DartType,
         DynamicType,
         Expression,
         ExpressionStatement,
+        Field,
         ForInStatement,
         IfStatement,
         InterfaceType,
         InvalidExpression,
         ListLiteral,
+        MapEntry,
+        MapLiteral,
         MethodInvocation,
         Name,
         Not,
         NullLiteral,
         Procedure,
+        PropertyGet,
         SetLiteral,
         Statement,
         StaticInvocation,
@@ -34,7 +41,7 @@
 
 import 'package:kernel/visitor.dart' show Transformer;
 
-import 'collections.dart' show SpreadElement;
+import 'collections.dart' show SpreadElement, SpreadMapEntry;
 
 import '../source/source_loader.dart' show SourceLoader;
 
@@ -46,6 +53,11 @@
   final Procedure setFactory;
   final Procedure setAdd;
   final Procedure objectEquals;
+  final Procedure mapEntries;
+  final Procedure mapPut;
+  final Class mapEntryClass;
+  final Field mapEntryKey;
+  final Field mapEntryValue;
 
   static Procedure _findSetFactory(CoreTypes coreTypes) {
     Procedure factory = coreTypes.index.getMember('dart:core', 'Set', '');
@@ -59,7 +71,16 @@
         setFactory = _findSetFactory(loader.coreTypes),
         setAdd = loader.coreTypes.index.getMember('dart:core', 'Set', 'add'),
         objectEquals =
-            loader.coreTypes.index.getMember('dart:core', 'Object', '==');
+            loader.coreTypes.index.getMember('dart:core', 'Object', '=='),
+        mapEntries =
+            loader.coreTypes.index.getMember('dart:core', 'Map', 'get:entries'),
+        mapPut = loader.coreTypes.index.getMember('dart:core', 'Map', '[]='),
+        mapEntryClass =
+            loader.coreTypes.index.getClass('dart:core', 'MapEntry'),
+        mapEntryKey =
+            loader.coreTypes.index.getMember('dart:core', 'MapEntry', 'key'),
+        mapEntryValue =
+            loader.coreTypes.index.getMember('dart:core', 'MapEntry', 'value');
 
   TreeNode _translateListOrSet(
       Expression node, DartType elementType, List<Expression> elements,
@@ -174,4 +195,98 @@
     return _translateListOrSet(node, node.typeArgument, node.expressions,
         isConst: node.isConst, isSet: true);
   }
+
+  @override
+  TreeNode visitMapLiteral(MapLiteral node) {
+    int i = 0;
+    for (; i < node.entries.length; ++i) {
+      if (node.entries[i] is SpreadMapEntry) break;
+      node.entries[i] = node.entries[i].accept(this)..parent = node;
+    }
+
+    if (i == node.entries.length) return node;
+
+    if (node.isConst) {
+      // We don't desugar const maps here.  REmove spread for now so that they
+      // don't leak out.
+      for (; i < node.entries.length; ++i) {
+        MapEntry entry = node.entries[i];
+        if (entry is SpreadMapEntry) {
+          entry.parent.replaceChild(
+              entry,
+              new MapEntry(
+                  InvalidExpression('unimplemented spread element')
+                    ..fileOffset = entry.fileOffset,
+                  new NullLiteral()));
+        }
+      }
+    }
+
+    VariableDeclaration map = new VariableDeclaration.forValue(
+        new MapLiteral([], keyType: node.keyType, valueType: node.valueType),
+        type: new InterfaceType(
+            coreTypes.mapClass, [node.keyType, node.valueType]),
+        isFinal: true);
+    List<Statement> body = [map];
+    for (int j = 0; j < i; ++j) {
+      body.add(new ExpressionStatement(new MethodInvocation(
+          new VariableGet(map),
+          new Name('[]='),
+          new Arguments([node.entries[j].key, node.entries[j].value]),
+          mapPut)));
+    }
+    DartType mapEntryType =
+        new InterfaceType(mapEntryClass, [node.keyType, node.valueType]);
+    for (; i < node.entries.length; ++i) {
+      MapEntry entry = node.entries[i];
+      if (entry is SpreadMapEntry) {
+        Expression value = entry.expression.accept(this);
+        // Null-aware spreads require testing the subexpression's value.
+        VariableDeclaration temp;
+        if (entry.isNullAware) {
+          temp = new VariableDeclaration.forValue(value,
+              type: coreTypes.mapClass.rawType);
+          body.add(temp);
+          value = new VariableGet(temp);
+        }
+
+        VariableDeclaration elt =
+            new VariableDeclaration(null, type: mapEntryType, isFinal: true);
+        Statement statement = new ForInStatement(
+            elt,
+            new PropertyGet(value, new Name('entries'), mapEntries),
+            new ExpressionStatement(new MethodInvocation(
+                new VariableGet(map),
+                new Name('[]='),
+                new Arguments([
+                  new PropertyGet(
+                      new VariableGet(elt), new Name('key'), mapEntryKey),
+                  new PropertyGet(
+                      new VariableGet(elt), new Name('value'), mapEntryValue)
+                ]),
+                mapPut)));
+
+        if (entry.isNullAware) {
+          statement = new IfStatement(
+              new Not(new MethodInvocation(
+                  new VariableGet(temp),
+                  new Name('=='),
+                  new Arguments([new NullLiteral()]),
+                  objectEquals)),
+              statement,
+              null);
+        }
+        body.add(statement);
+      } else {
+        entry = entry.accept(this);
+        body.add(new ExpressionStatement(new MethodInvocation(
+            new VariableGet(map),
+            new Name('[]='),
+            new Arguments([entry.key, entry.value]),
+            mapPut)));
+      }
+    }
+
+    return new BlockExpression(new Block(body), new VariableGet(map));
+  }
 }
diff --git a/pkg/front_end/lib/src/fasta/parser/literal_entry_info.dart b/pkg/front_end/lib/src/fasta/parser/literal_entry_info.dart
index cb85853..c29fb9a 100644
--- a/pkg/front_end/lib/src/fasta/parser/literal_entry_info.dart
+++ b/pkg/front_end/lib/src/fasta/parser/literal_entry_info.dart
@@ -10,7 +10,7 @@
 
 /// [simpleEntry] is the first step for parsing a literal entry
 /// without any control flow or spread collection operator.
-const LiteralEntryInfo simpleEntry = const LiteralEntryInfo(true);
+const LiteralEntryInfo simpleEntry = const LiteralEntryInfo(true, 0);
 
 /// [LiteralEntryInfo] represents steps for processing an entry
 /// in a literal list, map, or set. These steps will handle parsing
@@ -35,7 +35,11 @@
   /// or `false` if this object's [parse] method should be called.
   final bool hasEntry;
 
-  const LiteralEntryInfo(this.hasEntry);
+  /// Used for recovery, this indicates
+  /// +1 for an `if` condition and -1 for `else`.
+  final int ifConditionDelta;
+
+  const LiteralEntryInfo(this.hasEntry, this.ifConditionDelta);
 
   /// Parse the control flow and spread collection aspects of this entry.
   Token parse(Token token, Parser parser) {
diff --git a/pkg/front_end/lib/src/fasta/parser/literal_entry_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/literal_entry_info_impl.dart
index f62ba96..1ea0bf7 100644
--- a/pkg/front_end/lib/src/fasta/parser/literal_entry_info_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/literal_entry_info_impl.dart
@@ -19,7 +19,7 @@
 class ForCondition extends LiteralEntryInfo {
   bool inStyle;
 
-  ForCondition() : super(false);
+  ForCondition() : super(false, 0);
 
   @override
   Token parse(Token token, Parser parser) {
@@ -96,7 +96,7 @@
 /// A step for parsing a literal list, set, or map entry
 /// as the "for" control flow's expression.
 class ForEntry extends LiteralEntryInfo {
-  const ForEntry() : super(true);
+  const ForEntry() : super(true, 0);
 
   @override
   LiteralEntryInfo computeNext(Token token) {
@@ -107,7 +107,7 @@
 /// A step for parsing a literal list, set, or map entry
 /// as the "for-in" control flow's expression.
 class ForInEntry extends LiteralEntryInfo {
-  const ForInEntry() : super(true);
+  const ForInEntry() : super(true, 0);
 
   @override
   LiteralEntryInfo computeNext(Token token) {
@@ -116,7 +116,7 @@
 }
 
 class ForComplete extends LiteralEntryInfo {
-  const ForComplete() : super(false);
+  const ForComplete() : super(false, 0);
 
   @override
   Token parse(Token token, Parser parser) {
@@ -126,7 +126,7 @@
 }
 
 class ForInComplete extends LiteralEntryInfo {
-  const ForInComplete() : super(false);
+  const ForInComplete() : super(false, 0);
 
   @override
   Token parse(Token token, Parser parser) {
@@ -137,7 +137,7 @@
 
 /// The first step when processing an `if` control flow collection entry.
 class IfCondition extends LiteralEntryInfo {
-  const IfCondition() : super(false);
+  const IfCondition() : super(false, 1);
 
   @override
   Token parse(Token token, Parser parser) {
@@ -174,14 +174,14 @@
 /// A step for parsing a literal list, set, or map entry
 /// as the `if` control flow's then-expression.
 class IfEntry extends LiteralEntryInfo {
-  const IfEntry() : super(true);
+  const IfEntry() : super(true, 0);
 
   @override
   LiteralEntryInfo computeNext(Token token) => const IfComplete();
 }
 
 class IfComplete extends LiteralEntryInfo {
-  const IfComplete() : super(false);
+  const IfComplete() : super(false, 0);
 
   @override
   Token parse(Token token, Parser parser) {
@@ -199,7 +199,7 @@
 
 /// A step for parsing the `else` portion of an `if` control flow.
 class IfElse extends LiteralEntryInfo {
-  const IfElse() : super(false);
+  const IfElse() : super(false, -1);
 
   @override
   Token parse(Token token, Parser parser) {
@@ -235,7 +235,7 @@
 }
 
 class ElseEntry extends LiteralEntryInfo {
-  const ElseEntry() : super(true);
+  const ElseEntry() : super(true, 0);
 
   @override
   LiteralEntryInfo computeNext(Token token) {
@@ -244,7 +244,7 @@
 }
 
 class IfElseComplete extends LiteralEntryInfo {
-  const IfElseComplete() : super(false);
+  const IfElseComplete() : super(false, 0);
 
   @override
   Token parse(Token token, Parser parser) {
@@ -255,7 +255,7 @@
 
 /// The first step when processing a spread entry.
 class SpreadOperator extends LiteralEntryInfo {
-  const SpreadOperator() : super(false);
+  const SpreadOperator() : super(false, 0);
 
   @override
   Token parse(Token token, Parser parser) {
@@ -271,7 +271,7 @@
   LiteralEntryInfo nestedStep;
   final LiteralEntryInfo lastStep;
 
-  Nested(this.nestedStep, this.lastStep) : super(false);
+  Nested(this.nestedStep, this.lastStep) : super(false, 0);
 
   @override
   bool get hasEntry => nestedStep.hasEntry;
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 260fe3e..774daef 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -2416,10 +2416,50 @@
     int count = 0;
     bool old = mayParseFunctionExpressions;
     mayParseFunctionExpressions = false;
-    do {
-      token = parseInitializer(token.next);
+    Token next = begin;
+    while (true) {
+      token = parseInitializer(next);
       ++count;
-    } while (optional(',', token.next));
+      next = token.next;
+      if (!optional(',', next)) {
+        if (!next.isKeywordOrIdentifier) {
+          break;
+        }
+        // Recovery: Found an identifier which could be
+        // 1) missing preceding `,` thus it's another initializer, or
+        // 2) missing preceding `;` thus it's a class member, or
+        // 3) missing preceding '{' thus it's a statement
+        if (optional('assert', next)) {
+          next = next.next;
+          if (!optional('(', next)) {
+            break;
+          }
+          // Looks like assert expression ... fall through to insert comma
+        } else {
+          if (optional('this', next)) {
+            next = next.next;
+            if (!optional('.', next)) {
+              break;
+            }
+            next = next.next;
+            if (!next.isKeywordOrIdentifier) {
+              break;
+            }
+          }
+          next = next.next;
+          if (!optional('=', next)) {
+            break;
+          }
+          // Looks like field assignment... fall through to insert comma
+        }
+        // TODO(danrubel): Consider enhancing this to indicate that we are
+        // expecting one of `,` or `;` or `{`
+        reportRecoverableError(
+            token, fasta.templateExpectedAfterButGot.withArguments(','));
+        next = rewriter.insertToken(
+            token, new SyntheticToken(TokenType.COMMA, token.next.charOffset));
+      }
+    }
     mayParseFunctionExpressions = old;
     listener.endInitializers(count, begin, token.next);
     return token;
@@ -4211,7 +4251,17 @@
         token = next;
         break;
       }
-      token = parseListOrSetLiteralEntry(token);
+      int ifCount = 0;
+      LiteralEntryInfo info = computeLiteralEntry(token);
+      while (info != null) {
+        if (info.hasEntry) {
+          token = parseExpression(token);
+        } else {
+          token = info.parse(token, this);
+        }
+        ifCount += info.ifConditionDelta;
+        info = info.computeNext(token);
+      }
       next = token.next;
       ++count;
       if (!optional(',', next)) {
@@ -4236,10 +4286,11 @@
         }
         // This looks like the start of an expression.
         // Report an error, insert the comma, and continue parsing.
-        next = rewriteAndRecover(
-            token,
-            fasta.templateExpectedButGot.withArguments(','),
-            new SyntheticToken(TokenType.COMMA, next.offset));
+        var comma = new SyntheticToken(TokenType.COMMA, next.offset);
+        var message = ifCount > 0
+            ? fasta.messageExpectedElseOrComma
+            : fasta.templateExpectedButGot.withArguments(',');
+        next = rewriteAndRecover(token, message, comma);
       }
       token = next;
     }
@@ -4248,19 +4299,6 @@
     return token;
   }
 
-  Token parseListOrSetLiteralEntry(Token token) {
-    LiteralEntryInfo info = computeLiteralEntry(token);
-    while (info != null) {
-      if (info.hasEntry) {
-        token = parseExpression(token);
-      } else {
-        token = info.parse(token, this);
-      }
-      info = info.computeNext(token);
-    }
-    return token;
-  }
-
   /// This method parses the portion of a set or map literal that starts with
   /// the left curly brace when there are no leading type arguments.
   Token parseLiteralSetOrMapSuffix(Token token, Token constKeyword) {
@@ -4280,6 +4318,7 @@
     bool hasSetEntry;
 
     while (true) {
+      int ifCount = 0;
       LiteralEntryInfo info = computeLiteralEntry(token);
       if (info == simpleEntry) {
         // TODO(danrubel): Remove this section and use the while loop below
@@ -4304,6 +4343,7 @@
           } else {
             token = info.parse(token, this);
           }
+          ifCount += info.ifConditionDelta;
           info = info.computeNext(token);
         }
       }
@@ -4327,10 +4367,12 @@
         if (looksLikeLiteralEntry(next)) {
           // If this looks like the start of an expression,
           // then report an error, insert the comma, and continue parsing.
-          token = rewriteAndRecover(
-              token,
-              fasta.templateExpectedButGot.withArguments(','),
-              new SyntheticToken(TokenType.COMMA, next.offset));
+          // TODO(danrubel): Consider better error message
+          var comma = new SyntheticToken(TokenType.COMMA, next.offset);
+          var message = ifCount > 0
+              ? fasta.messageExpectedElseOrComma
+              : fasta.templateExpectedButGot.withArguments(',');
+          token = rewriteAndRecover(token, message, comma);
         } else {
           reportRecoverableError(
               next, fasta.templateExpectedButGot.withArguments('}'));
diff --git a/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart b/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
index 96b90c3..65db7c3 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
@@ -47,12 +47,7 @@
 import '../kernel/kernel_library_builder.dart' show KernelLibraryBuilder;
 
 import '../kernel/kernel_shadow_ast.dart'
-    show
-        ShadowClass,
-        ShadowField,
-        ShadowMember,
-        ShadowProcedure,
-        VariableDeclarationJudgment;
+    show ShadowClass, ShadowField, ShadowProcedure, VariableDeclarationJudgment;
 
 import '../messages.dart'
     show
@@ -160,7 +155,7 @@
       DartType overriddenType;
       if (resolvedCandidate is SyntheticAccessor) {
         var field = resolvedCandidate._field;
-        ShadowMember.resolveInferenceNode(field);
+        TypeInferenceEngine.resolveInferenceNode(field);
         overriddenType = field.type;
       } else if (resolvedCandidate.function != null) {
         switch (resolvedCandidate.kind) {
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 94cff43..a3251d6 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
@@ -11,6 +11,7 @@
         Field,
         FunctionType,
         InterfaceType,
+        Member,
         TypeParameter,
         TypeParameterType,
         TypedefType,
@@ -25,7 +26,7 @@
 import '../kernel/kernel_builder.dart'
     show LibraryBuilder, KernelLibraryBuilder;
 
-import '../kernel/kernel_shadow_ast.dart' show ShadowField;
+import '../kernel/kernel_shadow_ast.dart' show ShadowField, ShadowMember;
 
 import '../messages.dart' show noLength, templateCantInferTypeDueToCircularity;
 
@@ -272,9 +273,7 @@
     if (formal.type == null) {
       for (Field field in parent.enclosingClass.fields) {
         if (field.name.name == formal.name) {
-          if (field is ShadowField && field.inferenceNode != null) {
-            field.inferenceNode.resolve();
-          }
+          TypeInferenceEngine.resolveInferenceNode(field);
           formal.type = field.type;
           return;
         }
@@ -302,4 +301,13 @@
     ShadowField.setInferenceNode(field, node);
     staticInferenceNodes.add(node);
   }
+
+  static void resolveInferenceNode(Member member) {
+    if (member is ShadowMember) {
+      if (member.inferenceNode != null) {
+        member.inferenceNode.resolve();
+        member.inferenceNode = null;
+      }
+    }
+  }
 }
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 3de6c94..98cbf73 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
@@ -104,7 +104,6 @@
         ExpressionJudgment,
         ShadowClass,
         ShadowField,
-        ShadowMember,
         ShadowTypeInferenceEngine,
         ShadowTypeInferrer,
         VariableDeclarationJudgment,
@@ -545,7 +544,8 @@
 
   TypeInferrerImpl.private(
       this.engine, this.uri, bool topLevel, this.thisType, this.library)
-      : classHierarchy = engine.classHierarchy,
+      : assert((topLevel && library == null) || (!topLevel && library != null)),
+        classHierarchy = engine.classHierarchy,
         instrumentation = topLevel ? null : engine.instrumentation,
         typeSchemaEnvironment = engine.typeSchemaEnvironment,
         isTopLevel = topLevel,
@@ -1840,7 +1840,7 @@
         member = member is SyntheticAccessor
             ? SyntheticAccessor.getField(member)
             : member;
-        ShadowMember.resolveInferenceNode(member);
+        TypeInferenceEngine.resolveInferenceNode(member);
         return member;
       }
     }
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index e1f1b74..cfa04f1 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -30,6 +30,10 @@
 CannotReadSdkSpecification/analyzerCode: Fail
 CannotReadSdkSpecification/example: Fail
 CantDetermineConstness/analyzerCode: Fail
+CantDisambiguateAmbiguousInformation/analyzerCode: Fail # There's no analyzer code for that error yet.
+CantDisambiguateAmbiguousInformation/script: Fail # Can't be tested until 'spread-collections' flag is on.
+CantDisambiguateNotEnoughInformation/analyzerCode: Fail # There's no analyzer code for that error yet.
+CantDisambiguateNotEnoughInformation/script: Fail # Can't be tested until 'spread-collections' flag is on.
 CantInferPackagesFromManyInputs/analyzerCode: Fail
 CantInferPackagesFromManyInputs/example: Fail
 CantInferPackagesFromPackageUri/analyzerCode: Fail
@@ -128,6 +132,7 @@
 ExpectedClassMember/example: Fail
 ExpectedClassOrMixinBody/example: Fail
 ExpectedDeclaration/example: Fail
+ExpectedElseOrComma/example: Fail
 ExpectedFunctionBody/example: Fail
 ExpectedNamedArgument/example: Fail
 ExpectedOneExpression/analyzerCode: Fail
@@ -271,6 +276,8 @@
 NonConstConstructor/example: Fail
 NonConstFactory/example: Fail
 NonInstanceTypeVariableUse/example: Fail
+NonNullAwareSpreadIsNull/analyzerCode: Fail # There's no analyzer code for that error yet.
+NonNullAwareSpreadIsNull/script: Fail # Can't be tested until 'spread-collections' flag is on.
 NonPartOfDirectiveInPart/script1: Fail
 NotAConstantExpression/example: Fail
 NotAType/example: Fail
@@ -337,7 +344,12 @@
 SourceOutlineSummary/analyzerCode: Fail
 SourceOutlineSummary/example: Fail
 SpreadElementTypeMismatch/script: Fail # Can't be tested until 'spread-collections' flag is on.
-SpreadTypeMismatch/analyzerCode: Fail # There's not analyzer code for that error yet.
+SpreadMapEntryElementKeyTypeMismatch/script: Fail # Can't be tested until 'spread-collections' flag is on.
+SpreadMapEntryElementValueTypeMismatch/script: Fail # Can't be tested until 'spread-collections' flag is on.
+SpreadMapEntryTypeMismatch/analyzerCode: Fail # There's no analyzer code for that error yet.
+SpreadMapEntryTypeMismatch/script1: Fail # Can't be tested until 'spread-collections' flag is on.
+SpreadMapEntryTypeMismatch/script2: Fail # Can't be tested until 'spread-collections' flag is on.
+SpreadTypeMismatch/analyzerCode: Fail # There's no analyzer code for that error yet.
 SpreadTypeMismatch/script1: Fail # Can't be tested until 'spread-collections' flag is on.
 SpreadTypeMismatch/script2: Fail # Can't be tested until 'spread-collections' flag is on.
 StackOverflow/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 8b18378..195f967 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -201,6 +201,11 @@
       foo();
     }
 
+ExpectedElseOrComma:
+  index: 94
+  template: "Expected 'else' or comma."
+  analyzerCode: ParserErrorCode.EXPECTED_ELSE_OR_COMMA
+
 ExpectedBlock:
   template: "Expected a block."
   tip: "Try adding {}."
@@ -1533,7 +1538,10 @@
 
       -Dname
       -Dname=value
-        Ignored for now.
+        Define an environment variable in the compile-time environment.
+
+      --no-defines
+        Ignore all -D options and leave environment constants unevaluated.
 
       --
         Stop option parsing, the rest of the command line is assumed to be
@@ -2028,12 +2036,12 @@
   analyzerCode: INVALID_OVERRIDE_REQUIRED
 
 OverrideTypeMismatchParameter:
-  template: "The parameter '#name' of the method '#name2' has type '#type', which does not match the corresponding type in the overridden method, '#type2'."
+  template: "The parameter '#name' of the method '#name2' has type '#type', which does not match the corresponding type, '#type2', in the overridden method, '#name3'."
   tip: "Change to a supertype of '#type2', or, for a covariant parameter, a subtype."
   analyzerCode: INVALID_METHOD_OVERRIDE
 
 OverrideTypeMismatchReturnType:
-  template: "The return type of the method '#name' is '#type', which does not match the return type of the overridden method, '#type2'."
+  template: "The return type of the method '#name' is '#type', which does not match the return type, '#type2', of the overridden method, '#name2'."
   tip: "Change to a subtype of '#type2'."
   analyzerCode: INVALID_METHOD_OVERRIDE
 
@@ -2928,8 +2936,8 @@
     #num3%12.3 ms/libraries.
 
 CantInferTypeDueToInconsistentOverrides:
-  template: "Can't infer the type of '#string': overridden members must all have the same type."
-  tip: "Specify the type explicitly."
+  template: "Can't infer a type for '#name' as some of the inherited members have different types."
+  tip: "Try adding an explicit type."
   analyzerCode: INVALID_METHOD_OVERRIDE
 
 CantInferTypeDueToCircularity:
@@ -3493,3 +3501,65 @@
       List<String> a = <String>["foo"];
       List<int> b = <int>[...a];
     }
+
+SpreadMapEntryTypeMismatch:
+  template: "Unexpected type '#type' of a map spread entry.  Expected 'dynamic' or a Map."
+  script:
+    - |
+      main() {
+        int a = 42;
+        var b = <dynamic, dynamic>{...a};
+      }
+    - |
+      main() {
+        int Function() a = null;
+        var b = <dynamic, dynamic>{...a};
+      }
+
+SpreadMapEntryElementKeyTypeMismatch:
+  template: "Can't assign spread entry keys of type '#type' to map entry keys of type '#type2'."
+  analyzerCode: MAP_KEY_TYPE_NOT_ASSIGNABLE
+  script: >
+    main() {
+      Map<String, int> a = <String, int>{"foo": 42};
+      Map<int, int> b = <int, int>{...a};
+    }
+
+SpreadMapEntryElementValueTypeMismatch:
+  template: "Can't assign spread entry values of type '#type' to map entry values of type '#type2'."
+  analyzerCode: MAP_VALUE_TYPE_NOT_ASSIGNABLE
+  script: >
+    main() {
+      Map<String, int> a = <String, int>{"foo": 42};
+      Map<String, String> b = <String, String>{...a};
+    }
+
+CantDisambiguateNotEnoughInformation:
+  template: "Not enough type information to disambiguate between literal set and literal map."
+  tip: "Try providing type arguments for the literal explicitly to disambiguate it."
+  script: >
+    foo(dynamic spread) {
+      var a = {...spread};
+    }
+
+CantDisambiguateAmbiguousInformation:
+  template: "Both Iterable and Map spread elements encountered in ambiguous literal."
+  script: >
+    foo(Iterable<int> iterableSpread, Map<int, int> mapSpread) {
+      var c = {...iterableSpread, ...mapSpread};
+    }
+
+SpreadElement:
+  template: "Iterable spread."
+  severity: CONTEXT
+
+SpreadMapElement:
+  template: "Map spread."
+  severity: CONTEXT
+
+NonNullAwareSpreadIsNull:
+  template: "Can't spread a value with static type Null."
+  script: >
+    main() {
+      <int>[...null];
+    }
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index 5ca71fb..b3f5034 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -1,7 +1,7 @@
 name: front_end
 # Currently, front_end API is not stable and users should not
 # depend on semver semantics when depending on this package.
-version: 0.1.13
+version: 0.1.14
 author: Dart Team <misc@dartlang.org>
 description: Front end for compilation of Dart code.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/front_end
@@ -11,14 +11,14 @@
   charcode: '^1.1.1'
   convert: '^2.0.1'
   crypto: '^2.0.2'
-  kernel: 0.3.13
+  kernel: 0.3.14
   meta: '^1.1.1'
   package_config: '^1.0.1'
   path: '^1.3.9'
   source_span: '^1.2.3'
   yaml: '^2.1.12'
 dev_dependencies:
-  analyzer: 0.35.3
+  analyzer: 0.35.4
   args: '>=0.13.0 <2.0.0'
   build_integration:
     path: ../build_integration
diff --git a/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart b/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart
index 31ca046..3051815 100644
--- a/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart
@@ -21,47 +21,49 @@
 class CollectionElementTest {
   test_closingBrace() {
     parseEntry(
-      'before }',
+      '[ }',
       [
         'handleIdentifier  expression',
         'handleNoTypeArguments }',
         'handleNoArguments }',
         'handleSend  }',
+        'handleLiteralList 1, [, null, ]',
       ],
-      errors: [error(codeExpectedIdentifier, 7, 1)],
+      errors: [error(codeExpectedIdentifier, 2, 1)],
       expectAfter: '}',
     );
   }
 
   test_comma() {
     parseEntry(
-      'before ,',
+      '[ ,',
       [
         'handleIdentifier  expression',
         'handleNoTypeArguments ,',
         'handleNoArguments ,',
         'handleSend  ,',
+        'handleLiteralList 1, [, null, ]',
       ],
-      errors: [error(codeExpectedIdentifier, 7, 1)],
-      expectAfter: ',',
+      errors: [error(codeExpectedIdentifier, 2, 1)],
     );
   }
 
   test_expression() {
     parseEntry(
-      'before x',
+      '[ x',
       [
         'handleIdentifier x expression',
-        'handleNoTypeArguments ',
-        'handleNoArguments ',
-        'handleSend x ',
+        'handleNoTypeArguments ]',
+        'handleNoArguments ]',
+        'handleSend x ]',
+        'handleLiteralList 1, [, null, ]',
       ],
     );
   }
 
   test_for() {
     parseEntry(
-      'before for (var i = 0; i < 10; ++i) 2',
+      '[ for (var i = 0; i < 10; ++i) 2',
       [
         'beginForControlFlow null for',
         'beginMetadataStar var',
@@ -92,13 +94,14 @@
         'handleForInitializerExpressionStatement for ( ; 1',
         'handleLiteralInt 2',
         'endForControlFlow 2',
+        'handleLiteralList 1, [, null, ]',
       ],
     );
   }
 
   test_forForFor() {
     parseEntry(
-      'before for (var i = 0; i < 10; ++i) for (x in y) for (var a in [6]) 2',
+      '[ for (var i = 0; i < 10; ++i) for (x in y) for (var a in [6]) 2',
       [
         // for (var i = 0; i < 10; ++i)
         'beginForControlFlow null for',
@@ -168,13 +171,14 @@
         'endForInControlFlow 2',
         // end for
         'endForControlFlow 2',
+        'handleLiteralList 1, [, null, ]',
       ],
     );
   }
 
   test_forIfForElse() {
     parseEntry(
-      'before await for (var x in y) if (a) for (b in c) 2 else 7',
+      '[ await for (var x in y) if (a) for (b in c) 2 else 7',
       [
         // await for (var x in y)
         'beginForControlFlow await for',
@@ -228,6 +232,7 @@
         'endIfElseControlFlow 7',
         // end for
         'endForInControlFlow 7',
+        'handleLiteralList 1, [, null, ]',
       ],
       inAsync: true,
     );
@@ -235,7 +240,7 @@
 
   test_forIn() {
     parseEntry(
-      'before await for (var x in y) 2',
+      '[ await for (var x in y) 2',
       [
         'beginForControlFlow await for',
         'beginMetadataStar var',
@@ -257,6 +262,7 @@
         'handleForInLoopParts await for ( in',
         'handleLiteralInt 2',
         'endForInControlFlow 2',
+        'handleLiteralList 1, [, null, ]',
       ],
       inAsync: true,
     );
@@ -264,7 +270,7 @@
 
   test_forInSpread() {
     parseEntry(
-      'before for (var x in y) ...[2]',
+      '[ for (var x in y) ...[2]',
       [
         'beginForControlFlow null for',
         'beginMetadataStar var',
@@ -289,13 +295,14 @@
         'handleLiteralList 1, [, null, ]',
         'handleSpreadExpression ...',
         'endForInControlFlow ]',
+        'handleLiteralList 1, [, null, ]',
       ],
     );
   }
 
   test_forSpreadQ() {
     parseEntry(
-      'before for (i = 0; i < 10; ++i) ...[2]',
+      '[ for (i = 0; i < 10; ++i) ...[2]',
       [
         'beginForControlFlow null for',
         'handleIdentifier i expression',
@@ -324,26 +331,28 @@
         'handleLiteralList 1, [, null, ]',
         'handleSpreadExpression ...',
         'endForControlFlow ]',
+        'handleLiteralList 1, [, null, ]',
       ],
     );
   }
 
   test_if() {
     parseEntry(
-      'before if (true) 2',
+      '[ if (true) 2',
       [
         'beginIfControlFlow if',
         'handleLiteralBool true',
         'handleParenthesizedCondition (',
         'handleLiteralInt 2',
         'endIfControlFlow 2',
+        'handleLiteralList 1, [, null, ]',
       ],
     );
   }
 
   test_ifElse() {
     parseEntry(
-      'before if (true) 2 else 5',
+      '[ if (true) 2 else 5',
       [
         'beginIfControlFlow if',
         'handleLiteralBool true',
@@ -352,13 +361,14 @@
         'handleElseControlFlow else',
         'handleLiteralInt 5',
         'endIfElseControlFlow 5',
+        'handleLiteralList 1, [, null, ]',
       ],
     );
   }
 
   test_ifFor() {
     parseEntry(
-      'before if (true) for (x in y) 2',
+      '[ if (true) for (x in y) 2',
       [
         // if (true)
         'beginIfControlFlow if',
@@ -384,13 +394,14 @@
         'endForInControlFlow 2',
         // end if
         'endIfControlFlow 2',
+        'handleLiteralList 1, [, null, ]',
       ],
     );
   }
 
   test_ifForElseIfFor() {
     parseEntry(
-      'before if (true) for (a in b) 2 else if (c) for (d in e) 5',
+      '[ if (true) for (a in b) 2 else if (c) for (d in e) 5',
       [
         // if (true)
         'beginIfControlFlow if',
@@ -445,13 +456,14 @@
         'endIfControlFlow 5',
         // end else
         'endIfElseControlFlow 5',
+        'handleLiteralList 1, [, null, ]',
       ],
     );
   }
 
   test_ifSpreadQ() {
     parseEntry(
-      'before if (true) ...?[2]',
+      '[ if (true) ...?[2]',
       [
         'beginIfControlFlow if',
         'handleLiteralBool true',
@@ -461,13 +473,14 @@
         'handleLiteralList 1, [, null, ]',
         'handleSpreadExpression ...?',
         'endIfControlFlow ]',
+        'handleLiteralList 1, [, null, ]',
       ],
     );
   }
 
   test_ifElseSpreadQ() {
     parseEntry(
-      'before if (true) ...?[2] else ... const {5}',
+      '[ if (true) ...?[2] else ... const {5}',
       [
         'beginIfControlFlow if',
         'handleLiteralBool true',
@@ -481,34 +494,38 @@
         'handleNoTypeArguments {',
         'handleLiteralInt 5',
         'handleLiteralSetOrMap 1, {, const, }',
-        'endConstLiteral ',
+        'endConstLiteral ]',
         'handleSpreadExpression ...',
         'endIfElseControlFlow }',
+        'handleLiteralList 1, [, null, ]',
       ],
     );
   }
 
   test_intLiteral() {
-    parseEntry('before 1', [
+    parseEntry('[ 1', [
       'handleLiteralInt 1',
+      'handleLiteralList 1, [, null, ]',
     ]);
   }
 
   test_spread() {
-    parseEntry('before ...[1]', [
+    parseEntry('[ ...[1]', [
       'handleNoTypeArguments [',
       'handleLiteralInt 1',
       'handleLiteralList 1, [, null, ]',
       'handleSpreadExpression ...',
+      'handleLiteralList 1, [, null, ]',
     ]);
   }
 
   test_spreadQ() {
-    parseEntry('before ...?[1]', [
+    parseEntry('[ ...?[1]', [
       'handleNoTypeArguments [',
       'handleLiteralInt 1',
       'handleLiteralList 1, [, null, ]',
       'handleSpreadExpression ...?',
+      'handleLiteralList 1, [, null, ]',
     ]);
   }
 
@@ -518,7 +535,7 @@
     final listener = new TestInfoListener();
     final parser = new Parser(listener);
     if (inAsync != null) parser.asyncState = AsyncModifier.Async;
-    final lastConsumed = parser.parseListOrSetLiteralEntry(start);
+    final lastConsumed = parser.parseLiteralListSuffix(start, null);
 
     expect(listener.errors, errors);
     try {
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart b/pkg/front_end/testcases/inference/conflicting_fields.dart
new file mode 100644
index 0000000..0c53592
--- /dev/null
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2019, 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*/
+
+class A {
+  dynamic field1;
+  int field2;
+}
+
+class I {
+  int field1;
+  dynamic field2;
+}
+
+class B extends A implements I {
+  get /*@topType=dynamic*/field1 => null;
+  get /*@topType=dynamic*/field2 => null;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.hierarchy.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.hierarchy.expect
new file mode 100644
index 0000000..058c190
--- /dev/null
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.hierarchy.expect
@@ -0,0 +1,99 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+A:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    A.field1
+    Object.toString
+    A.field2
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+    A.field1
+    A.field2
+
+I:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    I.field1
+    Object.toString
+    I.field2
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+    I.field1
+    I.field2
+
+B:
+  superclasses:
+    Object
+      -> A
+  interfaces: I
+  classMembers:
+    B.field1
+    Object.toString
+    B.field2
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+    A.field1
+    A.field2
+  interfaceMembers:
+    B.field1
+    Object.toString
+    B.field2
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+    A.field1
+    A.field2
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.legacy.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.legacy.expect
new file mode 100644
index 0000000..67e1ae7
--- /dev/null
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.legacy.expect
@@ -0,0 +1,28 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic field1 = null;
+  field core::int field2 = null;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class I extends core::Object {
+  field core::int field1 = null;
+  field dynamic field2 = null;
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+}
+class B extends self::A implements self::I {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  get field1() → dynamic
+    return null;
+  get field2() → dynamic
+    return null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.legacy.transformed.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.legacy.transformed.expect
new file mode 100644
index 0000000..67e1ae7
--- /dev/null
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.legacy.transformed.expect
@@ -0,0 +1,28 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic field1 = null;
+  field core::int field2 = null;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class I extends core::Object {
+  field core::int field1 = null;
+  field dynamic field2 = null;
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+}
+class B extends self::A implements self::I {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  get field1() → dynamic
+    return null;
+  get field2() → dynamic
+    return null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect
new file mode 100644
index 0000000..6963ff2
--- /dev/null
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic field1;
+  field core::int field2;
+  synthetic constructor •() → self::A
+    ;
+}
+class I extends core::Object {
+  field core::int field1;
+  field dynamic field2;
+  synthetic constructor •() → self::I
+    ;
+}
+class B extends self::A implements self::I {
+  synthetic constructor •() → self::B
+    ;
+  get field1() → dynamic
+    ;
+  get field2() → dynamic
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect
new file mode 100644
index 0000000..be7339f
--- /dev/null
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect
@@ -0,0 +1,69 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference/conflicting_fields.dart:18:27: Error: Can't infer a type for 'field1' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   get /*@topType=dynamic*/field1 => null;
+//                           ^
+//
+// pkg/front_end/testcases/inference/conflicting_fields.dart:19:27: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   get /*@topType=dynamic*/field2 => null;
+//                           ^
+//
+// pkg/front_end/testcases/inference/conflicting_fields.dart:19:27: Error: The return type of the method 'B.field2' is 'dynamic', which does not match the return type, 'int', of the overridden method, 'A.field2'.
+// Change to a subtype of 'int'.
+//   get /*@topType=dynamic*/field2 => null;
+//                           ^
+// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is the overridden method ('field2').
+//   int field2;
+//       ^
+//
+// pkg/front_end/testcases/inference/conflicting_fields.dart:18:27: Error: The return type of the method 'B.field1' is 'dynamic', which does not match the return type, 'int', of the overridden method, 'I.field1'.
+// Change to a subtype of 'int'.
+//   get /*@topType=dynamic*/field1 => null;
+//                           ^
+// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is the overridden method ('field1').
+//   int field1;
+//       ^
+//
+// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Error: The return type of the method 'A.field1' is 'dynamic', which does not match the return type, 'int', of the overridden method, 'I.field1'.
+// Change to a subtype of 'int'.
+//   dynamic field1;
+//           ^
+// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is the overridden method ('field1').
+//   int field1;
+//       ^
+// pkg/front_end/testcases/inference/conflicting_fields.dart:17:7: Context: Both members are inherited by the non-abstract class 'B'.
+// class B extends A implements I {
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic field1 = null;
+  field core::int field2 = null;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class I extends core::Object {
+  field core::int field1 = null;
+  field dynamic field2 = null;
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+}
+class B extends self::A implements self::I {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  get field1() → dynamic
+    return null;
+  get field2() → dynamic
+    return null;
+  abstract forwarding-stub set field2(dynamic _) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect
index 1812788..fd0caa9 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect
@@ -2,17 +2,17 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: Can't infer the type of 'a': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: Can't infer a type for 'a' as some of the inherited members have different types.
+// Try adding an explicit type.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: Can't infer the type of 'a': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: Can't infer a type for 'a' as some of the inherited members have different types.
+// Try adding an explicit type.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: The return type of the method 'C1.a' is 'dynamic', which does not match the return type of the overridden method, 'I1'.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: The return type of the method 'C1.a' is 'dynamic', which does not match the return type, 'I1', of the overridden method, 'A.a'.
 //  - 'I1' is from 'pkg/front_end/testcases/inference/conflicts_can_happen.dart'.
 // Change to a subtype of 'I1'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
@@ -21,7 +21,7 @@
 //   final I1 a = null;
 //            ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: The return type of the method 'C1.a' is 'dynamic', which does not match the return type of the overridden method, 'I2'.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: The return type of the method 'C1.a' is 'dynamic', which does not match the return type, 'I2', of the overridden method, 'B.a'.
 //  - 'I2' is from 'pkg/front_end/testcases/inference/conflicts_can_happen.dart'.
 // Change to a subtype of 'I2'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
@@ -30,7 +30,7 @@
 //   final I2 a = null;
 //            ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: The return type of the method 'C2.a' is 'dynamic', which does not match the return type of the overridden method, 'I2'.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: The return type of the method 'C2.a' is 'dynamic', which does not match the return type, 'I2', of the overridden method, 'B.a'.
 //  - 'I2' is from 'pkg/front_end/testcases/inference/conflicts_can_happen.dart'.
 // Change to a subtype of 'I2'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
@@ -39,7 +39,7 @@
 //   final I2 a = null;
 //            ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: The return type of the method 'C2.a' is 'dynamic', which does not match the return type of the overridden method, 'I1'.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: The return type of the method 'C2.a' is 'dynamic', which does not match the return type, 'I1', of the overridden method, 'A.a'.
 //  - 'I1' is from 'pkg/front_end/testcases/inference/conflicts_can_happen.dart'.
 // Change to a subtype of 'I1'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect
index 9b5a480..292f0b7 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect
@@ -2,12 +2,12 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: Can't infer the type of 'a': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: Can't infer a type for 'a' as some of the inherited members have different types.
+// Try adding an explicit type.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: The return type of the method 'C2.a' is 'dynamic', which does not match the return type of the overridden method, 'I1'.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: The return type of the method 'C2.a' is 'dynamic', which does not match the return type, 'I1', of the overridden method, 'A.a'.
 //  - 'I1' is from 'pkg/front_end/testcases/inference/conflicts_can_happen2.dart'.
 // Change to a subtype of 'I1'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
@@ -16,7 +16,7 @@
 //   final I1 a = null;
 //            ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: The return type of the method 'C2.a' is 'dynamic', which does not match the return type of the overridden method, 'I2'.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: The return type of the method 'C2.a' is 'dynamic', which does not match the return type, 'I2', of the overridden method, 'B.a'.
 //  - 'I2' is from 'pkg/front_end/testcases/inference/conflicts_can_happen2.dart'.
 // Change to a subtype of 'I2'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
diff --git a/pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.strong.expect b/pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.strong.expect
index a20bdce..278c138 100644
--- a/pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart:13:49: Error: The return type of the method 'B.x' is 'dynamic', which does not match the return type of the overridden method, 'int'.
+// pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart:13:49: Error: The return type of the method 'B.x' is 'dynamic', which does not match the return type, 'int', of the overridden method, 'A.x'.
 // Change to a subtype of 'int'.
 //   /*error:INVALID_METHOD_OVERRIDE*/ dynamic get x => 3;
 //                                                 ^
diff --git a/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
index 9b3d956..6e70f39 100644
--- a/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
@@ -9,7 +9,7 @@
 //   T m<T>(T x) => x;
 //     ^
 //
-// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:14:64: Error: The return type of the method 'D.m' is 'dynamic', which does not match the return type of the overridden method, 'T'.
+// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:14:64: Error: The return type of the method 'D.m' is 'dynamic', which does not match the return type, 'T', of the overridden method, 'C.m'.
 // Change to a subtype of 'T'.
 // /*@error=OverrideTypeMismatchReturnType*/ /*@topType=dynamic*/ m(
 //                                                                ^
diff --git a/pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.strong.expect
index 5d175fa..04d3c2c 100644
--- a/pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.strong.expect
@@ -9,7 +9,7 @@
 //   /*@topType=dynamic*/ m(/*@topType=dynamic*/ x) => x;
 //                        ^
 //
-// pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:15:54: Error: The parameter 'x' of the method 'D.m' has type 'T', which does not match the corresponding type in the overridden method, 'dynamic'.
+// pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:15:54: Error: The parameter 'x' of the method 'D.m' has type 'T', which does not match the corresponding type, 'dynamic', in the overridden method, 'C.m'.
 // Change to a supertype of 'dynamic', or, for a covariant parameter, a subtype.
 //           T /*@error=OverrideTypeMismatchParameter*/ x) =>
 //                                                      ^
@@ -24,7 +24,7 @@
 //   dynamic g(int x) => x;
 //           ^
 //
-// pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:18:54: Error: The parameter 'x' of the method 'D.g' has type 'T', which does not match the corresponding type in the overridden method, 'int'.
+// pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:18:54: Error: The parameter 'x' of the method 'D.g' has type 'T', which does not match the corresponding type, 'int', in the overridden method, 'C.g'.
 // Change to a supertype of 'int', or, for a covariant parameter, a subtype.
 //           T /*@error=OverrideTypeMismatchParameter*/ x) =>
 //                                                      ^
diff --git a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
index a48dc1a..01203f7 100644
--- a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
@@ -2,22 +2,22 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: Can't infer the type of 'x': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: Can't infer the type of 'x': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: Can't infer the type of 'x': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: The return type of the method 'F.x' is 'dynamic', which does not match the return type of the overridden method, 'int'.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: The return type of the method 'F.x' is 'dynamic', which does not match the return type, 'int', of the overridden method, 'A.x'.
 // Change to a subtype of 'int'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
@@ -25,7 +25,7 @@
 //   int get x;
 //           ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: The return type of the method 'F.x' is 'dynamic', which does not match the return type of the overridden method, 'num'.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: The return type of the method 'F.x' is 'dynamic', which does not match the return type, 'num', of the overridden method, 'C.x'.
 // Change to a subtype of 'num'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
@@ -33,7 +33,7 @@
 //   num get x;
 //           ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: The return type of the method 'G.x' is 'dynamic', which does not match the return type of the overridden method, 'int'.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: The return type of the method 'G.x' is 'dynamic', which does not match the return type, 'int', of the overridden method, 'A.x'.
 // Change to a subtype of 'int'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
@@ -41,7 +41,7 @@
 //   int get x;
 //           ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: The return type of the method 'G.x' is 'dynamic', which does not match the return type of the overridden method, 'double'.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: The return type of the method 'G.x' is 'dynamic', which does not match the return type, 'double', of the overridden method, 'D.x'.
 // Change to a subtype of 'double'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
@@ -49,7 +49,7 @@
 //   double get x;
 //              ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: The return type of the method 'H.x' is 'dynamic', which does not match the return type of the overridden method, 'num'.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: The return type of the method 'H.x' is 'dynamic', which does not match the return type, 'num', of the overridden method, 'C.x'.
 // Change to a subtype of 'num'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
@@ -57,7 +57,7 @@
 //   num get x;
 //           ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: The return type of the method 'H.x' is 'dynamic', which does not match the return type of the overridden method, 'double'.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: The return type of the method 'H.x' is 'dynamic', which does not match the return type, 'double', of the overridden method, 'D.x'.
 // Change to a subtype of 'double'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
diff --git a/pkg/front_end/testcases/inference/infer_method_missing_params.dart.strong.expect b/pkg/front_end/testcases/inference/infer_method_missing_params.dart.strong.expect
index c73b3ed..e47b23c 100644
--- a/pkg/front_end/testcases/inference/infer_method_missing_params.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_method_missing_params.dart.strong.expect
@@ -2,18 +2,18 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/infer_method_missing_params.dart:25:79: Error: Can't infer the type of 'y': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:25:79: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// Try adding an explicit type.
 //       /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ y);
 //                                                                               ^
 //
-// pkg/front_end/testcases/inference/infer_method_missing_params.dart:29:80: Error: Can't infer the type of 'y': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:29:80: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// Try adding an explicit type.
 //       {/*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ y});
 //                                                                                ^
 //
-// pkg/front_end/testcases/inference/infer_method_missing_params.dart:27:80: Error: Can't infer the type of 'y': overridden members must all have the same type.
-// Specify the type explicitly.
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:27:80: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// Try adding an explicit type.
 //       [/*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ y]);
 //                                                                                ^
 //
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.strong.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.strong.expect
index a901909..e21b9d9 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart:13:49: Error: The return type of the method 'B.x' is 'dynamic', which does not match the return type of the overridden method, 'int'.
+// pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart:13:49: Error: The return type of the method 'B.x' is 'dynamic', which does not match the return type, 'int', of the overridden method, 'A.x'.
 // Change to a subtype of 'int'.
 //   /*error:INVALID_METHOD_OVERRIDE*/ dynamic get x => 3;
 //                                                 ^
diff --git a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect
index fe82b93..d33cc4c 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:24: Error: The return type of the method 'B.x' is 'int', which does not match the return type of the overridden method, 'double'.
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:24: Error: The return type of the method 'B.x' is 'int', which does not match the return type, 'double', of the overridden method, 'A.x'.
 // Change to a subtype of 'double'.
 //   var /*@topType=int*/ x;
 //                        ^
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect
index 57b6ceb..9e226c5 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:24: Error: The return type of the method 'C.x' is 'int', which does not match the return type of the overridden method, 'num'.
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:24: Error: The return type of the method 'C.x' is 'int', which does not match the return type, 'num', of the overridden method, 'A.x'.
 // Change to a subtype of 'num'.
 //   var /*@topType=int*/ x;
 //                        ^
diff --git a/pkg/front_end/testcases/override_check_accessor_after_inference.dart.strong.expect b/pkg/front_end/testcases/override_check_accessor_after_inference.dart.strong.expect
index e11b390..1f70d42 100644
--- a/pkg/front_end/testcases/override_check_accessor_after_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_accessor_after_inference.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/override_check_accessor_after_inference.dart:28:51: Error: The return type of the method 'F.y' is 'A', which does not match the return type of the overridden method, 'B'.
+// pkg/front_end/testcases/override_check_accessor_after_inference.dart:28:51: Error: The return type of the method 'F.y' is 'A', which does not match the return type, 'B', of the overridden method, 'D.y'.
 //  - 'A' is from 'pkg/front_end/testcases/override_check_accessor_after_inference.dart'.
 //  - 'B' is from 'pkg/front_end/testcases/override_check_accessor_after_inference.dart'.
 // Change to a subtype of 'B'.
@@ -12,7 +12,7 @@
 //   get y => null; // Inferred type: B
 //       ^
 //
-// pkg/front_end/testcases/override_check_accessor_after_inference.dart:27:57: Error: The parameter 'value' of the method 'F.x' has type 'B', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_accessor_after_inference.dart:27:57: Error: The parameter 'value' of the method 'F.x' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'D.x'.
 //  - 'B' is from 'pkg/front_end/testcases/override_check_accessor_after_inference.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/override_check_accessor_after_inference.dart'.
 // Change to a supertype of 'A', or, for a covariant parameter, a subtype.
diff --git a/pkg/front_end/testcases/override_check_accessor_basic.dart.strong.expect b/pkg/front_end/testcases/override_check_accessor_basic.dart.strong.expect
index 055f4f6..3407e98 100644
--- a/pkg/front_end/testcases/override_check_accessor_basic.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_accessor_basic.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/override_check_accessor_basic.dart:23:56: Error: The return type of the method 'E.y' is 'Object', which does not match the return type of the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_accessor_basic.dart:23:56: Error: The return type of the method 'E.y' is 'Object', which does not match the return type, 'A', of the overridden method, 'C.y'.
 //  - 'Object' is from 'dart:core'.
 //  - 'A' is from 'pkg/front_end/testcases/override_check_accessor_basic.dart'.
 // Change to a subtype of 'A'.
@@ -12,7 +12,7 @@
 //   A get y => null;
 //         ^
 //
-// pkg/front_end/testcases/override_check_accessor_basic.dart:22:57: Error: The parameter 'value' of the method 'E.x' has type 'B', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_accessor_basic.dart:22:57: Error: The parameter 'value' of the method 'E.x' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.x'.
 //  - 'B' is from 'pkg/front_end/testcases/override_check_accessor_basic.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/override_check_accessor_basic.dart'.
 // Change to a supertype of 'A', or, for a covariant parameter, a subtype.
diff --git a/pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.strong.expect b/pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.strong.expect
index 5fa7ead..2b08b5a 100644
--- a/pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:25:50: Error: The parameter 'value' of the method 'D.x4' has type 'B', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:25:50: Error: The parameter 'value' of the method 'D.x4' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.x4'.
 //  - 'B' is from 'pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart'.
 // Change to a supertype of 'A', or, for a covariant parameter, a subtype.
@@ -12,7 +12,7 @@
 //   void set x4(A value) {}
 //            ^
 //
-// pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:27:65: Error: The parameter 'value' of the method 'D.x5' has type 'String', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:27:65: Error: The parameter 'value' of the method 'D.x5' has type 'String', which does not match the corresponding type, 'A', in the overridden method, 'C.x5'.
 //  - 'A' is from 'pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart'.
 // Change to a supertype of 'A', or, for a covariant parameter, a subtype.
 //       covariant String /*@error=OverrideTypeMismatchParameter*/ value) {}
diff --git a/pkg/front_end/testcases/override_check_after_inference.dart.strong.expect b/pkg/front_end/testcases/override_check_after_inference.dart.strong.expect
index 5e5e5ac..0cfd406 100644
--- a/pkg/front_end/testcases/override_check_after_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_after_inference.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/override_check_after_inference.dart:24:53: Error: The parameter 'x' of the method 'F.f' has type 'B', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_after_inference.dart:24:53: Error: The parameter 'x' of the method 'F.f' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'D.f'.
 //  - 'B' is from 'pkg/front_end/testcases/override_check_after_inference.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/override_check_after_inference.dart'.
 // Change to a supertype of 'A', or, for a covariant parameter, a subtype.
diff --git a/pkg/front_end/testcases/override_check_basic.dart.strong.expect b/pkg/front_end/testcases/override_check_basic.dart.strong.expect
index 7810d9b..b7a5ddb 100644
--- a/pkg/front_end/testcases/override_check_basic.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_basic.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/override_check_basic.dart:29:52: Error: The return type of the method 'E.f4' is 'Object', which does not match the return type of the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_basic.dart:29:52: Error: The return type of the method 'E.f4' is 'Object', which does not match the return type, 'A', of the overridden method, 'C.f4'.
 //  - 'Object' is from 'dart:core'.
 //  - 'A' is from 'pkg/front_end/testcases/override_check_basic.dart'.
 // Change to a subtype of 'A'.
@@ -12,7 +12,7 @@
 //   A f4() {}
 //     ^
 //
-// pkg/front_end/testcases/override_check_basic.dart:28:55: Error: The parameter 'x' of the method 'E.f3' has type 'B', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_basic.dart:28:55: Error: The parameter 'x' of the method 'E.f3' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f3'.
 //  - 'B' is from 'pkg/front_end/testcases/override_check_basic.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/override_check_basic.dart'.
 // Change to a supertype of 'A', or, for a covariant parameter, a subtype.
@@ -22,7 +22,7 @@
 //   void f3({A x}) {}
 //        ^
 //
-// pkg/front_end/testcases/override_check_basic.dart:26:54: Error: The parameter 'x' of the method 'E.f1' has type 'B', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_basic.dart:26:54: Error: The parameter 'x' of the method 'E.f1' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f1'.
 //  - 'B' is from 'pkg/front_end/testcases/override_check_basic.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/override_check_basic.dart'.
 // Change to a supertype of 'A', or, for a covariant parameter, a subtype.
@@ -32,7 +32,7 @@
 //   void f1(A x) {}
 //        ^
 //
-// pkg/front_end/testcases/override_check_basic.dart:27:55: Error: The parameter 'x' of the method 'E.f2' has type 'B', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_basic.dart:27:55: Error: The parameter 'x' of the method 'E.f2' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f2'.
 //  - 'B' is from 'pkg/front_end/testcases/override_check_basic.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/override_check_basic.dart'.
 // Change to a supertype of 'A', or, for a covariant parameter, a subtype.
diff --git a/pkg/front_end/testcases/override_check_with_covariant_modifier.dart.strong.expect b/pkg/front_end/testcases/override_check_with_covariant_modifier.dart.strong.expect
index 96fcfd3..d008fb9 100644
--- a/pkg/front_end/testcases/override_check_with_covariant_modifier.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_with_covariant_modifier.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/override_check_with_covariant_modifier.dart:25:69: Error: The parameter 'x' of the method 'D.f5' has type 'String', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_with_covariant_modifier.dart:25:69: Error: The parameter 'x' of the method 'D.f5' has type 'String', which does not match the corresponding type, 'A', in the overridden method, 'C.f5'.
 //  - 'A' is from 'pkg/front_end/testcases/override_check_with_covariant_modifier.dart'.
 // Change to a supertype of 'A', or, for a covariant parameter, a subtype.
 //   void f5(covariant String /*@error=OverrideTypeMismatchParameter*/ x) {}
@@ -11,7 +11,7 @@
 //   void f5(covariant A x) {}
 //        ^
 //
-// pkg/front_end/testcases/override_check_with_covariant_modifier.dart:24:54: Error: The parameter 'x' of the method 'D.f4' has type 'B', which does not match the corresponding type in the overridden method, 'A'.
+// pkg/front_end/testcases/override_check_with_covariant_modifier.dart:24:54: Error: The parameter 'x' of the method 'D.f4' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f4'.
 //  - 'B' is from 'pkg/front_end/testcases/override_check_with_covariant_modifier.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/override_check_with_covariant_modifier.dart'.
 // Change to a supertype of 'A', or, for a covariant parameter, a subtype.
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
index 61b9f49..5fceebe 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:48:7: Error: The return type of the method 'M.y' is 'int', which does not match the return type of the overridden method, 'Object'.
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:48:7: Error: The return type of the method 'M.y' is 'int', which does not match the return type, 'Object', of the overridden method, 'I.y'.
 //  - 'Object' is from 'dart:core'.
 // Change to a subtype of 'Object'.
 //   int y;
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect
index b92f411..450603a 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:39:9: Error: The return type of the method 'M.x' is 'void Function(T)', which does not match the return type of the overridden method, 'void Function(int)'.
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:39:9: Error: The return type of the method 'M.x' is 'void Function(T)', which does not match the return type, 'void Function(int)', of the overridden method, 'B.x'.
 // Change to a subtype of 'void Function(int)'.
 //   T get x => f();
 //         ^
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
index 47119ca..5a1fc12 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:53:18: Error: The parameter 'value' of the method 'M.y' has type 'int', which does not match the corresponding type in the overridden method, 'Object'.
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:53:18: Error: The parameter 'value' of the method 'M.y' has type 'int', which does not match the corresponding type, 'Object', in the overridden method, 'I.y'.
 //  - 'Object' is from 'dart:core'.
 // Change to a supertype of 'Object', or, for a covariant parameter, a subtype.
 //   void set y(int value) {
diff --git a/pkg/front_end/testcases/spread_collection.dart.legacy.expect b/pkg/front_end/testcases/spread_collection.dart.legacy.expect
index 4872fd1..ce54701 100644
--- a/pkg/front_end/testcases/spread_collection.dart.legacy.expect
+++ b/pkg/front_end/testcases/spread_collection.dart.legacy.expect
@@ -18,14 +18,6 @@
 //   final aMap = <int, int>{1: 1, ...{2: 2}, ...?{3: 3}};
 //                                            ^^^^
 //
-// pkg/front_end/testcases/spread_collection.dart:7:36: Error: Expected ':' after this.
-//   final aMap = <int, int>{1: 1, ...{2: 2}, ...?{3: 3}};
-//                                    ^
-//
-// pkg/front_end/testcases/spread_collection.dart:7:48: Error: Expected ':' after this.
-//   final aMap = <int, int>{1: 1, ...{2: 2}, ...?{3: 3}};
-//                                                ^
-//
 // pkg/front_end/testcases/spread_collection.dart:8:25: Error: Unexpected token '...'.
 //   final aSet = <int>{1, ...[2], ...?[3]};
 //                         ^^^
@@ -38,17 +30,13 @@
 //   final aSetOrMap = {...foo()};
 //                      ^^^
 //
-// pkg/front_end/testcases/spread_collection.dart:9:25: Error: Expected ':' after this.
-//   final aSetOrMap = {...foo()};
-//                         ^
-//
 import self as self;
 import "dart:core" as core;
 
 static method main() → dynamic {
-  final dynamic aList = <core::int>[1, <dynamic>[2], <dynamic>[3]];
+  final dynamic aList = <core::int>[1];
   final dynamic aMap = <core::int, core::int>{1: 1};
-  final dynamic aSet = <core::int>{1, <dynamic>[2], <dynamic>[3]};
+  final dynamic aSet = <core::int>{1};
   final dynamic aSetOrMap = <dynamic, dynamic>{};
   core::print(aList);
   core::print(aSet);
diff --git a/pkg/front_end/testcases/spread_collection.dart.legacy.transformed.expect b/pkg/front_end/testcases/spread_collection.dart.legacy.transformed.expect
index 4872fd1..ce54701 100644
--- a/pkg/front_end/testcases/spread_collection.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/spread_collection.dart.legacy.transformed.expect
@@ -18,14 +18,6 @@
 //   final aMap = <int, int>{1: 1, ...{2: 2}, ...?{3: 3}};
 //                                            ^^^^
 //
-// pkg/front_end/testcases/spread_collection.dart:7:36: Error: Expected ':' after this.
-//   final aMap = <int, int>{1: 1, ...{2: 2}, ...?{3: 3}};
-//                                    ^
-//
-// pkg/front_end/testcases/spread_collection.dart:7:48: Error: Expected ':' after this.
-//   final aMap = <int, int>{1: 1, ...{2: 2}, ...?{3: 3}};
-//                                                ^
-//
 // pkg/front_end/testcases/spread_collection.dart:8:25: Error: Unexpected token '...'.
 //   final aSet = <int>{1, ...[2], ...?[3]};
 //                         ^^^
@@ -38,17 +30,13 @@
 //   final aSetOrMap = {...foo()};
 //                      ^^^
 //
-// pkg/front_end/testcases/spread_collection.dart:9:25: Error: Expected ':' after this.
-//   final aSetOrMap = {...foo()};
-//                         ^
-//
 import self as self;
 import "dart:core" as core;
 
 static method main() → dynamic {
-  final dynamic aList = <core::int>[1, <dynamic>[2], <dynamic>[3]];
+  final dynamic aList = <core::int>[1];
   final dynamic aMap = <core::int, core::int>{1: 1};
-  final dynamic aSet = <core::int>{1, <dynamic>[2], <dynamic>[3]};
+  final dynamic aSet = <core::int>{1};
   final dynamic aSetOrMap = <dynamic, dynamic>{};
   core::print(aList);
   core::print(aSet);
diff --git a/pkg/front_end/testcases/spread_collection.dart.strong.expect b/pkg/front_end/testcases/spread_collection.dart.strong.expect
index 4b1c6d9..dbfd7b4 100644
--- a/pkg/front_end/testcases/spread_collection.dart.strong.expect
+++ b/pkg/front_end/testcases/spread_collection.dart.strong.expect
@@ -1,4 +1,12 @@
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/spread_collection.dart:9:21: Error: Not enough type information to disambiguate between literal set and literal map.
+// Try providing type arguments for the literal explicitly to disambiguate it.
+//   final aSetOrMap = {...foo()};
+//                     ^
+//
 import self as self;
 import "dart:core" as core;
 import "dart:collection" as col;
@@ -14,18 +22,30 @@
       for (final core::int #t4 in #t3)
         #t1.{core::List::add}(#t4);
   } =>#t1;
-  final core::Map<core::int, core::int> aMap = <core::int, core::int>{1: 1, invalid-expression "unimplemented spread entry": null, invalid-expression "unimplemented spread entry": null};
-  final core::Set<core::int> aSet = block {
-    final core::Set<core::int> #t5 = col::LinkedHashSet::•<core::int>();
-    #t5.{core::Set::add}(1);
-    for (final core::int #t6 in <core::int>[2])
-      #t5.{core::Set::add}(#t6);
-    final dynamic #t7 = <core::int>[3];
+  final core::Map<core::int, core::int> aMap = block {
+    final core::Map<core::int, core::int> #t5 = <core::int, core::int>{};
+    #t5.{core::Map::[]=}(1, 1);
+    for (final core::MapEntry<core::int, core::int> #t6 in <core::int, core::int>{2: 2}.{core::Map::entries})
+      #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
+    final core::Map<dynamic, dynamic> #t7 = <core::int, core::int>{3: 3};
     if(!#t7.{core::Object::==}(null))
-      for (final core::int #t8 in #t7)
-        #t5.{core::Set::add}(#t8);
+      for (final core::MapEntry<core::int, core::int> #t8 in #t7.{core::Map::entries})
+        #t5.{core::Map::[]=}(#t8.{core::MapEntry::key}, #t8.{core::MapEntry::value});
   } =>#t5;
-  final core::Map<dynamic, dynamic> aSetOrMap = <dynamic, dynamic>{invalid-expression "unimplemented spread entry": null};
+  final core::Set<core::int> aSet = block {
+    final core::Set<core::int> #t9 = col::LinkedHashSet::•<core::int>();
+    #t9.{core::Set::add}(1);
+    for (final core::int #t10 in <core::int>[2])
+      #t9.{core::Set::add}(#t10);
+    final dynamic #t11 = <core::int>[3];
+    if(!#t11.{core::Object::==}(null))
+      for (final core::int #t12 in #t11)
+        #t9.{core::Set::add}(#t12);
+  } =>#t9;
+  final dynamic aSetOrMap = invalid-expression "pkg/front_end/testcases/spread_collection.dart:9:21: Error: Not enough type information to disambiguate between literal set and literal map.
+Try providing type arguments for the literal explicitly to disambiguate it.
+  final aSetOrMap = {...foo()};
+                    ^";
   core::print(aList);
   core::print(aSet);
   core::print(aMap);
diff --git a/pkg/front_end/testcases/spread_collection.dart.strong.transformed.expect b/pkg/front_end/testcases/spread_collection.dart.strong.transformed.expect
index 4b1c6d9..dbfd7b4 100644
--- a/pkg/front_end/testcases/spread_collection.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/spread_collection.dart.strong.transformed.expect
@@ -1,4 +1,12 @@
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/spread_collection.dart:9:21: Error: Not enough type information to disambiguate between literal set and literal map.
+// Try providing type arguments for the literal explicitly to disambiguate it.
+//   final aSetOrMap = {...foo()};
+//                     ^
+//
 import self as self;
 import "dart:core" as core;
 import "dart:collection" as col;
@@ -14,18 +22,30 @@
       for (final core::int #t4 in #t3)
         #t1.{core::List::add}(#t4);
   } =>#t1;
-  final core::Map<core::int, core::int> aMap = <core::int, core::int>{1: 1, invalid-expression "unimplemented spread entry": null, invalid-expression "unimplemented spread entry": null};
-  final core::Set<core::int> aSet = block {
-    final core::Set<core::int> #t5 = col::LinkedHashSet::•<core::int>();
-    #t5.{core::Set::add}(1);
-    for (final core::int #t6 in <core::int>[2])
-      #t5.{core::Set::add}(#t6);
-    final dynamic #t7 = <core::int>[3];
+  final core::Map<core::int, core::int> aMap = block {
+    final core::Map<core::int, core::int> #t5 = <core::int, core::int>{};
+    #t5.{core::Map::[]=}(1, 1);
+    for (final core::MapEntry<core::int, core::int> #t6 in <core::int, core::int>{2: 2}.{core::Map::entries})
+      #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
+    final core::Map<dynamic, dynamic> #t7 = <core::int, core::int>{3: 3};
     if(!#t7.{core::Object::==}(null))
-      for (final core::int #t8 in #t7)
-        #t5.{core::Set::add}(#t8);
+      for (final core::MapEntry<core::int, core::int> #t8 in #t7.{core::Map::entries})
+        #t5.{core::Map::[]=}(#t8.{core::MapEntry::key}, #t8.{core::MapEntry::value});
   } =>#t5;
-  final core::Map<dynamic, dynamic> aSetOrMap = <dynamic, dynamic>{invalid-expression "unimplemented spread entry": null};
+  final core::Set<core::int> aSet = block {
+    final core::Set<core::int> #t9 = col::LinkedHashSet::•<core::int>();
+    #t9.{core::Set::add}(1);
+    for (final core::int #t10 in <core::int>[2])
+      #t9.{core::Set::add}(#t10);
+    final dynamic #t11 = <core::int>[3];
+    if(!#t11.{core::Object::==}(null))
+      for (final core::int #t12 in #t11)
+        #t9.{core::Set::add}(#t12);
+  } =>#t9;
+  final dynamic aSetOrMap = invalid-expression "pkg/front_end/testcases/spread_collection.dart:9:21: Error: Not enough type information to disambiguate between literal set and literal map.
+Try providing type arguments for the literal explicitly to disambiguate it.
+  final aSetOrMap = {...foo()};
+                    ^";
   core::print(aList);
   core::print(aSet);
   core::print(aMap);
diff --git a/pkg/front_end/testcases/spread_collection_inference.dart b/pkg/front_end/testcases/spread_collection_inference.dart
index c1cfb85..6225eca 100644
--- a/pkg/front_end/testcases/spread_collection_inference.dart
+++ b/pkg/front_end/testcases/spread_collection_inference.dart
@@ -9,6 +9,7 @@
 
 foo() {
   List<int> spread = <int>[1, 2, 3];
+  Map<String, int> mapSpread = <String, int>{"foo": 4, "bar": 2};
   int notSpreadInt = 42;
   int Function() notSpreadFunction = null;
 
@@ -17,46 +18,121 @@
 
   var /*@type=Set<dynamic>*/ set10 = <dynamic>{... /*@typeArgs=dynamic*/ []};
 
+  var /*@type=Map<dynamic, dynamic>*/ map10 = <dynamic, dynamic>{...
+    /*@typeArgs=dynamic, dynamic*/ {}};
+
+  var /*@type=Map<dynamic, dynamic>*/ map10ambiguous =
+    /*@typeArgs=dynamic, dynamic*/ {...  /*@typeArgs=dynamic, dynamic*/ {}};
+
   var /*@type=List<int>*/ lhs20 = /*@typeArgs=int*/ [...spread];
 
   var /*@type=Set<int>*/ set20 = /*@typeArgs=int*/ {...spread, 42};
 
+  var /*@type=Set<int>*/ set20ambiguous = /*@typeArgs=int*/ {...spread};
+
+  var /*@type=Map<String, int>*/ map20 = /*@typeArgs=String, int*/
+    {...mapSpread, "baz": 42};
+
+  var /*@type=Map<String, int>*/ map20ambiguous = /*@typeArgs=String, int*/
+    {...mapSpread};
+
   var /*@type=List<dynamic>*/ lhs21 = /*@typeArgs=dynamic*/ [...(spread as
       dynamic)];
 
   var /*@type=Set<dynamic>*/ set21 = /*@typeArgs=dynamic*/ {...(spread as
       dynamic), 42};
 
+  var /*@type=Map<dynamic, dynamic>*/ map21 = /*@typeArgs=dynamic, dynamic*/
+    {...(mapSpread as dynamic), "baz": 42};
+
+  dynamic map21ambiguous = /*@error=CantDisambiguateNotEnoughInformation*/ {...
+    (mapSpread as dynamic)};
+
   List<int> lhs22 = /*@typeArgs=int*/ [... /*@typeArgs=int*/ []];
 
   Set<int> set22 = /*@typeArgs=int*/ {... /*@typeArgs=int*/ [], 42};
 
+  Set<int> set22ambiguous = /*@typeArgs=int*/ {... /*@typeArgs=int*/ []};
+
+  Map<String, int> map22 = /*@typeArgs=String, int*/
+    {... /*@typeArgs=String, int*/ {}};
+
   List<List<int>> lhs23 = /*@typeArgs=List<int>*/ [... /*@typeArgs=List<int>*/
     [/*@typeArgs=int*/ []]];
 
   Set<List<int>> set23 = /*@typeArgs=List<int>*/ {... /*@typeArgs=List<int>*/
     [/*@typeArgs=int*/ []], <int>[42]};
 
+  Set<List<int>> set23ambiguous = /*@typeArgs=List<int>*/
+    {... /*@typeArgs=List<int>*/ [/*@typeArgs=int*/ []]};
+
+  Map<String, List<int>> map23 = /*@typeArgs=String, List<int>*/
+    {... /*@typeArgs=String, List<int>*/ {"baz": /*@typeArgs=int*/ []}};
+
+  dynamic map24ambiguous = /*@error=CantDisambiguateAmbiguousInformation*/ {...
+    spread, ...mapSpread};
+
   int lhs30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ [...spread];
 
   int set30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ {...spread, 42};
 
+  int set30ambiguous = /*@error=InvalidAssignment*/ /*@typeArgs=int*/
+    {...spread};
+
+  int map30 = /*@error=InvalidAssignment*/ /*@typeArgs=String, int*/
+    {...mapSpread, "baz": 42};
+
+  int map30ambiguous = /*@error=InvalidAssignment*/ /*@typeArgs=String, int*/
+    {...mapSpread};
+
   List<dynamic> lhs40 = <dynamic>[... /*@error=SpreadTypeMismatch*/
     notSpreadInt];
 
   Set<dynamic> set40 = <dynamic>{... /*@error=SpreadTypeMismatch*/
     notSpreadInt};
 
+  Map<dynamic, dynamic> map40 = <dynamic, dynamic>{...
+    /*@error=SpreadMapEntryTypeMismatch*/ notSpreadInt};
+
   List<dynamic> lhs50 = <dynamic> [... /*@error=SpreadTypeMismatch*/
     notSpreadFunction];
 
   Set<dynamic> set50 = <dynamic> {... /*@error=SpreadTypeMismatch*/
     notSpreadFunction};
 
+  Map<dynamic, dynamic> map50 = <dynamic, dynamic>{...
+    /*@error=SpreadMapEntryTypeMismatch*/ notSpreadFunction};
+
   List<String> lhs60 = <String>[... /*@error=SpreadElementTypeMismatch*/
     spread];
 
   Set<String> set60 = <String>{... /*@error=SpreadElementTypeMismatch*/ spread};
+
+  Map<int, int> map60 = <int, int>{...
+    /*@error=SpreadMapEntryElementKeyTypeMismatch*/ mapSpread};
+
+  Map<String, String> map61 = <String, String>{...
+    /*@error=SpreadMapEntryElementValueTypeMismatch*/ mapSpread};
+
+  List<int> lhs70 = <int>[... /*@error=NonNullAwareSpreadIsNull*/ null];
+
+  Set<int> set70 = <int>{... /*@error=NonNullAwareSpreadIsNull*/ null};
+
+  var /*@type=Set<dynamic>*/ set71ambiguous = /*@typeArgs=dynamic*/
+    {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+      []};
+
+  Map<String, int> map70 = <String, int>{... /*@error=NonNullAwareSpreadIsNull*/
+    null};
+
+  List<int> lhs80 = <int>[...?null];
+
+  Set<int> set80 = <int>{...?null};
+
+  var /*@type=Set<dynamic>*/ set81ambiguous = /*@typeArgs=dynamic*/
+    {...?null, ... /*@typeArgs=dynamic*/ []};
+
+  Map<String, int> map80 = <String, int>{...?null};
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/spread_collection_inference.dart.legacy.expect b/pkg/front_end/testcases/spread_collection_inference.dart.legacy.expect
index 8af1aa9..b419aeb 100644
--- a/pkg/front_end/testcases/spread_collection_inference.dart.legacy.expect
+++ b/pkg/front_end/testcases/spread_collection_inference.dart.legacy.expect
@@ -2,102 +2,250 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:15:62: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:16:62: Error: Unexpected token '...'.
 //   var /*@type=List<dynamic>*/ lhs10 = /*@typeArgs=dynamic*/ [...
 //                                                              ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:18:48: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:19:48: Error: Unexpected token '...'.
 //   var /*@type=Set<dynamic>*/ set10 = <dynamic>{... /*@typeArgs=dynamic*/ []};
 //                                                ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:20:54: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:21:66: Error: Unexpected token '...'.
+//   var /*@type=Map<dynamic, dynamic>*/ map10 = <dynamic, dynamic>{...
+//                                                                  ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:25:37: Error: Unexpected token '...'.
+//     /*@typeArgs=dynamic, dynamic*/ {...  /*@typeArgs=dynamic, dynamic*/ {}};
+//                                     ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:27:54: Error: Unexpected token '...'.
 //   var /*@type=List<int>*/ lhs20 = /*@typeArgs=int*/ [...spread];
 //                                                      ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:22:53: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:29:53: Error: Unexpected token '...'.
 //   var /*@type=Set<int>*/ set20 = /*@typeArgs=int*/ {...spread, 42};
 //                                                     ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:24:62: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:31:62: Error: Unexpected token '...'.
+//   var /*@type=Set<int>*/ set20ambiguous = /*@typeArgs=int*/ {...spread};
+//                                                              ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:34:6: Error: Unexpected token '...'.
+//     {...mapSpread, "baz": 42};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:37:6: Error: Unexpected token '...'.
+//     {...mapSpread};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:39:62: Error: Unexpected token '...'.
 //   var /*@type=List<dynamic>*/ lhs21 = /*@typeArgs=dynamic*/ [...(spread as
 //                                                              ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:27:61: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:42:61: Error: Unexpected token '...'.
 //   var /*@type=Set<dynamic>*/ set21 = /*@typeArgs=dynamic*/ {...(spread as
 //                                                             ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:30:40: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:46:6: Error: Unexpected token '...'.
+//     {...(mapSpread as dynamic), "baz": 42};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:48:77: Error: Unexpected token '...'.
+//   dynamic map21ambiguous = /*@error=CantDisambiguateNotEnoughInformation*/ {...
+//                                                                             ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:51:40: Error: Unexpected token '...'.
 //   List<int> lhs22 = /*@typeArgs=int*/ [... /*@typeArgs=int*/ []];
 //                                        ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:32:39: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:53:39: Error: Unexpected token '...'.
 //   Set<int> set22 = /*@typeArgs=int*/ {... /*@typeArgs=int*/ [], 42};
 //                                       ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:34:52: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:55:48: Error: Unexpected token '...'.
+//   Set<int> set22ambiguous = /*@typeArgs=int*/ {... /*@typeArgs=int*/ []};
+//                                                ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:58:6: Error: Unexpected token '...'.
+//     {... /*@typeArgs=String, int*/ {}};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:60:52: Error: Unexpected token '...'.
 //   List<List<int>> lhs23 = /*@typeArgs=List<int>*/ [... /*@typeArgs=List<int>*/
 //                                                    ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:37:51: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:63:51: Error: Unexpected token '...'.
 //   Set<List<int>> set23 = /*@typeArgs=List<int>*/ {... /*@typeArgs=List<int>*/
 //                                                   ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:40:63: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:67:6: Error: Unexpected token '...'.
+//     {... /*@typeArgs=List<int>*/ [/*@typeArgs=int*/ []]};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:70:6: Error: Unexpected token '...'.
+//     {... /*@typeArgs=String, List<int>*/ {"baz": /*@typeArgs=int*/ []}};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:72:77: Error: Unexpected token '...'.
+//   dynamic map24ambiguous = /*@error=CantDisambiguateAmbiguousInformation*/ {...
+//                                                                             ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:73:13: Error: Unexpected token '...'.
+//     spread, ...mapSpread};
+//             ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:75:63: Error: Unexpected token '...'.
 //   int lhs30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ [...spread];
 //                                                               ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:42:63: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:77:63: Error: Unexpected token '...'.
 //   int set30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ {...spread, 42};
 //                                                               ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:44:35: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:80:6: Error: Unexpected token '...'.
+//     {...spread};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:83:6: Error: Unexpected token '...'.
+//     {...mapSpread, "baz": 42};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:86:6: Error: Unexpected token '...'.
+//     {...mapSpread};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:88:35: Error: Unexpected token '...'.
 //   List<dynamic> lhs40 = <dynamic>[... /*@error=SpreadTypeMismatch*/
 //                                   ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:47:34: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:91:34: Error: Unexpected token '...'.
 //   Set<dynamic> set40 = <dynamic>{... /*@error=SpreadTypeMismatch*/
 //                                  ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:50:36: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:94:52: Error: Unexpected token '...'.
+//   Map<dynamic, dynamic> map40 = <dynamic, dynamic>{...
+//                                                    ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:97:36: Error: Unexpected token '...'.
 //   List<dynamic> lhs50 = <dynamic> [... /*@error=SpreadTypeMismatch*/
 //                                    ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:53:35: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:100:35: Error: Unexpected token '...'.
 //   Set<dynamic> set50 = <dynamic> {... /*@error=SpreadTypeMismatch*/
 //                                   ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:56:33: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:103:52: Error: Unexpected token '...'.
+//   Map<dynamic, dynamic> map50 = <dynamic, dynamic>{...
+//                                                    ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:106:33: Error: Unexpected token '...'.
 //   List<String> lhs60 = <String>[... /*@error=SpreadElementTypeMismatch*/
 //                                 ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:59:32: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:109:32: Error: Unexpected token '...'.
 //   Set<String> set60 = <String>{... /*@error=SpreadElementTypeMismatch*/ spread};
 //                                ^^^
 //
+// pkg/front_end/testcases/spread_collection_inference.dart:111:36: Error: Unexpected token '...'.
+//   Map<int, int> map60 = <int, int>{...
+//                                    ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:114:48: Error: Unexpected token '...'.
+//   Map<String, String> map61 = <String, String>{...
+//                                                ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:117:27: Error: Unexpected token '...'.
+//   List<int> lhs70 = <int>[... /*@error=NonNullAwareSpreadIsNull*/ null];
+//                           ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:119:26: Error: Unexpected token '...'.
+//   Set<int> set70 = <int>{... /*@error=NonNullAwareSpreadIsNull*/ null};
+//                          ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:122:6: Error: Unexpected token '...'.
+//     {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:122:52: Error: Unexpected token '...'.
+//     {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+//                                                    ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:125:42: Error: Unexpected token '...'.
+//   Map<String, int> map70 = <String, int>{... /*@error=NonNullAwareSpreadIsNull*/
+//                                          ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:128:27: Error: Unexpected token '...?'.
+//   List<int> lhs80 = <int>[...?null];
+//                           ^^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:130:26: Error: Unexpected token '...?'.
+//   Set<int> set80 = <int>{...?null};
+//                          ^^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:133:6: Error: Unexpected token '...?'.
+//     {...?null, ... /*@typeArgs=dynamic*/ []};
+//      ^^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:133:16: Error: Unexpected token '...'.
+//     {...?null, ... /*@typeArgs=dynamic*/ []};
+//                ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:135:42: Error: Unexpected token '...?'.
+//   Map<String, int> map80 = <String, int>{...?null};
+//                                          ^^^^
+//
 import self as self;
 import "dart:core" as core;
 
 static method foo() → dynamic {
   core::List<core::int> spread = <core::int>[1, 2, 3];
+  core::Map<core::String, core::int> mapSpread = <core::String, core::int>{"foo": 4, "bar": 2};
   core::int notSpreadInt = 42;
   () → core::int notSpreadFunction = null;
-  dynamic lhs10 = <dynamic>[<dynamic>[]];
-  dynamic set10 = <dynamic>{<dynamic>[]};
-  dynamic lhs20 = <dynamic>[spread];
-  dynamic set20 = <dynamic>{spread, 42};
-  dynamic lhs21 = <dynamic>[spread as dynamic];
-  dynamic set21 = <dynamic>{spread as dynamic, 42};
-  core::List<core::int> lhs22 = <dynamic>[<dynamic>[]];
-  core::Set<core::int> set22 = <dynamic>{<dynamic>[], 42};
-  core::List<core::List<core::int>> lhs23 = <dynamic>[<dynamic>[<dynamic>[]]];
-  core::Set<core::List<core::int>> set23 = <dynamic>{<dynamic>[<dynamic>[]], <core::int>[42]};
-  core::int lhs30 = <dynamic>[spread];
-  core::int set30 = <dynamic>{spread, 42};
-  core::List<dynamic> lhs40 = <dynamic>[notSpreadInt];
-  core::Set<dynamic> set40 = <dynamic>{notSpreadInt};
-  core::List<dynamic> lhs50 = <dynamic>[notSpreadFunction];
-  core::Set<dynamic> set50 = <dynamic>{notSpreadFunction};
-  core::List<core::String> lhs60 = <core::String>[spread];
-  core::Set<core::String> set60 = <core::String>{spread};
+  dynamic lhs10 = <dynamic>[];
+  dynamic set10 = <dynamic>{};
+  dynamic map10 = <dynamic, dynamic>{};
+  dynamic map10ambiguous = <dynamic, dynamic>{};
+  dynamic lhs20 = <dynamic>[];
+  dynamic set20 = <dynamic>{42};
+  dynamic set20ambiguous = <dynamic, dynamic>{};
+  dynamic map20 = <dynamic, dynamic>{"baz": 42};
+  dynamic map20ambiguous = <dynamic, dynamic>{};
+  dynamic lhs21 = <dynamic>[];
+  dynamic set21 = <dynamic>{42};
+  dynamic map21 = <dynamic, dynamic>{"baz": 42};
+  dynamic map21ambiguous = <dynamic, dynamic>{};
+  core::List<core::int> lhs22 = <dynamic>[];
+  core::Set<core::int> set22 = <dynamic>{42};
+  core::Set<core::int> set22ambiguous = <dynamic, dynamic>{};
+  core::Map<core::String, core::int> map22 = <dynamic, dynamic>{};
+  core::List<core::List<core::int>> lhs23 = <dynamic>[];
+  core::Set<core::List<core::int>> set23 = <dynamic>{<core::int>[42]};
+  core::Set<core::List<core::int>> set23ambiguous = <dynamic, dynamic>{};
+  core::Map<core::String, core::List<core::int>> map23 = <dynamic, dynamic>{};
+  dynamic map24ambiguous = <dynamic, dynamic>{};
+  core::int lhs30 = <dynamic>[];
+  core::int set30 = <dynamic>{42};
+  core::int set30ambiguous = <dynamic, dynamic>{};
+  core::int map30 = <dynamic, dynamic>{"baz": 42};
+  core::int map30ambiguous = <dynamic, dynamic>{};
+  core::List<dynamic> lhs40 = <dynamic>[];
+  core::Set<dynamic> set40 = <dynamic>{};
+  core::Map<dynamic, dynamic> map40 = <dynamic, dynamic>{};
+  core::List<dynamic> lhs50 = <dynamic>[];
+  core::Set<dynamic> set50 = <dynamic>{};
+  core::Map<dynamic, dynamic> map50 = <dynamic, dynamic>{};
+  core::List<core::String> lhs60 = <core::String>[];
+  core::Set<core::String> set60 = <core::String>{};
+  core::Map<core::int, core::int> map60 = <core::int, core::int>{};
+  core::Map<core::String, core::String> map61 = <core::String, core::String>{};
+  core::List<core::int> lhs70 = <core::int>[];
+  core::Set<core::int> set70 = <core::int>{};
+  dynamic set71ambiguous = <dynamic, dynamic>{};
+  core::Map<core::String, core::int> map70 = <core::String, core::int>{};
+  core::List<core::int> lhs80 = <core::int>[];
+  core::Set<core::int> set80 = <core::int>{};
+  dynamic set81ambiguous = <dynamic, dynamic>{};
+  core::Map<core::String, core::int> map80 = <core::String, core::int>{};
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/spread_collection_inference.dart.legacy.transformed.expect b/pkg/front_end/testcases/spread_collection_inference.dart.legacy.transformed.expect
index 8af1aa9..b419aeb 100644
--- a/pkg/front_end/testcases/spread_collection_inference.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/spread_collection_inference.dart.legacy.transformed.expect
@@ -2,102 +2,250 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:15:62: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:16:62: Error: Unexpected token '...'.
 //   var /*@type=List<dynamic>*/ lhs10 = /*@typeArgs=dynamic*/ [...
 //                                                              ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:18:48: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:19:48: Error: Unexpected token '...'.
 //   var /*@type=Set<dynamic>*/ set10 = <dynamic>{... /*@typeArgs=dynamic*/ []};
 //                                                ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:20:54: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:21:66: Error: Unexpected token '...'.
+//   var /*@type=Map<dynamic, dynamic>*/ map10 = <dynamic, dynamic>{...
+//                                                                  ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:25:37: Error: Unexpected token '...'.
+//     /*@typeArgs=dynamic, dynamic*/ {...  /*@typeArgs=dynamic, dynamic*/ {}};
+//                                     ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:27:54: Error: Unexpected token '...'.
 //   var /*@type=List<int>*/ lhs20 = /*@typeArgs=int*/ [...spread];
 //                                                      ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:22:53: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:29:53: Error: Unexpected token '...'.
 //   var /*@type=Set<int>*/ set20 = /*@typeArgs=int*/ {...spread, 42};
 //                                                     ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:24:62: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:31:62: Error: Unexpected token '...'.
+//   var /*@type=Set<int>*/ set20ambiguous = /*@typeArgs=int*/ {...spread};
+//                                                              ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:34:6: Error: Unexpected token '...'.
+//     {...mapSpread, "baz": 42};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:37:6: Error: Unexpected token '...'.
+//     {...mapSpread};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:39:62: Error: Unexpected token '...'.
 //   var /*@type=List<dynamic>*/ lhs21 = /*@typeArgs=dynamic*/ [...(spread as
 //                                                              ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:27:61: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:42:61: Error: Unexpected token '...'.
 //   var /*@type=Set<dynamic>*/ set21 = /*@typeArgs=dynamic*/ {...(spread as
 //                                                             ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:30:40: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:46:6: Error: Unexpected token '...'.
+//     {...(mapSpread as dynamic), "baz": 42};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:48:77: Error: Unexpected token '...'.
+//   dynamic map21ambiguous = /*@error=CantDisambiguateNotEnoughInformation*/ {...
+//                                                                             ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:51:40: Error: Unexpected token '...'.
 //   List<int> lhs22 = /*@typeArgs=int*/ [... /*@typeArgs=int*/ []];
 //                                        ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:32:39: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:53:39: Error: Unexpected token '...'.
 //   Set<int> set22 = /*@typeArgs=int*/ {... /*@typeArgs=int*/ [], 42};
 //                                       ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:34:52: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:55:48: Error: Unexpected token '...'.
+//   Set<int> set22ambiguous = /*@typeArgs=int*/ {... /*@typeArgs=int*/ []};
+//                                                ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:58:6: Error: Unexpected token '...'.
+//     {... /*@typeArgs=String, int*/ {}};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:60:52: Error: Unexpected token '...'.
 //   List<List<int>> lhs23 = /*@typeArgs=List<int>*/ [... /*@typeArgs=List<int>*/
 //                                                    ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:37:51: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:63:51: Error: Unexpected token '...'.
 //   Set<List<int>> set23 = /*@typeArgs=List<int>*/ {... /*@typeArgs=List<int>*/
 //                                                   ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:40:63: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:67:6: Error: Unexpected token '...'.
+//     {... /*@typeArgs=List<int>*/ [/*@typeArgs=int*/ []]};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:70:6: Error: Unexpected token '...'.
+//     {... /*@typeArgs=String, List<int>*/ {"baz": /*@typeArgs=int*/ []}};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:72:77: Error: Unexpected token '...'.
+//   dynamic map24ambiguous = /*@error=CantDisambiguateAmbiguousInformation*/ {...
+//                                                                             ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:73:13: Error: Unexpected token '...'.
+//     spread, ...mapSpread};
+//             ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:75:63: Error: Unexpected token '...'.
 //   int lhs30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ [...spread];
 //                                                               ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:42:63: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:77:63: Error: Unexpected token '...'.
 //   int set30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ {...spread, 42};
 //                                                               ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:44:35: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:80:6: Error: Unexpected token '...'.
+//     {...spread};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:83:6: Error: Unexpected token '...'.
+//     {...mapSpread, "baz": 42};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:86:6: Error: Unexpected token '...'.
+//     {...mapSpread};
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:88:35: Error: Unexpected token '...'.
 //   List<dynamic> lhs40 = <dynamic>[... /*@error=SpreadTypeMismatch*/
 //                                   ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:47:34: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:91:34: Error: Unexpected token '...'.
 //   Set<dynamic> set40 = <dynamic>{... /*@error=SpreadTypeMismatch*/
 //                                  ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:50:36: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:94:52: Error: Unexpected token '...'.
+//   Map<dynamic, dynamic> map40 = <dynamic, dynamic>{...
+//                                                    ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:97:36: Error: Unexpected token '...'.
 //   List<dynamic> lhs50 = <dynamic> [... /*@error=SpreadTypeMismatch*/
 //                                    ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:53:35: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:100:35: Error: Unexpected token '...'.
 //   Set<dynamic> set50 = <dynamic> {... /*@error=SpreadTypeMismatch*/
 //                                   ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:56:33: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:103:52: Error: Unexpected token '...'.
+//   Map<dynamic, dynamic> map50 = <dynamic, dynamic>{...
+//                                                    ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:106:33: Error: Unexpected token '...'.
 //   List<String> lhs60 = <String>[... /*@error=SpreadElementTypeMismatch*/
 //                                 ^^^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:59:32: Error: Unexpected token '...'.
+// pkg/front_end/testcases/spread_collection_inference.dart:109:32: Error: Unexpected token '...'.
 //   Set<String> set60 = <String>{... /*@error=SpreadElementTypeMismatch*/ spread};
 //                                ^^^
 //
+// pkg/front_end/testcases/spread_collection_inference.dart:111:36: Error: Unexpected token '...'.
+//   Map<int, int> map60 = <int, int>{...
+//                                    ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:114:48: Error: Unexpected token '...'.
+//   Map<String, String> map61 = <String, String>{...
+//                                                ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:117:27: Error: Unexpected token '...'.
+//   List<int> lhs70 = <int>[... /*@error=NonNullAwareSpreadIsNull*/ null];
+//                           ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:119:26: Error: Unexpected token '...'.
+//   Set<int> set70 = <int>{... /*@error=NonNullAwareSpreadIsNull*/ null};
+//                          ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:122:6: Error: Unexpected token '...'.
+//     {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+//      ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:122:52: Error: Unexpected token '...'.
+//     {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+//                                                    ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:125:42: Error: Unexpected token '...'.
+//   Map<String, int> map70 = <String, int>{... /*@error=NonNullAwareSpreadIsNull*/
+//                                          ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:128:27: Error: Unexpected token '...?'.
+//   List<int> lhs80 = <int>[...?null];
+//                           ^^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:130:26: Error: Unexpected token '...?'.
+//   Set<int> set80 = <int>{...?null};
+//                          ^^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:133:6: Error: Unexpected token '...?'.
+//     {...?null, ... /*@typeArgs=dynamic*/ []};
+//      ^^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:133:16: Error: Unexpected token '...'.
+//     {...?null, ... /*@typeArgs=dynamic*/ []};
+//                ^^^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:135:42: Error: Unexpected token '...?'.
+//   Map<String, int> map80 = <String, int>{...?null};
+//                                          ^^^^
+//
 import self as self;
 import "dart:core" as core;
 
 static method foo() → dynamic {
   core::List<core::int> spread = <core::int>[1, 2, 3];
+  core::Map<core::String, core::int> mapSpread = <core::String, core::int>{"foo": 4, "bar": 2};
   core::int notSpreadInt = 42;
   () → core::int notSpreadFunction = null;
-  dynamic lhs10 = <dynamic>[<dynamic>[]];
-  dynamic set10 = <dynamic>{<dynamic>[]};
-  dynamic lhs20 = <dynamic>[spread];
-  dynamic set20 = <dynamic>{spread, 42};
-  dynamic lhs21 = <dynamic>[spread as dynamic];
-  dynamic set21 = <dynamic>{spread as dynamic, 42};
-  core::List<core::int> lhs22 = <dynamic>[<dynamic>[]];
-  core::Set<core::int> set22 = <dynamic>{<dynamic>[], 42};
-  core::List<core::List<core::int>> lhs23 = <dynamic>[<dynamic>[<dynamic>[]]];
-  core::Set<core::List<core::int>> set23 = <dynamic>{<dynamic>[<dynamic>[]], <core::int>[42]};
-  core::int lhs30 = <dynamic>[spread];
-  core::int set30 = <dynamic>{spread, 42};
-  core::List<dynamic> lhs40 = <dynamic>[notSpreadInt];
-  core::Set<dynamic> set40 = <dynamic>{notSpreadInt};
-  core::List<dynamic> lhs50 = <dynamic>[notSpreadFunction];
-  core::Set<dynamic> set50 = <dynamic>{notSpreadFunction};
-  core::List<core::String> lhs60 = <core::String>[spread];
-  core::Set<core::String> set60 = <core::String>{spread};
+  dynamic lhs10 = <dynamic>[];
+  dynamic set10 = <dynamic>{};
+  dynamic map10 = <dynamic, dynamic>{};
+  dynamic map10ambiguous = <dynamic, dynamic>{};
+  dynamic lhs20 = <dynamic>[];
+  dynamic set20 = <dynamic>{42};
+  dynamic set20ambiguous = <dynamic, dynamic>{};
+  dynamic map20 = <dynamic, dynamic>{"baz": 42};
+  dynamic map20ambiguous = <dynamic, dynamic>{};
+  dynamic lhs21 = <dynamic>[];
+  dynamic set21 = <dynamic>{42};
+  dynamic map21 = <dynamic, dynamic>{"baz": 42};
+  dynamic map21ambiguous = <dynamic, dynamic>{};
+  core::List<core::int> lhs22 = <dynamic>[];
+  core::Set<core::int> set22 = <dynamic>{42};
+  core::Set<core::int> set22ambiguous = <dynamic, dynamic>{};
+  core::Map<core::String, core::int> map22 = <dynamic, dynamic>{};
+  core::List<core::List<core::int>> lhs23 = <dynamic>[];
+  core::Set<core::List<core::int>> set23 = <dynamic>{<core::int>[42]};
+  core::Set<core::List<core::int>> set23ambiguous = <dynamic, dynamic>{};
+  core::Map<core::String, core::List<core::int>> map23 = <dynamic, dynamic>{};
+  dynamic map24ambiguous = <dynamic, dynamic>{};
+  core::int lhs30 = <dynamic>[];
+  core::int set30 = <dynamic>{42};
+  core::int set30ambiguous = <dynamic, dynamic>{};
+  core::int map30 = <dynamic, dynamic>{"baz": 42};
+  core::int map30ambiguous = <dynamic, dynamic>{};
+  core::List<dynamic> lhs40 = <dynamic>[];
+  core::Set<dynamic> set40 = <dynamic>{};
+  core::Map<dynamic, dynamic> map40 = <dynamic, dynamic>{};
+  core::List<dynamic> lhs50 = <dynamic>[];
+  core::Set<dynamic> set50 = <dynamic>{};
+  core::Map<dynamic, dynamic> map50 = <dynamic, dynamic>{};
+  core::List<core::String> lhs60 = <core::String>[];
+  core::Set<core::String> set60 = <core::String>{};
+  core::Map<core::int, core::int> map60 = <core::int, core::int>{};
+  core::Map<core::String, core::String> map61 = <core::String, core::String>{};
+  core::List<core::int> lhs70 = <core::int>[];
+  core::Set<core::int> set70 = <core::int>{};
+  dynamic set71ambiguous = <dynamic, dynamic>{};
+  core::Map<core::String, core::int> map70 = <core::String, core::int>{};
+  core::List<core::int> lhs80 = <core::int>[];
+  core::Set<core::int> set80 = <core::int>{};
+  dynamic set81ambiguous = <dynamic, dynamic>{};
+  core::Map<core::String, core::int> map80 = <core::String, core::int>{};
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/spread_collection_inference.dart.strong.expect b/pkg/front_end/testcases/spread_collection_inference.dart.strong.expect
index c93245e..fa9fa70 100644
--- a/pkg/front_end/testcases/spread_collection_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/spread_collection_inference.dart.strong.expect
@@ -2,48 +2,114 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:40:62: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
+// pkg/front_end/testcases/spread_collection_inference.dart:48:76: Error: Not enough type information to disambiguate between literal set and literal map.
+// Try providing type arguments for the literal explicitly to disambiguate it.
+//   dynamic map21ambiguous = /*@error=CantDisambiguateNotEnoughInformation*/ {...
+//                                                                            ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:72:76: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+//   dynamic map24ambiguous = /*@error=CantDisambiguateAmbiguousInformation*/ {...
+//                                                                            ^
+// pkg/front_end/testcases/spread_collection_inference.dart:73:5: Context: Iterable spread.
+//     spread, ...mapSpread};
+//     ^
+// pkg/front_end/testcases/spread_collection_inference.dart:73:16: Context: Map spread.
+//     spread, ...mapSpread};
+//                ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:75:62: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
 //  - 'List' is from 'dart:core'.
 // Try changing the type of the left hand side, or casting the right hand side to 'int'.
 //   int lhs30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ [...spread];
 //                                                              ^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:42:62: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
+// pkg/front_end/testcases/spread_collection_inference.dart:77:62: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
 //  - 'Set' is from 'dart:core'.
 // Try changing the type of the left hand side, or casting the right hand side to 'int'.
 //   int set30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ {...spread, 42};
 //                                                              ^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:45:5: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
+// pkg/front_end/testcases/spread_collection_inference.dart:80:5: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
+//  - 'Set' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+//     {...spread};
+//     ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:83:5: Error: A value of type 'Map<String, int>' can't be assigned to a variable of type 'int'.
+//  - 'Map' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+//     {...mapSpread, "baz": 42};
+//     ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:86:5: Error: A value of type 'Map<String, int>' can't be assigned to a variable of type 'int'.
+//  - 'Map' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+//     {...mapSpread};
+//     ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:89:5: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
 //     notSpreadInt];
 //     ^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:48:5: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
+// pkg/front_end/testcases/spread_collection_inference.dart:92:5: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
 //     notSpreadInt};
 //     ^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:51:5: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
+// pkg/front_end/testcases/spread_collection_inference.dart:95:43: Error: Unexpected type 'int' of a map spread entry.  Expected 'dynamic' or a Map.
+//     /*@error=SpreadMapEntryTypeMismatch*/ notSpreadInt};
+//                                           ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:98:5: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
 //     notSpreadFunction];
 //     ^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:54:5: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
+// pkg/front_end/testcases/spread_collection_inference.dart:101:5: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
 //     notSpreadFunction};
 //     ^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:57:5: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+// pkg/front_end/testcases/spread_collection_inference.dart:104:43: Error: Unexpected type 'int Function()' of a map spread entry.  Expected 'dynamic' or a Map.
+//     /*@error=SpreadMapEntryTypeMismatch*/ notSpreadFunction};
+//                                           ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:107:5: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
 //     spread];
 //     ^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:59:73: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+// pkg/front_end/testcases/spread_collection_inference.dart:109:73: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
 //   Set<String> set60 = <String>{... /*@error=SpreadElementTypeMismatch*/ spread};
 //                                                                         ^
 //
+// pkg/front_end/testcases/spread_collection_inference.dart:112:53: Error: Can't assign spread entry keys of type 'String' to map entry keys of type 'int'.
+//     /*@error=SpreadMapEntryElementKeyTypeMismatch*/ mapSpread};
+//                                                     ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:115:55: Error: Can't assign spread entry values of type 'int' to map entry values of type 'String'.
+//     /*@error=SpreadMapEntryElementValueTypeMismatch*/ mapSpread};
+//                                                       ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:117:67: Error: Can't spread a value with static type Null.
+//   List<int> lhs70 = <int>[... /*@error=NonNullAwareSpreadIsNull*/ null];
+//                                                                   ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:119:66: Error: Can't spread a value with static type Null.
+//   Set<int> set70 = <int>{... /*@error=NonNullAwareSpreadIsNull*/ null};
+//                                                                  ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:122:46: Error: Can't spread a value with static type Null.
+//     {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+//                                              ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:126:5: Error: Can't spread a value with static type Null.
+//     null};
+//     ^
+//
 import self as self;
 import "dart:core" as core;
 import "dart:collection" as col;
 
 static method foo() → dynamic {
   core::List<core::int> spread = <core::int>[1, 2, 3];
+  core::Map<core::String, core::int> mapSpread = <core::String, core::int>{"foo": 4, "bar": 2};
   core::int notSpreadInt = 42;
   () → core::int notSpreadFunction = null;
   core::List<dynamic> lhs10 = block {
@@ -56,86 +122,232 @@
     for (final dynamic #t4 in <dynamic>[])
       #t3.{core::Set::add}(#t4);
   } =>#t3;
-  core::List<core::int> lhs20 = block {
-    final core::List<core::int> #t5 = <core::int>[];
-    for (final core::int #t6 in spread)
-      #t5.{core::List::add}(#t6);
+  core::Map<dynamic, dynamic> map10 = block {
+    final core::Map<dynamic, dynamic> #t5 = <dynamic, dynamic>{};
+    for (final core::MapEntry<dynamic, dynamic> #t6 in <dynamic, dynamic>{}.{core::Map::entries})
+      #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
   } =>#t5;
-  core::Set<core::int> set20 = block {
-    final core::Set<core::int> #t7 = col::LinkedHashSet::•<core::int>();
-    for (final core::int #t8 in spread)
-      #t7.{core::Set::add}(#t8);
-    #t7.{core::Set::add}(42);
+  core::Map<dynamic, dynamic> map10ambiguous = block {
+    final core::Map<dynamic, dynamic> #t7 = <dynamic, dynamic>{};
+    for (final core::MapEntry<dynamic, dynamic> #t8 in <dynamic, dynamic>{}.{core::Map::entries})
+      #t7.{core::Map::[]=}(#t8.{core::MapEntry::key}, #t8.{core::MapEntry::value});
   } =>#t7;
-  core::List<dynamic> lhs21 = block {
-    final core::List<dynamic> #t9 = <dynamic>[];
-    for (final dynamic #t10 in (spread as dynamic) as{TypeError} core::Iterable<dynamic>)
+  core::List<core::int> lhs20 = block {
+    final core::List<core::int> #t9 = <core::int>[];
+    for (final core::int #t10 in spread)
       #t9.{core::List::add}(#t10);
   } =>#t9;
-  core::Set<dynamic> set21 = block {
-    final core::Set<dynamic> #t11 = col::LinkedHashSet::•<dynamic>();
-    for (final dynamic #t12 in (spread as dynamic) as{TypeError} core::Iterable<dynamic>)
+  core::Set<core::int> set20 = block {
+    final core::Set<core::int> #t11 = col::LinkedHashSet::•<core::int>();
+    for (final core::int #t12 in spread)
       #t11.{core::Set::add}(#t12);
     #t11.{core::Set::add}(42);
   } =>#t11;
-  core::List<core::int> lhs22 = block {
-    final core::List<core::int> #t13 = <core::int>[];
-    for (final core::int #t14 in <core::int>[])
-      #t13.{core::List::add}(#t14);
+  core::Set<core::int> set20ambiguous = block {
+    final core::Set<core::int> #t13 = col::LinkedHashSet::•<core::int>();
+    for (final core::int #t14 in spread)
+      #t13.{core::Set::add}(#t14);
   } =>#t13;
-  core::Set<core::int> set22 = block {
-    final core::Set<core::int> #t15 = col::LinkedHashSet::•<core::int>();
-    for (final core::int #t16 in <core::int>[])
-      #t15.{core::Set::add}(#t16);
-    #t15.{core::Set::add}(42);
+  core::Map<core::String, core::int> map20 = block {
+    final core::Map<core::String, core::int> #t15 = <core::String, core::int>{};
+    for (final core::MapEntry<core::String, core::int> #t16 in mapSpread.{core::Map::entries})
+      #t15.{core::Map::[]=}(#t16.{core::MapEntry::key}, #t16.{core::MapEntry::value});
+    #t15.{core::Map::[]=}("baz", 42);
   } =>#t15;
-  core::List<core::List<core::int>> lhs23 = block {
-    final core::List<core::List<core::int>> #t17 = <core::List<core::int>>[];
-    for (final core::List<core::int> #t18 in <core::List<core::int>>[<core::int>[]])
-      #t17.{core::List::add}(#t18);
+  core::Map<core::String, core::int> map20ambiguous = block {
+    final core::Map<core::String, core::int> #t17 = <core::String, core::int>{};
+    for (final core::MapEntry<core::String, core::int> #t18 in mapSpread.{core::Map::entries})
+      #t17.{core::Map::[]=}(#t18.{core::MapEntry::key}, #t18.{core::MapEntry::value});
   } =>#t17;
-  core::Set<core::List<core::int>> set23 = block {
-    final core::Set<core::List<core::int>> #t19 = col::LinkedHashSet::•<core::List<core::int>>();
-    for (final core::List<core::int> #t20 in <core::List<core::int>>[<core::int>[]])
-      #t19.{core::Set::add}(#t20);
-    #t19.{core::Set::add}(<core::int>[42]);
+  core::List<dynamic> lhs21 = block {
+    final core::List<dynamic> #t19 = <dynamic>[];
+    for (final dynamic #t20 in (spread as dynamic) as{TypeError} core::Iterable<dynamic>)
+      #t19.{core::List::add}(#t20);
   } =>#t19;
-  core::int lhs30 = let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:40:62: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
+  core::Set<dynamic> set21 = block {
+    final core::Set<dynamic> #t21 = col::LinkedHashSet::•<dynamic>();
+    for (final dynamic #t22 in (spread as dynamic) as{TypeError} core::Iterable<dynamic>)
+      #t21.{core::Set::add}(#t22);
+    #t21.{core::Set::add}(42);
+  } =>#t21;
+  core::Map<dynamic, dynamic> map21 = block {
+    final core::Map<dynamic, dynamic> #t23 = <dynamic, dynamic>{};
+    for (final core::MapEntry<dynamic, dynamic> #t24 in ((mapSpread as dynamic) as{TypeError} core::Map<dynamic, dynamic>).{core::Map::entries})
+      #t23.{core::Map::[]=}(#t24.{core::MapEntry::key}, #t24.{core::MapEntry::value});
+    #t23.{core::Map::[]=}("baz", 42);
+  } =>#t23;
+  dynamic map21ambiguous = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:48:76: Error: Not enough type information to disambiguate between literal set and literal map.
+Try providing type arguments for the literal explicitly to disambiguate it.
+  dynamic map21ambiguous = /*@error=CantDisambiguateNotEnoughInformation*/ {...
+                                                                           ^";
+  core::List<core::int> lhs22 = block {
+    final core::List<core::int> #t25 = <core::int>[];
+    for (final core::int #t26 in <core::int>[])
+      #t25.{core::List::add}(#t26);
+  } =>#t25;
+  core::Set<core::int> set22 = block {
+    final core::Set<core::int> #t27 = col::LinkedHashSet::•<core::int>();
+    for (final core::int #t28 in <core::int>[])
+      #t27.{core::Set::add}(#t28);
+    #t27.{core::Set::add}(42);
+  } =>#t27;
+  core::Set<core::int> set22ambiguous = block {
+    final core::Set<core::int> #t29 = col::LinkedHashSet::•<core::int>();
+    for (final core::int #t30 in <core::int>[])
+      #t29.{core::Set::add}(#t30);
+  } =>#t29;
+  core::Map<core::String, core::int> map22 = block {
+    final core::Map<core::String, core::int> #t31 = <core::String, core::int>{};
+    for (final core::MapEntry<core::String, core::int> #t32 in <core::String, core::int>{}.{core::Map::entries})
+      #t31.{core::Map::[]=}(#t32.{core::MapEntry::key}, #t32.{core::MapEntry::value});
+  } =>#t31;
+  core::List<core::List<core::int>> lhs23 = block {
+    final core::List<core::List<core::int>> #t33 = <core::List<core::int>>[];
+    for (final core::List<core::int> #t34 in <core::List<core::int>>[<core::int>[]])
+      #t33.{core::List::add}(#t34);
+  } =>#t33;
+  core::Set<core::List<core::int>> set23 = block {
+    final core::Set<core::List<core::int>> #t35 = col::LinkedHashSet::•<core::List<core::int>>();
+    for (final core::List<core::int> #t36 in <core::List<core::int>>[<core::int>[]])
+      #t35.{core::Set::add}(#t36);
+    #t35.{core::Set::add}(<core::int>[42]);
+  } =>#t35;
+  core::Set<core::List<core::int>> set23ambiguous = block {
+    final core::Set<core::List<core::int>> #t37 = col::LinkedHashSet::•<core::List<core::int>>();
+    for (final core::List<core::int> #t38 in <core::List<core::int>>[<core::int>[]])
+      #t37.{core::Set::add}(#t38);
+  } =>#t37;
+  core::Map<core::String, core::List<core::int>> map23 = block {
+    final core::Map<core::String, core::List<core::int>> #t39 = <core::String, core::List<core::int>>{};
+    for (final core::MapEntry<core::String, core::List<core::int>> #t40 in <core::String, core::List<core::int>>{"baz": <core::int>[]}.{core::Map::entries})
+      #t39.{core::Map::[]=}(#t40.{core::MapEntry::key}, #t40.{core::MapEntry::value});
+  } =>#t39;
+  dynamic map24ambiguous = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:72:76: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+  dynamic map24ambiguous = /*@error=CantDisambiguateAmbiguousInformation*/ {...
+                                                                           ^";
+  core::int lhs30 = let final<BottomType> #t41 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:75:62: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
  - 'List' is from 'dart:core'.
 Try changing the type of the left hand side, or casting the right hand side to 'int'.
   int lhs30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ [...spread];
                                                              ^" in ( block {
-    final core::List<core::int> #t22 = <core::int>[];
-    for (final core::int #t23 in spread)
-      #t22.{core::List::add}(#t23);
-  } =>#t22) as{TypeError} core::int;
-  core::int set30 = let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:42:62: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
+    final core::List<core::int> #t42 = <core::int>[];
+    for (final core::int #t43 in spread)
+      #t42.{core::List::add}(#t43);
+  } =>#t42) as{TypeError} core::int;
+  core::int set30 = let final<BottomType> #t44 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:77:62: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
  - 'Set' is from 'dart:core'.
 Try changing the type of the left hand side, or casting the right hand side to 'int'.
   int set30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ {...spread, 42};
                                                              ^" in ( block {
-    final core::Set<core::int> #t25 = col::LinkedHashSet::•<core::int>();
-    for (final core::int #t26 in spread)
-      #t25.{core::Set::add}(#t26);
-    #t25.{core::Set::add}(42);
-  } =>#t25) as{TypeError} core::int;
-  core::List<dynamic> lhs40 = <dynamic>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:45:5: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
+    final core::Set<core::int> #t45 = col::LinkedHashSet::•<core::int>();
+    for (final core::int #t46 in spread)
+      #t45.{core::Set::add}(#t46);
+    #t45.{core::Set::add}(42);
+  } =>#t45) as{TypeError} core::int;
+  core::int set30ambiguous = let final<BottomType> #t47 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:80:5: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
+ - 'Set' is from 'dart:core'.
+Try changing the type of the left hand side, or casting the right hand side to 'int'.
+    {...spread};
+    ^" in ( block {
+    final core::Set<core::int> #t48 = col::LinkedHashSet::•<core::int>();
+    for (final core::int #t49 in spread)
+      #t48.{core::Set::add}(#t49);
+  } =>#t48) as{TypeError} core::int;
+  core::int map30 = let final<BottomType> #t50 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:83:5: Error: A value of type 'Map<String, int>' can't be assigned to a variable of type 'int'.
+ - 'Map' is from 'dart:core'.
+Try changing the type of the left hand side, or casting the right hand side to 'int'.
+    {...mapSpread, \"baz\": 42};
+    ^" in ( block {
+    final core::Map<core::String, core::int> #t51 = <core::String, core::int>{};
+    for (final core::MapEntry<core::String, core::int> #t52 in mapSpread.{core::Map::entries})
+      #t51.{core::Map::[]=}(#t52.{core::MapEntry::key}, #t52.{core::MapEntry::value});
+    #t51.{core::Map::[]=}("baz", 42);
+  } =>#t51) as{TypeError} core::int;
+  core::int map30ambiguous = let final<BottomType> #t53 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:86:5: Error: A value of type 'Map<String, int>' can't be assigned to a variable of type 'int'.
+ - 'Map' is from 'dart:core'.
+Try changing the type of the left hand side, or casting the right hand side to 'int'.
+    {...mapSpread};
+    ^" in ( block {
+    final core::Map<core::String, core::int> #t54 = <core::String, core::int>{};
+    for (final core::MapEntry<core::String, core::int> #t55 in mapSpread.{core::Map::entries})
+      #t54.{core::Map::[]=}(#t55.{core::MapEntry::key}, #t55.{core::MapEntry::value});
+  } =>#t54) as{TypeError} core::int;
+  core::List<dynamic> lhs40 = <dynamic>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:89:5: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
     notSpreadInt];
     ^"];
-  core::Set<dynamic> set40 = let final core::Set<dynamic> #t27 = col::LinkedHashSet::•<dynamic>() in let final dynamic #t28 = #t27.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:48:5: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
+  core::Set<dynamic> set40 = let final core::Set<dynamic> #t56 = col::LinkedHashSet::•<dynamic>() in let final dynamic #t57 = #t56.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:92:5: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
     notSpreadInt};
-    ^") in #t27;
-  core::List<dynamic> lhs50 = <dynamic>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:51:5: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
+    ^") in #t56;
+  core::Map<dynamic, dynamic> map40 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:95:43: Error: Unexpected type 'int' of a map spread entry.  Expected 'dynamic' or a Map.
+    /*@error=SpreadMapEntryTypeMismatch*/ notSpreadInt};
+                                          ^": null};
+  core::List<dynamic> lhs50 = <dynamic>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:98:5: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
     notSpreadFunction];
     ^"];
-  core::Set<dynamic> set50 = let final core::Set<dynamic> #t29 = col::LinkedHashSet::•<dynamic>() in let final dynamic #t30 = #t29.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:54:5: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
+  core::Set<dynamic> set50 = let final core::Set<dynamic> #t58 = col::LinkedHashSet::•<dynamic>() in let final dynamic #t59 = #t58.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:101:5: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
     notSpreadFunction};
-    ^") in #t29;
-  core::List<core::String> lhs60 = <core::String>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:57:5: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+    ^") in #t58;
+  core::Map<dynamic, dynamic> map50 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:104:43: Error: Unexpected type 'int Function()' of a map spread entry.  Expected 'dynamic' or a Map.
+    /*@error=SpreadMapEntryTypeMismatch*/ notSpreadFunction};
+                                          ^": null};
+  core::List<core::String> lhs60 = <core::String>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:107:5: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
     spread];
     ^"];
-  core::Set<core::String> set60 = let final core::Set<core::String> #t31 = col::LinkedHashSet::•<core::String>() in let final dynamic #t32 = #t31.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:59:73: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+  core::Set<core::String> set60 = let final core::Set<core::String> #t60 = col::LinkedHashSet::•<core::String>() in let final dynamic #t61 = #t60.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:109:73: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
   Set<String> set60 = <String>{... /*@error=SpreadElementTypeMismatch*/ spread};
-                                                                        ^") in #t31;
+                                                                        ^") in #t60;
+  core::Map<core::int, core::int> map60 = <core::int, core::int>{invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:112:53: Error: Can't assign spread entry keys of type 'String' to map entry keys of type 'int'.
+    /*@error=SpreadMapEntryElementKeyTypeMismatch*/ mapSpread};
+                                                    ^": null};
+  core::Map<core::String, core::String> map61 = <core::String, core::String>{null: invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:115:55: Error: Can't assign spread entry values of type 'int' to map entry values of type 'String'.
+    /*@error=SpreadMapEntryElementValueTypeMismatch*/ mapSpread};
+                                                      ^"};
+  core::List<core::int> lhs70 = <core::int>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:117:67: Error: Can't spread a value with static type Null.
+  List<int> lhs70 = <int>[... /*@error=NonNullAwareSpreadIsNull*/ null];
+                                                                  ^"];
+  core::Set<core::int> set70 = let final core::Set<core::int> #t62 = col::LinkedHashSet::•<core::int>() in let final dynamic #t63 = #t62.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:119:66: Error: Can't spread a value with static type Null.
+  Set<int> set70 = <int>{... /*@error=NonNullAwareSpreadIsNull*/ null};
+                                                                 ^") in #t62;
+  core::Set<dynamic> set71ambiguous = block {
+    final core::Set<dynamic> #t64 = col::LinkedHashSet::•<dynamic>();
+    #t64.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:122:46: Error: Can't spread a value with static type Null.
+    {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+                                             ^");
+    for (final dynamic #t65 in <dynamic>[])
+      #t64.{core::Set::add}(#t65);
+  } =>#t64;
+  core::Map<core::String, core::int> map70 = <core::String, core::int>{invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:126:5: Error: Can't spread a value with static type Null.
+    null};
+    ^": null};
+  core::List<core::int> lhs80 = block {
+    final core::List<core::int> #t66 = <core::int>[];
+    final dynamic #t67 = null;
+    if(!#t67.{core::Object::==}(null))
+      for (final core::int #t68 in #t67)
+        #t66.{core::List::add}(#t68);
+  } =>#t66;
+  core::Set<core::int> set80 = block {
+    final core::Set<core::int> #t69 = col::LinkedHashSet::•<core::int>();
+    final dynamic #t70 = null;
+    if(!#t70.{core::Object::==}(null))
+      for (final core::int #t71 in #t70)
+        #t69.{core::Set::add}(#t71);
+  } =>#t69;
+  core::Set<dynamic> set81ambiguous = block {
+    final core::Set<dynamic> #t72 = col::LinkedHashSet::•<dynamic>();
+    final dynamic #t73 = null;
+    if(!#t73.{core::Object::==}(null))
+      for (final dynamic #t74 in #t73)
+        #t72.{core::Set::add}(#t74);
+    for (final dynamic #t75 in <dynamic>[])
+      #t72.{core::Set::add}(#t75);
+  } =>#t72;
+  core::Map<core::String, core::int> map80 = block {
+    final core::Map<core::String, core::int> #t76 = <core::String, core::int>{};
+    final core::Map<dynamic, dynamic> #t77 = null;
+    if(!#t77.{core::Object::==}(null))
+      for (final core::MapEntry<core::String, core::int> #t78 in #t77.{core::Map::entries})
+        #t76.{core::Map::[]=}(#t78.{core::MapEntry::key}, #t78.{core::MapEntry::value});
+  } =>#t76;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/spread_collection_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/spread_collection_inference.dart.strong.transformed.expect
index 81ec36f..d9fbaef 100644
--- a/pkg/front_end/testcases/spread_collection_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/spread_collection_inference.dart.strong.transformed.expect
@@ -2,48 +2,114 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:40:62: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
+// pkg/front_end/testcases/spread_collection_inference.dart:48:76: Error: Not enough type information to disambiguate between literal set and literal map.
+// Try providing type arguments for the literal explicitly to disambiguate it.
+//   dynamic map21ambiguous = /*@error=CantDisambiguateNotEnoughInformation*/ {...
+//                                                                            ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:72:76: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+//   dynamic map24ambiguous = /*@error=CantDisambiguateAmbiguousInformation*/ {...
+//                                                                            ^
+// pkg/front_end/testcases/spread_collection_inference.dart:73:5: Context: Iterable spread.
+//     spread, ...mapSpread};
+//     ^
+// pkg/front_end/testcases/spread_collection_inference.dart:73:16: Context: Map spread.
+//     spread, ...mapSpread};
+//                ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:75:62: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
 //  - 'List' is from 'dart:core'.
 // Try changing the type of the left hand side, or casting the right hand side to 'int'.
 //   int lhs30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ [...spread];
 //                                                              ^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:42:62: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
+// pkg/front_end/testcases/spread_collection_inference.dart:77:62: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
 //  - 'Set' is from 'dart:core'.
 // Try changing the type of the left hand side, or casting the right hand side to 'int'.
 //   int set30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ {...spread, 42};
 //                                                              ^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:45:5: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
+// pkg/front_end/testcases/spread_collection_inference.dart:80:5: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
+//  - 'Set' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+//     {...spread};
+//     ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:83:5: Error: A value of type 'Map<String, int>' can't be assigned to a variable of type 'int'.
+//  - 'Map' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+//     {...mapSpread, "baz": 42};
+//     ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:86:5: Error: A value of type 'Map<String, int>' can't be assigned to a variable of type 'int'.
+//  - 'Map' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+//     {...mapSpread};
+//     ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:89:5: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
 //     notSpreadInt];
 //     ^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:48:5: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
+// pkg/front_end/testcases/spread_collection_inference.dart:92:5: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
 //     notSpreadInt};
 //     ^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:51:5: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
+// pkg/front_end/testcases/spread_collection_inference.dart:95:43: Error: Unexpected type 'int' of a map spread entry.  Expected 'dynamic' or a Map.
+//     /*@error=SpreadMapEntryTypeMismatch*/ notSpreadInt};
+//                                           ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:98:5: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
 //     notSpreadFunction];
 //     ^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:54:5: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
+// pkg/front_end/testcases/spread_collection_inference.dart:101:5: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
 //     notSpreadFunction};
 //     ^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:57:5: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+// pkg/front_end/testcases/spread_collection_inference.dart:104:43: Error: Unexpected type 'int Function()' of a map spread entry.  Expected 'dynamic' or a Map.
+//     /*@error=SpreadMapEntryTypeMismatch*/ notSpreadFunction};
+//                                           ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:107:5: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
 //     spread];
 //     ^
 //
-// pkg/front_end/testcases/spread_collection_inference.dart:59:73: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+// pkg/front_end/testcases/spread_collection_inference.dart:109:73: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
 //   Set<String> set60 = <String>{... /*@error=SpreadElementTypeMismatch*/ spread};
 //                                                                         ^
 //
+// pkg/front_end/testcases/spread_collection_inference.dart:112:53: Error: Can't assign spread entry keys of type 'String' to map entry keys of type 'int'.
+//     /*@error=SpreadMapEntryElementKeyTypeMismatch*/ mapSpread};
+//                                                     ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:115:55: Error: Can't assign spread entry values of type 'int' to map entry values of type 'String'.
+//     /*@error=SpreadMapEntryElementValueTypeMismatch*/ mapSpread};
+//                                                       ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:117:67: Error: Can't spread a value with static type Null.
+//   List<int> lhs70 = <int>[... /*@error=NonNullAwareSpreadIsNull*/ null];
+//                                                                   ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:119:66: Error: Can't spread a value with static type Null.
+//   Set<int> set70 = <int>{... /*@error=NonNullAwareSpreadIsNull*/ null};
+//                                                                  ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:122:46: Error: Can't spread a value with static type Null.
+//     {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+//                                              ^
+//
+// pkg/front_end/testcases/spread_collection_inference.dart:126:5: Error: Can't spread a value with static type Null.
+//     null};
+//     ^
+//
 import self as self;
 import "dart:core" as core;
 import "dart:collection" as col;
 
 static method foo() → dynamic {
   core::List<core::int> spread = <core::int>[1, 2, 3];
+  core::Map<core::String, core::int> mapSpread = <core::String, core::int>{"foo": 4, "bar": 2};
   core::int notSpreadInt = 42;
   () → core::int notSpreadFunction = null;
   core::List<dynamic> lhs10 = block {
@@ -56,86 +122,232 @@
     for (final dynamic #t4 in <dynamic>[])
       #t3.{core::Set::add}(#t4);
   } =>#t3;
-  core::List<core::int> lhs20 = block {
-    final core::List<core::int> #t5 = <core::int>[];
-    for (final core::int #t6 in spread)
-      #t5.{core::List::add}(#t6);
+  core::Map<dynamic, dynamic> map10 = block {
+    final core::Map<dynamic, dynamic> #t5 = <dynamic, dynamic>{};
+    for (final core::MapEntry<dynamic, dynamic> #t6 in <dynamic, dynamic>{}.{core::Map::entries})
+      #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
   } =>#t5;
-  core::Set<core::int> set20 = block {
-    final core::Set<core::int> #t7 = col::LinkedHashSet::•<core::int>();
-    for (final core::int #t8 in spread)
-      #t7.{core::Set::add}(#t8);
-    #t7.{core::Set::add}(42);
+  core::Map<dynamic, dynamic> map10ambiguous = block {
+    final core::Map<dynamic, dynamic> #t7 = <dynamic, dynamic>{};
+    for (final core::MapEntry<dynamic, dynamic> #t8 in <dynamic, dynamic>{}.{core::Map::entries})
+      #t7.{core::Map::[]=}(#t8.{core::MapEntry::key}, #t8.{core::MapEntry::value});
   } =>#t7;
-  core::List<dynamic> lhs21 = block {
-    final core::List<dynamic> #t9 = <dynamic>[];
-    for (final dynamic #t10 in (spread as dynamic) as{TypeError} core::Iterable<dynamic>)
+  core::List<core::int> lhs20 = block {
+    final core::List<core::int> #t9 = <core::int>[];
+    for (final core::int #t10 in spread)
       #t9.{core::List::add}(#t10);
   } =>#t9;
-  core::Set<dynamic> set21 = block {
-    final core::Set<dynamic> #t11 = col::LinkedHashSet::•<dynamic>();
-    for (final dynamic #t12 in (spread as dynamic) as{TypeError} core::Iterable<dynamic>)
+  core::Set<core::int> set20 = block {
+    final core::Set<core::int> #t11 = col::LinkedHashSet::•<core::int>();
+    for (final core::int #t12 in spread)
       #t11.{core::Set::add}(#t12);
     #t11.{core::Set::add}(42);
   } =>#t11;
-  core::List<core::int> lhs22 = block {
-    final core::List<core::int> #t13 = <core::int>[];
-    for (final core::int #t14 in <core::int>[])
-      #t13.{core::List::add}(#t14);
+  core::Set<core::int> set20ambiguous = block {
+    final core::Set<core::int> #t13 = col::LinkedHashSet::•<core::int>();
+    for (final core::int #t14 in spread)
+      #t13.{core::Set::add}(#t14);
   } =>#t13;
-  core::Set<core::int> set22 = block {
-    final core::Set<core::int> #t15 = col::LinkedHashSet::•<core::int>();
-    for (final core::int #t16 in <core::int>[])
-      #t15.{core::Set::add}(#t16);
-    #t15.{core::Set::add}(42);
+  core::Map<core::String, core::int> map20 = block {
+    final core::Map<core::String, core::int> #t15 = <core::String, core::int>{};
+    for (final core::MapEntry<core::String, core::int> #t16 in mapSpread.{core::Map::entries})
+      #t15.{core::Map::[]=}(#t16.{core::MapEntry::key}, #t16.{core::MapEntry::value});
+    #t15.{core::Map::[]=}("baz", 42);
   } =>#t15;
-  core::List<core::List<core::int>> lhs23 = block {
-    final core::List<core::List<core::int>> #t17 = <core::List<core::int>>[];
-    for (final core::List<core::int> #t18 in <core::List<core::int>>[<core::int>[]])
-      #t17.{core::List::add}(#t18);
+  core::Map<core::String, core::int> map20ambiguous = block {
+    final core::Map<core::String, core::int> #t17 = <core::String, core::int>{};
+    for (final core::MapEntry<core::String, core::int> #t18 in mapSpread.{core::Map::entries})
+      #t17.{core::Map::[]=}(#t18.{core::MapEntry::key}, #t18.{core::MapEntry::value});
   } =>#t17;
-  core::Set<core::List<core::int>> set23 = block {
-    final core::Set<core::List<core::int>> #t19 = col::LinkedHashSet::•<core::List<core::int>>();
-    for (final core::List<core::int> #t20 in <core::List<core::int>>[<core::int>[]])
-      #t19.{core::Set::add}(#t20);
-    #t19.{core::Set::add}(<core::int>[42]);
+  core::List<dynamic> lhs21 = block {
+    final core::List<dynamic> #t19 = <dynamic>[];
+    for (final dynamic #t20 in (spread as dynamic) as{TypeError} core::Iterable<dynamic>)
+      #t19.{core::List::add}(#t20);
   } =>#t19;
-  core::int lhs30 = let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:40:62: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
+  core::Set<dynamic> set21 = block {
+    final core::Set<dynamic> #t21 = col::LinkedHashSet::•<dynamic>();
+    for (final dynamic #t22 in (spread as dynamic) as{TypeError} core::Iterable<dynamic>)
+      #t21.{core::Set::add}(#t22);
+    #t21.{core::Set::add}(42);
+  } =>#t21;
+  core::Map<dynamic, dynamic> map21 = block {
+    final core::Map<dynamic, dynamic> #t23 = <dynamic, dynamic>{};
+    for (final core::MapEntry<dynamic, dynamic> #t24 in ((mapSpread as dynamic) as{TypeError} core::Map<dynamic, dynamic>).{core::Map::entries})
+      #t23.{core::Map::[]=}(#t24.{core::MapEntry::key}, #t24.{core::MapEntry::value});
+    #t23.{core::Map::[]=}("baz", 42);
+  } =>#t23;
+  dynamic map21ambiguous = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:48:76: Error: Not enough type information to disambiguate between literal set and literal map.
+Try providing type arguments for the literal explicitly to disambiguate it.
+  dynamic map21ambiguous = /*@error=CantDisambiguateNotEnoughInformation*/ {...
+                                                                           ^";
+  core::List<core::int> lhs22 = block {
+    final core::List<core::int> #t25 = <core::int>[];
+    for (final core::int #t26 in <core::int>[])
+      #t25.{core::List::add}(#t26);
+  } =>#t25;
+  core::Set<core::int> set22 = block {
+    final core::Set<core::int> #t27 = col::LinkedHashSet::•<core::int>();
+    for (final core::int #t28 in <core::int>[])
+      #t27.{core::Set::add}(#t28);
+    #t27.{core::Set::add}(42);
+  } =>#t27;
+  core::Set<core::int> set22ambiguous = block {
+    final core::Set<core::int> #t29 = col::LinkedHashSet::•<core::int>();
+    for (final core::int #t30 in <core::int>[])
+      #t29.{core::Set::add}(#t30);
+  } =>#t29;
+  core::Map<core::String, core::int> map22 = block {
+    final core::Map<core::String, core::int> #t31 = <core::String, core::int>{};
+    for (final core::MapEntry<core::String, core::int> #t32 in <core::String, core::int>{}.{core::Map::entries})
+      #t31.{core::Map::[]=}(#t32.{core::MapEntry::key}, #t32.{core::MapEntry::value});
+  } =>#t31;
+  core::List<core::List<core::int>> lhs23 = block {
+    final core::List<core::List<core::int>> #t33 = <core::List<core::int>>[];
+    for (final core::List<core::int> #t34 in <core::List<core::int>>[<core::int>[]])
+      #t33.{core::List::add}(#t34);
+  } =>#t33;
+  core::Set<core::List<core::int>> set23 = block {
+    final core::Set<core::List<core::int>> #t35 = col::LinkedHashSet::•<core::List<core::int>>();
+    for (final core::List<core::int> #t36 in <core::List<core::int>>[<core::int>[]])
+      #t35.{core::Set::add}(#t36);
+    #t35.{core::Set::add}(<core::int>[42]);
+  } =>#t35;
+  core::Set<core::List<core::int>> set23ambiguous = block {
+    final core::Set<core::List<core::int>> #t37 = col::LinkedHashSet::•<core::List<core::int>>();
+    for (final core::List<core::int> #t38 in <core::List<core::int>>[<core::int>[]])
+      #t37.{core::Set::add}(#t38);
+  } =>#t37;
+  core::Map<core::String, core::List<core::int>> map23 = block {
+    final core::Map<core::String, core::List<core::int>> #t39 = <core::String, core::List<core::int>>{};
+    for (final core::MapEntry<core::String, core::List<core::int>> #t40 in <core::String, core::List<core::int>>{"baz": <core::int>[]}.{core::Map::entries})
+      #t39.{core::Map::[]=}(#t40.{core::MapEntry::key}, #t40.{core::MapEntry::value});
+  } =>#t39;
+  dynamic map24ambiguous = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:72:76: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+  dynamic map24ambiguous = /*@error=CantDisambiguateAmbiguousInformation*/ {...
+                                                                           ^";
+  core::int lhs30 = let final<BottomType> #t41 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:75:62: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
  - 'List' is from 'dart:core'.
 Try changing the type of the left hand side, or casting the right hand side to 'int'.
   int lhs30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ [...spread];
                                                              ^" in ( block {
-    final core::List<core::int> #t22 = <core::int>[];
-    for (final core::int #t23 in spread)
-      #t22.{core::List::add}(#t23);
-  } =>#t22) as{TypeError} core::int;
-  core::int set30 = let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:42:62: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
+    final core::List<core::int> #t42 = <core::int>[];
+    for (final core::int #t43 in spread)
+      #t42.{core::List::add}(#t43);
+  } =>#t42) as{TypeError} core::int;
+  core::int set30 = let final<BottomType> #t44 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:77:62: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
  - 'Set' is from 'dart:core'.
 Try changing the type of the left hand side, or casting the right hand side to 'int'.
   int set30 = /*@error=InvalidAssignment*/ /*@typeArgs=int*/ {...spread, 42};
                                                              ^" in ( block {
-    final core::Set<core::int> #t25 = col::LinkedHashSet::•<core::int>();
-    for (final core::int #t26 in spread)
-      #t25.{core::Set::add}(#t26);
-    #t25.{core::Set::add}(42);
-  } =>#t25) as{TypeError} core::int;
-  core::List<dynamic> lhs40 = <dynamic>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:45:5: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
+    final core::Set<core::int> #t45 = col::LinkedHashSet::•<core::int>();
+    for (final core::int #t46 in spread)
+      #t45.{core::Set::add}(#t46);
+    #t45.{core::Set::add}(42);
+  } =>#t45) as{TypeError} core::int;
+  core::int set30ambiguous = let final<BottomType> #t47 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:80:5: Error: A value of type 'Set<int>' can't be assigned to a variable of type 'int'.
+ - 'Set' is from 'dart:core'.
+Try changing the type of the left hand side, or casting the right hand side to 'int'.
+    {...spread};
+    ^" in ( block {
+    final core::Set<core::int> #t48 = col::LinkedHashSet::•<core::int>();
+    for (final core::int #t49 in spread)
+      #t48.{core::Set::add}(#t49);
+  } =>#t48) as{TypeError} core::int;
+  core::int map30 = let final<BottomType> #t50 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:83:5: Error: A value of type 'Map<String, int>' can't be assigned to a variable of type 'int'.
+ - 'Map' is from 'dart:core'.
+Try changing the type of the left hand side, or casting the right hand side to 'int'.
+    {...mapSpread, \"baz\": 42};
+    ^" in ( block {
+    final core::Map<core::String, core::int> #t51 = <core::String, core::int>{};
+    for (final core::MapEntry<core::String, core::int> #t52 in mapSpread.{core::Map::entries})
+      #t51.{core::Map::[]=}(#t52.{core::MapEntry::key}, #t52.{core::MapEntry::value});
+    #t51.{core::Map::[]=}("baz", 42);
+  } =>#t51) as{TypeError} core::int;
+  core::int map30ambiguous = let final<BottomType> #t53 = invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:86:5: Error: A value of type 'Map<String, int>' can't be assigned to a variable of type 'int'.
+ - 'Map' is from 'dart:core'.
+Try changing the type of the left hand side, or casting the right hand side to 'int'.
+    {...mapSpread};
+    ^" in ( block {
+    final core::Map<core::String, core::int> #t54 = <core::String, core::int>{};
+    for (final core::MapEntry<core::String, core::int> #t55 in mapSpread.{core::Map::entries})
+      #t54.{core::Map::[]=}(#t55.{core::MapEntry::key}, #t55.{core::MapEntry::value});
+  } =>#t54) as{TypeError} core::int;
+  core::List<dynamic> lhs40 = <dynamic>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:89:5: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
     notSpreadInt];
     ^"];
-  core::Set<dynamic> set40 = let final core::Set<dynamic> #t27 = col::LinkedHashSet::•<dynamic>() in let final core::bool #t28 = #t27.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:48:5: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
+  core::Set<dynamic> set40 = let final core::Set<dynamic> #t56 = col::LinkedHashSet::•<dynamic>() in let final core::bool #t57 = #t56.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:92:5: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
     notSpreadInt};
-    ^") in #t27;
-  core::List<dynamic> lhs50 = <dynamic>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:51:5: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
+    ^") in #t56;
+  core::Map<dynamic, dynamic> map40 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:95:43: Error: Unexpected type 'int' of a map spread entry.  Expected 'dynamic' or a Map.
+    /*@error=SpreadMapEntryTypeMismatch*/ notSpreadInt};
+                                          ^": null};
+  core::List<dynamic> lhs50 = <dynamic>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:98:5: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
     notSpreadFunction];
     ^"];
-  core::Set<dynamic> set50 = let final core::Set<dynamic> #t29 = col::LinkedHashSet::•<dynamic>() in let final core::bool #t30 = #t29.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:54:5: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
+  core::Set<dynamic> set50 = let final core::Set<dynamic> #t58 = col::LinkedHashSet::•<dynamic>() in let final core::bool #t59 = #t58.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:101:5: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
     notSpreadFunction};
-    ^") in #t29;
-  core::List<core::String> lhs60 = <core::String>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:57:5: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+    ^") in #t58;
+  core::Map<dynamic, dynamic> map50 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:104:43: Error: Unexpected type 'int Function()' of a map spread entry.  Expected 'dynamic' or a Map.
+    /*@error=SpreadMapEntryTypeMismatch*/ notSpreadFunction};
+                                          ^": null};
+  core::List<core::String> lhs60 = <core::String>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:107:5: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
     spread];
     ^"];
-  core::Set<core::String> set60 = let final core::Set<core::String> #t31 = col::LinkedHashSet::•<core::String>() in let final core::bool #t32 = #t31.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:59:73: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+  core::Set<core::String> set60 = let final core::Set<core::String> #t60 = col::LinkedHashSet::•<core::String>() in let final core::bool #t61 = #t60.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:109:73: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
   Set<String> set60 = <String>{... /*@error=SpreadElementTypeMismatch*/ spread};
-                                                                        ^") in #t31;
+                                                                        ^") in #t60;
+  core::Map<core::int, core::int> map60 = <core::int, core::int>{invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:112:53: Error: Can't assign spread entry keys of type 'String' to map entry keys of type 'int'.
+    /*@error=SpreadMapEntryElementKeyTypeMismatch*/ mapSpread};
+                                                    ^": null};
+  core::Map<core::String, core::String> map61 = <core::String, core::String>{null: invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:115:55: Error: Can't assign spread entry values of type 'int' to map entry values of type 'String'.
+    /*@error=SpreadMapEntryElementValueTypeMismatch*/ mapSpread};
+                                                      ^"};
+  core::List<core::int> lhs70 = <core::int>[invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:117:67: Error: Can't spread a value with static type Null.
+  List<int> lhs70 = <int>[... /*@error=NonNullAwareSpreadIsNull*/ null];
+                                                                  ^"];
+  core::Set<core::int> set70 = let final core::Set<core::int> #t62 = col::LinkedHashSet::•<core::int>() in let final core::bool #t63 = #t62.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:119:66: Error: Can't spread a value with static type Null.
+  Set<int> set70 = <int>{... /*@error=NonNullAwareSpreadIsNull*/ null};
+                                                                 ^") in #t62;
+  core::Set<dynamic> set71ambiguous = block {
+    final core::Set<dynamic> #t64 = col::LinkedHashSet::•<dynamic>();
+    #t64.{core::Set::add}(invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:122:46: Error: Can't spread a value with static type Null.
+    {... /*@error=NonNullAwareSpreadIsNull*/ null, ... /*@typeArgs=dynamic*/
+                                             ^");
+    for (final dynamic #t65 in <dynamic>[])
+      #t64.{core::Set::add}(#t65);
+  } =>#t64;
+  core::Map<core::String, core::int> map70 = <core::String, core::int>{invalid-expression "pkg/front_end/testcases/spread_collection_inference.dart:126:5: Error: Can't spread a value with static type Null.
+    null};
+    ^": null};
+  core::List<core::int> lhs80 = block {
+    final core::List<core::int> #t66 = <core::int>[];
+    final dynamic #t67 = null;
+    if(!#t67.{core::Object::==}(null))
+      for (final core::int #t68 in #t67)
+        #t66.{core::List::add}(#t68);
+  } =>#t66;
+  core::Set<core::int> set80 = block {
+    final core::Set<core::int> #t69 = col::LinkedHashSet::•<core::int>();
+    final dynamic #t70 = null;
+    if(!#t70.{core::Object::==}(null))
+      for (final core::int #t71 in #t70)
+        #t69.{core::Set::add}(#t71);
+  } =>#t69;
+  core::Set<dynamic> set81ambiguous = block {
+    final core::Set<dynamic> #t72 = col::LinkedHashSet::•<dynamic>();
+    final dynamic #t73 = null;
+    if(!#t73.{core::Object::==}(null))
+      for (final dynamic #t74 in #t73)
+        #t72.{core::Set::add}(#t74);
+    for (final dynamic #t75 in <dynamic>[])
+      #t72.{core::Set::add}(#t75);
+  } =>#t72;
+  core::Map<core::String, core::int> map80 = block {
+    final core::Map<core::String, core::int> #t76 = <core::String, core::int>{};
+    final core::Map<dynamic, dynamic> #t77 = null;
+    if(!#t77.{core::Object::==}(null))
+      for (final core::MapEntry<core::String, core::int> #t78 in #t77.{core::Map::entries})
+        #t76.{core::Map::[]=}(#t78.{core::MapEntry::key}, #t78.{core::MapEntry::value});
+  } =>#t76;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 25ac322..d89dded 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -26,6 +26,7 @@
 fallthrough: ExpectationFileMismatch
 incomplete_field_formal_parameter: RuntimeError
 inference/abstract_class_instantiation: InstrumentationMismatch # Issue #30040
+inference/conflicting_fields: TypeCheckError
 inference/conflicts_can_happen: TypeCheckError
 inference/conflicts_can_happen2: TypeCheckError
 inference/constructors_infer_from_arguments_argument_not_assignable: TypeCheckError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index fe97d6b..4d5dc75 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -157,6 +157,7 @@
 inference/complex_predecrement: TextSerializationFailure # Was: Pass
 inference/conditional_lub: TextSerializationFailure # Was: Pass
 inference/conditional_upwards_inference: TextSerializationFailure # Was: Pass
+inference/conflicting_fields: TypeCheckError
 inference/conflicts_can_happen2: TypeCheckError
 inference/conflicts_can_happen: TypeCheckError
 inference/constructors_downwards_with_constraint: TextSerializationFailure # Was: Pass
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index 6dd8999..a1457fc 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -299,7 +299,7 @@
       "mode": "release",
       "common": "--dart2js-batch --time -pcolor --report -ax64 -mrelease --write-result-log",
       "command-lines": [
-        "-cdart2js -rd8 --use-sdk --minified --dart2js-with-kernel language language_2 dart2js_extra dart2js_native corelib corelib_2"
+        "-cdart2js -rd8 --use-sdk --minified language language_2 dart2js_extra dart2js_native corelib corelib_2"
       ]
     },
 
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index 385d151..ae7650d 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -251,6 +251,7 @@
   "--legacy": "--legacy-mode",
   "--legacy-mode": false,
   "--libraries-json": Uri,
+  "--no-defines": false,
   "--output": Uri,
   "--packages": Uri,
   "--platform": Uri,
@@ -310,6 +311,8 @@
         "Valid targets are:\n  ${targets.keys.join("\n  ")}");
   }
 
+  final bool noDefines = options["--no-defines"];
+
   final bool enableAsserts = options["--enable-asserts"];
 
   final bool verify = options["--verify"];
@@ -385,7 +388,7 @@
           ..verify = verify
           ..bytecode = bytecode
           ..experimentalFlags = experimentalFlags
-          ..environmentDefines = parsedArguments.defines,
+          ..environmentDefines = noDefines ? null : parsedArguments.defines,
         inputs: <Uri>[Uri.parse(arguments[0])],
         output: resolveInputUri(arguments[3]));
   } else if (arguments.isEmpty) {
@@ -421,7 +424,7 @@
     ..verbose = verbose
     ..verify = verify
     ..experimentalFlags = experimentalFlags
-    ..environmentDefines = parsedArguments.defines;
+    ..environmentDefines = noDefines ? null : parsedArguments.defines;
 
   // TODO(ahe): What about chase dependencies?
 
diff --git a/pkg/front_end/tool/fasta b/pkg/front_end/tool/fasta
index 2567a4e..465f05b 100755
--- a/pkg/front_end/tool/fasta
+++ b/pkg/front_end/tool/fasta
@@ -23,6 +23,13 @@
 
 export DART_CONFIGURATION=${DART_CONFIGURATION:-ReleaseX64}
 
+EXTRA_VM_ARGS=()
+
+while [[ "$1" == -* ]]; do
+  EXTRA_VM_ARGS+=("$1")
+  shift
+done
+
 case "${1//_/-}" in
   abcompile) SCRIPT="${TOOL_DIR}/abcompile.dart";;
   compile) SCRIPT="${TOOL_DIR}/compile.dart";;
@@ -55,4 +62,4 @@
 
 shift
 
-exec "${DART_VM}" -c "${SCRIPT}" "$@"
+exec "${DART_VM}" "${EXTRA_VM_ARGS[@]}" -c "${SCRIPT}" "$@"
diff --git a/pkg/front_end/tool/status_files/update_from_log.dart b/pkg/front_end/tool/status_files/update_from_log.dart
deleted file mode 100644
index 2fa2b11..0000000
--- a/pkg/front_end/tool/status_files/update_from_log.dart
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2017, 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.
-
-/// Script that updates kernel status lines automatically for tests under the
-/// '$strong' configuration.
-///
-/// This script is hardcoded to only support this configuration and relies on
-/// a convention for how the status files are structured, In particular,
-/// every status file is expected to have these sections:
-///
-///     [ $compiler == dartk && $runtime == vm && $strong ]
-///     [ $compiler == dartk && $runtime == vm && $strong && $mode == debug ]
-///     [ $compiler == dartkp && $runtime == dart_precompiled && $strong ]
-///     [ $compiler == dartkp && $runtime == dart_precompiled && $strong && $mode == debug]
-///
-/// we allow other sections specifying $checked mode, but the script currently
-/// has not been configured to update them.
-///
-///     [ $compiler == dartk && $runtime == vm && $strong && $checked ]
-///     [ $compiler == dartk && $runtime == vm && $strong && !$checked ]
-///     [ $compiler == dartkp && $runtime == dart_precompiled && $strong && $checked]
-///     [ $compiler == dartkp && $runtime == dart_precompiled && $strong && !$checked]
-///
-/// Note that this script is brittle and will not work properly if there are
-/// other overlapping sections. If you see the script adding entries like "Pass"
-/// it is a sign that a test was broadly marked as failing in a more general
-/// section (e.g. $runtime == vm, but no compiler was specified).
-
-library front_end.status_files.update_from_log;
-
-import '../../../compiler/tool/status_files/update_from_log.dart'
-    show mainInternal;
-
-final kernelStrongConfigurations = {
-  'dartk': r'[ $compiler == dartk && $runtime == vm && $strong ]',
-  'dartk-debug':
-      r'[ $compiler == dartk && $runtime == vm && $strong && $mode == debug]',
-  'dartkp':
-      r'[ $compiler == dartkp && $runtime == dart_precompiled && $strong ]',
-  'dartkp-debug':
-      r'[ $compiler == dartkp && $runtime == dart_precompiled && $strong && $mode == debug]',
-};
-
-final kernelStrongStatusFiles = {
-  'corelib_2': 'tests/corelib_2/corelib_2.status',
-  'language_2': 'tests/language_2/language_2_kernel.status',
-  'lib_2': 'tests/lib_2/lib_2_kernel.status',
-  'standalone_2': 'tests/standalone_2/standalone_2_kernel.status',
-};
-
-main(args) {
-  mainInternal(args, kernelStrongConfigurations, kernelStrongStatusFiles);
-}
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 5fab418..613741e7 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -137,7 +137,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 20;
+  UInt32 formatVersion = 21;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
   UriSource sourceMap;
@@ -696,6 +696,28 @@
   List<Expression> expressions;
 }
 
+type ListConcatenation extends Expression {
+  Byte tag = 111;
+  FileOffset fileOffset;
+  DartType typeArgument;
+  List<Expression> lists;
+}
+
+type SetConcatenation extends Expression {
+  Byte tag = 112;
+  FileOffset fileOffset;
+  DartType typeArgument;
+  List<Expression> sets;
+}
+
+type MapConcatenation extends Expression {
+  Byte tag = 113;
+  FileOffset fileOffset;
+  DartType keyType;
+  DartType valueType;
+  List<Expression> maps;
+}
+
 type IsExpression extends Expression {
   Byte tag = 37;
   FileOffset fileOffset;
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 939af1f..2d7e3a1 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -3204,6 +3204,116 @@
   }
 }
 
+/// Concatenate lists into a single list.
+///
+/// If [lists] is empty then an empty list is returned.
+///
+/// These arise from spread and control-flow elements in const list literals
+/// containing unevaluated subexpressions. They only ever occur within
+/// unevaluated constants in constant expressions.
+class ListConcatenation extends Expression {
+  DartType typeArgument;
+  final List<Expression> lists;
+
+  ListConcatenation(this.lists, {this.typeArgument: const DynamicType()}) {
+    setParents(lists, this);
+  }
+
+  DartType getStaticType(TypeEnvironment types) {
+    return types.literalListType(typeArgument);
+  }
+
+  accept(ExpressionVisitor v) => v.visitListConcatenation(this);
+  accept1(ExpressionVisitor1 v, arg) => v.visitListConcatenation(this, arg);
+
+  visitChildren(Visitor v) {
+    typeArgument?.accept(v);
+    visitList(lists, v);
+  }
+
+  transformChildren(Transformer v) {
+    typeArgument = v.visitDartType(typeArgument);
+    transformList(lists, v, this);
+  }
+}
+
+/// Concatenate sets into a single set.
+///
+/// If [sets] is empty then an empty set is returned.
+///
+/// These arise from spread and control-flow elements in const set literals
+/// containing unevaluated subexpressions. They only ever occur within
+/// unevaluated constants in constant expressions.
+///
+/// Duplicated values in or across the sets will result in a compile-time error
+/// during constant evaluation.
+class SetConcatenation extends Expression {
+  DartType typeArgument;
+  final List<Expression> sets;
+
+  SetConcatenation(this.sets, {this.typeArgument: const DynamicType()}) {
+    setParents(sets, this);
+  }
+
+  DartType getStaticType(TypeEnvironment types) {
+    return types.literalSetType(typeArgument);
+  }
+
+  accept(ExpressionVisitor v) => v.visitSetConcatenation(this);
+  accept1(ExpressionVisitor1 v, arg) => v.visitSetConcatenation(this, arg);
+
+  visitChildren(Visitor v) {
+    typeArgument?.accept(v);
+    visitList(sets, v);
+  }
+
+  transformChildren(Transformer v) {
+    typeArgument = v.visitDartType(typeArgument);
+    transformList(sets, v, this);
+  }
+}
+
+/// Concatenate maps into a single map.
+///
+/// If [maps] is empty then an empty map is returned.
+///
+/// These arise from spread and control-flow elements in const map literals
+/// containing unevaluated subexpressions. They only ever occur within
+/// unevaluated constants in constant expressions.
+///
+/// Duplicated keys in or across the maps will result in a compile-time error
+/// during constant evaluation.
+class MapConcatenation extends Expression {
+  DartType keyType;
+  DartType valueType;
+  final List<Expression> maps;
+
+  MapConcatenation(this.maps,
+      {this.keyType: const DynamicType(),
+      this.valueType: const DynamicType()}) {
+    setParents(maps, this);
+  }
+
+  DartType getStaticType(TypeEnvironment types) {
+    return types.literalMapType(keyType, valueType);
+  }
+
+  accept(ExpressionVisitor v) => v.visitMapConcatenation(this);
+  accept1(ExpressionVisitor1 v, arg) => v.visitMapConcatenation(this, arg);
+
+  visitChildren(Visitor v) {
+    keyType?.accept(v);
+    valueType?.accept(v);
+    visitList(maps, v);
+  }
+
+  transformChildren(Transformer v) {
+    keyType = v.visitDartType(keyType);
+    valueType = v.visitDartType(valueType);
+    transformList(maps, v, this);
+  }
+}
+
 /// Expression of form `x is T`.
 class IsExpression extends Expression {
   Expression operand;
@@ -5585,6 +5695,10 @@
       : root = nameRoot ?? new CanonicalName.root(),
         libraries = libraries ?? <Library>[],
         uriToSource = uriToSource ?? <Uri, Source>{} {
+    adoptChildren();
+  }
+
+  void adoptChildren() {
     if (libraries != null) {
       for (int i = 0; i < libraries.length; ++i) {
         // The libraries are owned by this component, and so are their canonical
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 29fc2cc..f5b7c33 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -1511,6 +1511,25 @@
         int offset = readOffset();
         return new StringConcatenation(readExpressionList())
           ..fileOffset = offset;
+      case Tag.ListConcatenation:
+        int offset = readOffset();
+        var typeArgument = readDartType();
+        return new ListConcatenation(readExpressionList(),
+            typeArgument: typeArgument)
+          ..fileOffset = offset;
+      case Tag.SetConcatenation:
+        int offset = readOffset();
+        var typeArgument = readDartType();
+        return new SetConcatenation(readExpressionList(),
+            typeArgument: typeArgument)
+          ..fileOffset = offset;
+      case Tag.MapConcatenation:
+        int offset = readOffset();
+        var keyType = readDartType();
+        var valueType = readDartType();
+        return new MapConcatenation(readExpressionList(),
+            keyType: keyType, valueType: valueType)
+          ..fileOffset = offset;
       case Tag.IsExpression:
         int offset = readOffset();
         return new IsExpression(readExpression(), readDartType())
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 383e6ba..db91bfb 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -1466,6 +1466,31 @@
   }
 
   @override
+  void visitListConcatenation(ListConcatenation node) {
+    writeByte(Tag.ListConcatenation);
+    writeOffset(node.fileOffset);
+    writeNode(node.typeArgument);
+    writeNodeList(node.lists);
+  }
+
+  @override
+  void visitSetConcatenation(SetConcatenation node) {
+    writeByte(Tag.SetConcatenation);
+    writeOffset(node.fileOffset);
+    writeNode(node.typeArgument);
+    writeNodeList(node.sets);
+  }
+
+  @override
+  void visitMapConcatenation(MapConcatenation node) {
+    writeByte(Tag.MapConcatenation);
+    writeOffset(node.fileOffset);
+    writeNode(node.keyType);
+    writeNode(node.valueType);
+    writeNodeList(node.maps);
+  }
+
+  @override
   void visitIsExpression(IsExpression node) {
     writeByte(Tag.IsExpression);
     writeOffset(node.fileOffset);
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index ff6e228..ba6cc4e 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -50,6 +50,9 @@
   static const int LogicalExpression = 34;
   static const int ConditionalExpression = 35;
   static const int StringConcatenation = 36;
+  static const int ListConcatenation = 111;
+  static const int SetConcatenation = 112;
+  static const int MapConcatenation = 113;
   static const int IsExpression = 37;
   static const int AsExpression = 38;
   static const int StringLiteral = 39;
@@ -123,6 +126,9 @@
   /// 108 is occupied by [RedirectingFactoryConstructor] (member).
   /// 109 is occupied by [SetLiteral] (expression).
   /// 110 is occupied by [ConstSetLiteral] (expression).
+  /// 111 is occupied by [ListConcatenation] (expression).
+  /// 112 is occupied by [SetConcatenation] (expression).
+  /// 113 is occupied by [MapConcatenation] (expression).
 
   static const int SpecializedTagHighBit = 0x80; // 10000000
   static const int SpecializedTagMask = 0xF8; // 11111000
@@ -139,7 +145,7 @@
   /// Internal version of kernel binary format.
   /// Bump it when making incompatible changes in kernel binaries.
   /// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
-  static const int BinaryFormatVersion = 20;
+  static const int BinaryFormatVersion = 21;
 }
 
 abstract class ConstantTag {
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index a059436..4105a43 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -190,6 +190,21 @@
     return new StringConcatenation(node.expressions.map(clone).toList());
   }
 
+  visitListConcatenation(ListConcatenation node) {
+    return new ListConcatenation(node.lists.map(clone).toList(),
+        typeArgument: visitType(node.typeArgument));
+  }
+
+  visitSetConcatenation(SetConcatenation node) {
+    return new SetConcatenation(node.sets.map(clone).toList(),
+        typeArgument: visitType(node.typeArgument));
+  }
+
+  visitMapConcatenation(MapConcatenation node) {
+    return new MapConcatenation(node.maps.map(clone).toList(),
+        keyType: visitType(node.keyType), valueType: visitType(node.valueType));
+  }
+
   visitIsExpression(IsExpression node) {
     return new IsExpression(clone(node.operand), visitType(node.type));
   }
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 94d2f55..29af291 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -1272,6 +1272,33 @@
     state = WORD;
   }
 
+  visitListConcatenation(ListConcatenation node) {
+    bool first = true;
+    for (Expression part in node.lists) {
+      if (!first) writeSpaced('+');
+      writeExpression(part);
+      first = false;
+    }
+  }
+
+  visitSetConcatenation(SetConcatenation node) {
+    bool first = true;
+    for (Expression part in node.sets) {
+      if (!first) writeSpaced('+');
+      writeExpression(part);
+      first = false;
+    }
+  }
+
+  visitMapConcatenation(MapConcatenation node) {
+    bool first = true;
+    for (Expression part in node.maps) {
+      if (!first) writeSpaced('+');
+      writeExpression(part);
+      first = false;
+    }
+  }
+
   visitIsExpression(IsExpression node) {
     writeExpression(node.operand, Precedence.BITWISE_OR);
     writeSpaced('is');
@@ -1993,11 +2020,16 @@
     endLine(sb.toString());
   }
 
+  visitStringConstant(StringConstant node) {
+    final String name = syntheticNames.nameConstant(node);
+    endLine('  $name = "${escapeString(node.value)}"');
+  }
+
   visitUnevaluatedConstant(UnevaluatedConstant node) {
     final String name = syntheticNames.nameConstant(node);
-    write('  $name = ');
+    write('  $name = (');
     writeExpression(node.expression);
-    endLine();
+    endLine(')');
   }
 
   defaultNode(Node node) {
diff --git a/pkg/kernel/lib/text/text_serialization_verifier.dart b/pkg/kernel/lib/text/text_serialization_verifier.dart
index 2625376..b9f2662 100644
--- a/pkg/kernel/lib/text/text_serialization_verifier.dart
+++ b/pkg/kernel/lib/text/text_serialization_verifier.dart
@@ -888,6 +888,24 @@
   }
 
   @override
+  void visitListConcatenation(ListConcatenation node) {
+    storeLastSeenUriAndOffset(node);
+    makeExpressionRoundTrip(node);
+  }
+
+  @override
+  void visitSetConcatenation(SetConcatenation node) {
+    storeLastSeenUriAndOffset(node);
+    makeExpressionRoundTrip(node);
+  }
+
+  @override
+  void visitMapConcatenation(MapConcatenation node) {
+    storeLastSeenUriAndOffset(node);
+    makeExpressionRoundTrip(node);
+  }
+
+  @override
   void visitConditionalExpression(ConditionalExpression node) {
     storeLastSeenUriAndOffset(node);
     makeExpressionRoundTrip(node);
diff --git a/pkg/kernel/lib/transformations/constants.dart b/pkg/kernel/lib/transformations/constants.dart
index f4361bd..e7c77df 100644
--- a/pkg/kernel/lib/transformations/constants.dart
+++ b/pkg/kernel/lib/transformations/constants.dart
@@ -1075,8 +1075,8 @@
     if (left is UnevaluatedConstant) {
       return unevaluated(
           node,
-          new LogicalExpression(
-              unique(left.expression), node.operator, node.right));
+          new LogicalExpression(unique(left.expression), node.operator,
+              cloner.clone(node.right)));
     }
     switch (node.operator) {
       case '||':
@@ -1138,8 +1138,11 @@
     } else if (condition is UnevaluatedConstant) {
       return unevaluated(
           node,
-          new ConditionalExpression(unique(condition.expression), node.then,
-              node.otherwise, node.staticType));
+          new ConditionalExpression(
+              unique(condition.expression),
+              cloner.clone(node.then),
+              cloner.clone(node.otherwise),
+              node.staticType));
     } else {
       throw new _AbortCurrentEvaluation(errorReporter.invalidDartType(
           contextChain, node, condition, typeEnvironment.boolType));
@@ -1211,7 +1214,7 @@
         if (target.isConst) {
           if (target.isInExternalLibrary && target.initializer == null) {
             // The variable is unavailable due to separate compilation.
-            return unevaluated(node, node);
+            return unevaluated(node, new StaticGet(target));
           }
           return runInsideContext(target, () {
             return _evaluateSubexpression(target.initializer);
diff --git a/pkg/kernel/lib/transformations/mixin_full_resolution.dart b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
index 5154517..4a401fa 100644
--- a/pkg/kernel/lib/transformations/mixin_full_resolution.dart
+++ b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
@@ -188,7 +188,7 @@
 
           assert(src.typeParameters.length == dst.typeParameters.length);
           for (int j = 0; j < src.typeParameters.length; ++j) {
-            dst.typeParameters[j].flags = src.typeParameters[i].flags;
+            dst.typeParameters[j].flags = src.typeParameters[j].flags;
           }
           for (int j = 0; j < src.positionalParameters.length; ++j) {
             dst.positionalParameters[j].flags =
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index 094bd2f..a8d41d4 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -275,6 +275,9 @@
 
   @override
   Supertype substituteSupertype(Supertype node) => node;
+
+  @override
+  String toString() => "Substitution.empty";
 }
 
 class _MapSubstitution extends Substitution {
@@ -286,6 +289,9 @@
   DartType getSubstitute(TypeParameter parameter, bool upperBound) {
     return upperBound ? upper[parameter] : lower[parameter];
   }
+
+  @override
+  String toString() => "_MapSubstitution($upper, $lower)";
 }
 
 class _TopSubstitutor extends _TypeSubstitutor {
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index 56eb744..7f04bce 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -683,6 +683,36 @@
   }
 
   @override
+  DartType visitListConcatenation(ListConcatenation node) {
+    DartType type = environment.literalListType(node.typeArgument);
+    for (Expression part in node.lists) {
+      DartType partType = visitExpression(part);
+      checkAssignable(node, type, partType);
+    }
+    return type;
+  }
+
+  @override
+  DartType visitSetConcatenation(SetConcatenation node) {
+    DartType type = environment.literalSetType(node.typeArgument);
+    for (Expression part in node.sets) {
+      DartType partType = visitExpression(part);
+      checkAssignable(node, type, partType);
+    }
+    return type;
+  }
+
+  @override
+  DartType visitMapConcatenation(MapConcatenation node) {
+    DartType type = environment.literalMapType(node.keyType, node.valueType);
+    for (Expression part in node.maps) {
+      DartType partType = visitExpression(part);
+      checkAssignable(node, type, partType);
+    }
+    return type;
+  }
+
+  @override
   DartType visitStringLiteral(StringLiteral node) {
     return environment.stringType;
   }
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index 53ea440..0cecee1 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -38,6 +38,9 @@
       defaultExpression(node);
   R visitStringConcatenation(StringConcatenation node) =>
       defaultExpression(node);
+  R visitListConcatenation(ListConcatenation node) => defaultExpression(node);
+  R visitSetConcatenation(SetConcatenation node) => defaultExpression(node);
+  R visitMapConcatenation(MapConcatenation node) => defaultExpression(node);
   R visitIsExpression(IsExpression node) => defaultExpression(node);
   R visitAsExpression(AsExpression node) => defaultExpression(node);
   R visitSymbolLiteral(SymbolLiteral node) => defaultExpression(node);
@@ -161,6 +164,9 @@
       defaultExpression(node);
   R visitStringConcatenation(StringConcatenation node) =>
       defaultExpression(node);
+  R visitListConcatenation(ListConcatenation node) => defaultExpression(node);
+  R visitSetConcatenation(SetConcatenation node) => defaultExpression(node);
+  R visitMapConcatenation(MapConcatenation node) => defaultExpression(node);
   R visitIsExpression(IsExpression node) => defaultExpression(node);
   R visitAsExpression(AsExpression node) => defaultExpression(node);
   R visitSymbolLiteral(SymbolLiteral node) => defaultExpression(node);
@@ -496,6 +502,12 @@
       defaultExpression(node, arg);
   R visitStringConcatenation(StringConcatenation node, T arg) =>
       defaultExpression(node, arg);
+  R visitListConcatenation(ListConcatenation node, T arg) =>
+      defaultExpression(node, arg);
+  R visitSetConcatenation(SetConcatenation node, T arg) =>
+      defaultExpression(node, arg);
+  R visitMapConcatenation(MapConcatenation node, T arg) =>
+      defaultExpression(node, arg);
   R visitIsExpression(IsExpression node, T arg) => defaultExpression(node, arg);
   R visitAsExpression(AsExpression node, T arg) => defaultExpression(node, arg);
   R visitSymbolLiteral(SymbolLiteral node, T arg) =>
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml
index 02c4e5e..6072c7e 100644
--- a/pkg/kernel/pubspec.yaml
+++ b/pkg/kernel/pubspec.yaml
@@ -1,7 +1,7 @@
 name: kernel
 # Currently, kernel API is not stable and users should
 # not depend on semver semantics when depending on this package.
-version: 0.3.13
+version: 0.3.14
 author: Dart Team <misc@dartlang.org>
 description: Dart IR (Intermediate Representation)
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/kernel
diff --git a/pkg/smith/lib/configuration.dart b/pkg/smith/lib/configuration.dart
index 803ac2b..1b1c268 100644
--- a/pkg/smith/lib/configuration.dart
+++ b/pkg/smith/lib/configuration.dart
@@ -249,6 +249,7 @@
         name, architecture, compiler, mode, runtime, system,
         builderTag: stringOption("builder-tag"),
         vmOptions: stringListOption("vm-options"),
+        dart2jsOptions: stringListOption("dart2js-options"),
         timeout: intOption("timeout"),
         enableAsserts: boolOption("enable-asserts"),
         isChecked: boolOption("checked"),
@@ -259,8 +260,6 @@
         useAnalyzerCfe: boolOption("use-cfe"),
         useAnalyzerFastaParser: boolOption("analyzer-use-fasta-parser"),
         useBlobs: boolOption("use-blobs"),
-        useDart2JSWithKernel: boolOption("dart2js-with-kernel"),
-        useDart2JSOldFrontEnd: boolOption("dart2js-old-frontend"),
         useHotReload: boolOption("hot-reload"),
         useHotReloadRollback: boolOption("hot-reload-rollback"),
         useSdk: boolOption("use-sdk"));
@@ -289,6 +288,8 @@
 
   final List<String> vmOptions;
 
+  final List<String> dart2jsOptions;
+
   int timeout;
 
   final bool enableAsserts;
@@ -313,10 +314,6 @@
   // TODO(rnystrom): What is this?
   final bool useBlobs;
 
-  // TODO(rnystrom): Remove these when Dart 1.0 is no longer supported.
-  final bool useDart2JSWithKernel;
-  final bool useDart2JSOldFrontEnd;
-
   final bool useHotReload;
   final bool useHotReloadRollback;
 
@@ -326,6 +323,7 @@
       this.runtime, this.system,
       {String builderTag,
       List<String> vmOptions,
+      List<String> dart2jsOptions,
       int timeout,
       bool enableAsserts,
       bool isChecked,
@@ -336,13 +334,12 @@
       bool useAnalyzerCfe,
       bool useAnalyzerFastaParser,
       bool useBlobs,
-      bool useDart2JSWithKernel,
-      bool useDart2JSOldFrontEnd,
       bool useHotReload,
       bool useHotReloadRollback,
       bool useSdk})
       : builderTag = builderTag ?? "",
         vmOptions = vmOptions ?? <String>[],
+        dart2jsOptions = dart2jsOptions ?? <String>[],
         timeout = timeout,
         enableAsserts = enableAsserts ?? false,
         isChecked = isChecked ?? false,
@@ -353,8 +350,6 @@
         useAnalyzerCfe = useAnalyzerCfe ?? false,
         useAnalyzerFastaParser = useAnalyzerFastaParser ?? false,
         useBlobs = useBlobs ?? false,
-        useDart2JSWithKernel = useDart2JSWithKernel ?? false,
-        useDart2JSOldFrontEnd = useDart2JSOldFrontEnd ?? false,
         useHotReload = useHotReload ?? false,
         useHotReloadRollback = useHotReloadRollback ?? false,
         useSdk = useSdk ?? false;
@@ -369,6 +364,7 @@
       system == other.system &&
       builderTag == other.builderTag &&
       vmOptions.join(" & ") == other.vmOptions.join(" & ") &&
+      dart2jsOptions.join(" & ") == other.dart2jsOptions.join(" & ") &&
       timeout == other.timeout &&
       enableAsserts == other.enableAsserts &&
       isChecked == other.isChecked &&
@@ -379,8 +375,6 @@
       useAnalyzerCfe == other.useAnalyzerCfe &&
       useAnalyzerFastaParser == other.useAnalyzerFastaParser &&
       useBlobs == other.useBlobs &&
-      useDart2JSWithKernel == other.useDart2JSWithKernel &&
-      useDart2JSOldFrontEnd == other.useDart2JSOldFrontEnd &&
       useHotReload == other.useHotReload &&
       useHotReloadRollback == other.useHotReloadRollback &&
       useSdk == other.useSdk;
@@ -400,6 +394,7 @@
       system.hashCode ^
       builderTag.hashCode ^
       vmOptions.join(" & ").hashCode ^
+      dart2jsOptions.join(" & ").hashCode ^
       timeout.hashCode ^
       _toBinary([
         enableAsserts,
@@ -411,8 +406,6 @@
         useAnalyzerCfe,
         useAnalyzerFastaParser,
         useBlobs,
-        useDart2JSWithKernel,
-        useDart2JSOldFrontEnd,
         useHotReload,
         useHotReloadRollback,
         useSdk
@@ -432,6 +425,8 @@
 
     if (builderTag != "") fields.add("builder-tag: $builderTag");
     if (vmOptions != "") fields.add("vm-options: [${vmOptions.join(", ")}]");
+    if (dart2jsOptions != "")
+      fields.add("dart2js-options: [${dart2jsOptions.join(", ")}]");
     if (timeout != 0) fields.add("timeout: $timeout");
     if (enableAsserts) fields.add("enable-asserts");
     if (isChecked) fields.add("checked");
@@ -442,8 +437,6 @@
     if (useAnalyzerCfe) fields.add("use-cfe");
     if (useAnalyzerFastaParser) fields.add("analyzer-use-fasta-parser");
     if (useBlobs) fields.add("use-blobs");
-    if (useDart2JSWithKernel) fields.add("dart2js-with-kernel");
-    if (useDart2JSOldFrontEnd) fields.add("dart2js-old-frontend");
     if (useHotReload) fields.add("hot-reload");
     if (useHotReloadRollback) fields.add("hot-reload-rollback");
     if (useSdk) fields.add("use-sdk");
@@ -475,6 +468,11 @@
       var otherTag = "[${other.vmOptions.join(", ")}]";
       fields.add("vm-options: $tag $otherTag");
     }
+    if (dart2jsOptions != "" || other.dart2jsOptions != "") {
+      var tag = "[${dart2jsOptions.join(", ")}]";
+      var otherTag = "[${other.dart2jsOptions.join(", ")}]";
+      fields.add("dart2js-options: $tag $otherTag");
+    }
     fields.add("timeout: $timeout ${other.timeout}");
     if (enableAsserts || other.enableAsserts) {
       fields.add("enable-asserts $enableAsserts ${other.enableAsserts}");
@@ -504,14 +502,6 @@
     if (useBlobs || other.useBlobs) {
       fields.add("useBlobs $useBlobs ${other.useBlobs}");
     }
-    if (useDart2JSWithKernel || other.useDart2JSWithKernel) {
-      fields.add("useDart2JSWithKernel "
-          "$useDart2JSWithKernel ${other.useDart2JSWithKernel}");
-    }
-    if (useDart2JSOldFrontEnd || other.useDart2JSOldFrontEnd) {
-      fields.add("useDart2JSOldFrontEnd "
-          "$useDart2JSOldFrontEnd ${other.useDart2JSOldFrontEnd}");
-    }
     if (useHotReload || other.useHotReload) {
       fields.add("useHotReload $useHotReload ${other.useHotReload}");
     }
diff --git a/pkg/smith/test/configuration_test.dart b/pkg/smith/test/configuration_test.dart
index 0952c72..9c77fb3 100644
--- a/pkg/smith/test/configuration_test.dart
+++ b/pkg/smith/test/configuration_test.dart
@@ -200,14 +200,13 @@
             Configuration.parse("dart2js", {
               "builder-tag": "the tag",
               "vm-options": ["vm stuff", "more vm stuff"],
+              "dart2js-options": ["dart2js stuff", "more dart2js stuff"],
               "enable-asserts": true,
               "checked": true,
               "csp": true,
               "host-checked": true,
               "minified": true,
               "preview-dart-2": true,
-              "dart2js-with-kernel": true,
-              "dart2js-old-frontend": true,
               "hot-reload": true,
               "hot-reload-rollback": true,
               "use-sdk": true,
@@ -221,14 +220,13 @@
               System.host,
               builderTag: "the tag",
               vmOptions: ["vm stuff", "more vm stuff"],
+              dart2jsOptions: ["dart2js stuff", "more dart2js stuff"],
               enableAsserts: true,
               isChecked: true,
               isCsp: true,
               isHostChecked: true,
               isMinified: true,
               previewDart2: true,
-              useDart2JSWithKernel: true,
-              useDart2JSOldFrontEnd: true,
               useHotReload: true,
               useHotReloadRollback: true,
               useSdk: true,
diff --git a/pkg/vm/bin/protobuf_aware_treeshaker.dart b/pkg/vm/bin/protobuf_aware_treeshaker.dart
new file mode 100644
index 0000000..b971b13
--- /dev/null
+++ b/pkg/vm/bin/protobuf_aware_treeshaker.dart
@@ -0,0 +1,169 @@
+#!/usr/bin/env dart
+// Copyright (c) 2019, 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.
+
+/// This program will take a .dill file and do a protobuf aware tree-shaking.
+///
+/// All fields of GeneratedMessage subclasses that are not accessed with their
+/// getter or setter will have their metadata removed from the class definition.
+///
+/// Then a general treeshaking will be run, and
+/// all GeneratedMessage subclasses that are never used directly will be
+/// removed.
+///
+/// The processed program will have observable differences: The tree-shaken
+/// fields will be parsed as unknown fields.
+/// The toString method will treat the unknown fields as missing.
+///
+/// Using the `GeneratedMessage.info_` field to reflect on fields will have
+/// unpredictable behavior.
+///
+/// Constants are evaluated, this is mainly to enable detecting
+/// `@pragma('vm:entry-point')`.
+library vm.protobuf_aware_treeshaker;
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:args/args.dart';
+import 'package:kernel/kernel.dart';
+import 'package:kernel/binary/limited_ast_to_binary.dart';
+import 'package:kernel/target/targets.dart' show TargetFlags, getTarget;
+import 'package:meta/meta.dart';
+import 'package:vm/target/install.dart' show installAdditionalTargets;
+import 'package:vm/transformations/protobuf_aware_treeshaker/transformer.dart'
+    as treeshaker;
+
+ArgResults parseArgs(List<String> args) {
+  ArgParser argParser = ArgParser()
+    ..addOption('platform',
+        valueHelp: "path/to/vm_platform.dill",
+        help: 'A platform.dill file to append to the input. If not given, no '
+            'platform.dill will be appended.')
+    ..addOption('target',
+        allowed: ['dart_runner', 'flutter', 'flutter-runner', 'vm'],
+        defaultsTo: 'vm',
+        help: 'A platform.dill file to append to the input. If not given, no '
+            'platform.dill will be appended.')
+    ..addFlag('write-txt',
+        help: 'Also write the result in kernel-text format as <out.dill>.txt',
+        defaultsTo: false)
+    ..addFlag('remove-core-libs',
+        help:
+            'If set, the resulting dill file will not include `dart:` libraries',
+        defaultsTo: false)
+    ..addMultiOption('define',
+        abbr: 'D',
+        help: 'Perform constant evaluation with this environment define set.',
+        valueHelp: 'variable=value')
+    ..addFlag('remove-source',
+        help: 'Removes source code from the emitted dill', defaultsTo: false)
+    ..addFlag('enable-asserts',
+        help: 'Enables asserts in the emitted dill', defaultsTo: false)
+    ..addFlag('verbose',
+        help: 'Write to stdout about what classes and fields where remeoved')
+    ..addFlag('help', help: 'Prints this help', negatable: false);
+
+  ArgResults argResults;
+  try {
+    argResults = argParser.parse(args);
+  } on FormatException catch (e) {
+    print(e.message);
+  }
+  if (argResults == null || argResults['help'] || argResults.rest.length != 2) {
+    String script = 'protobuf_aware_treeshaker.dart';
+    print(
+        'A tool for removing protobuf messages types that are never referred by a program');
+    print('Usage: $script [args] <input.dill> <output.dill>');
+
+    print(argParser.usage);
+    exit(-1);
+  }
+
+  return argResults;
+}
+
+Future main(List<String> args) async {
+  ArgResults argResults = parseArgs(args);
+
+  final input = argResults.rest[0];
+  final output = argResults.rest[1];
+
+  final Map<String, String> environment = Map.fromIterable(
+      argResults['define'].map((x) => x.split('=')),
+      key: (x) => x[0],
+      value: (x) => x[1]);
+
+  var bytes = File(input).readAsBytesSync();
+  final platformFile = argResults['platform'];
+  if (platformFile != null) {
+    bytes = concatenate(File(platformFile).readAsBytesSync(), bytes);
+  }
+  final component = loadComponentFromBytes(bytes);
+
+  installAdditionalTargets();
+
+  treeshaker.TransformationInfo info = treeshaker.transformComponent(
+      component, environment, getTarget(argResults['target'], TargetFlags()),
+      collectInfo: argResults['verbose'],
+      enableAsserts: argResults['enable-asserts']);
+
+  if (argResults['verbose']) {
+    for (String fieldName in info.removedMessageFields) {
+      print('Removed $fieldName');
+    }
+    for (Class removedClass in info.removedMessageClasses) {
+      print('Removed $removedClass');
+    }
+  }
+
+  await writeComponent(component, output,
+      removeCoreLibs: argResults['remove-core-libs'],
+      removeSource: argResults['remove-source']);
+  if (argResults['write-txt']) {
+    writeComponentToText(component, path: output + '.txt');
+  }
+}
+
+Uint8List concatenate(Uint8List a, Uint8List b) {
+  final bytes = Uint8List(a.length + b.length);
+  bytes.setRange(0, a.length, a);
+  bytes.setRange(a.length, a.length + b.length, b);
+  return bytes;
+}
+
+Future writeComponent(Component component, String filename,
+    {@required bool removeCoreLibs, @required bool removeSource}) async {
+  if (removeSource) {
+    component.uriToSource.clear();
+  }
+
+  for (final lib in component.libraries) {
+    lib.dependencies.clear();
+    lib.additionalExports.clear();
+    lib.parts.clear();
+  }
+
+  final sink = File(filename).openWrite();
+  final printer = LimitedBinaryPrinter(sink, (lib) {
+    if (removeCoreLibs && isCoreLibrary(lib)) return false;
+    if (isLibEmpty(lib)) return false;
+    return true;
+  }, /*excludeUriToSource=*/ removeSource);
+
+  printer.writeComponentFile(component);
+  await sink.close();
+}
+
+bool isLibEmpty(Library lib) {
+  return lib.classes.isEmpty &&
+      lib.procedures.isEmpty &&
+      lib.fields.isEmpty &&
+      lib.typedefs.isEmpty;
+}
+
+bool isCoreLibrary(Library library) {
+  return library.importUri.scheme == 'dart';
+}
diff --git a/pkg/vm/lib/frontend_server.dart b/pkg/vm/lib/frontend_server.dart
index e0b9cfc..ecd0c8e 100644
--- a/pkg/vm/lib/frontend_server.dart
+++ b/pkg/vm/lib/frontend_server.dart
@@ -28,6 +28,7 @@
 import 'package:vm/incremental_compiler.dart' show IncrementalCompiler;
 import 'package:vm/kernel_front_end.dart'
     show
+        asFileUri,
         compileToKernel,
         parseCommandLineDefines,
         convertFileOrUriArgumentToUri,
@@ -115,16 +116,16 @@
 String usage = '''
 Usage: server [options] [input.dart]
 
-If input dart source code is provided on the command line, then the server
-compiles it, generates dill file and exits.
-If no input dart source is provided on the command line, server waits for
+If filename or uri pointing to the entrypoint is provided on the command line,
+then the server compiles it, generates dill file and exits.
+If no entrypoint is provided on the command line, server waits for
 instructions from stdin.
 
 Instructions:
 - compile <input.dart>
 - recompile [<input.dart>] <boundary-key>
-<path/to/updated/file1.dart>
-<path/to/updated/file2.dart>
+<invalidated file uri>
+<invalidated file uri>
 ...
 <boundary-key>
 - accept
@@ -152,20 +153,20 @@
 
 /// Actions that every compiler should implement.
 abstract class CompilerInterface {
-  /// Compile given Dart program identified by `filename` with given list of
+  /// Compile given Dart program identified by `entryPoint` with given list of
   /// `options`. When `generator` parameter is omitted, new instance of
   /// `IncrementalKernelGenerator` is created by this method. Main use for this
   /// parameter is for mocking in tests.
   /// Returns [true] if compilation was successful and produced no errors.
   Future<bool> compile(
-    String filename,
+    String entryPoint,
     ArgResults options, {
     IncrementalCompiler generator,
   });
 
   /// Assuming some Dart program was previously compiled, recompile it again
   /// taking into account some changed(invalidated) sources.
-  Future<Null> recompileDelta({String filename});
+  Future<Null> recompileDelta({String entryPoint});
 
   /// Accept results of previous compilation so that next recompilation cycle
   /// won't recompile sources that were previously reported as changed.
@@ -240,30 +241,27 @@
   String _kernelBinaryFilenameFull;
   String _initializeFromDill;
 
+  Set<Uri> previouslyReportedDependencies = Set<Uri>();
+
   final ProgramTransformer transformer;
 
   final List<String> errors = new List<String>();
 
-  void setMainSourceFilename(String filename) {
-    final Uri filenameUri = _getFileOrUri(filename);
-    _mainSource = filenameUri;
-  }
-
   @override
   Future<bool> compile(
-    String filename,
+    String entryPoint,
     ArgResults options, {
     IncrementalCompiler generator,
   }) async {
     _options = options;
     _fileSystem = createFrontEndFileSystem(
         options['filesystem-scheme'], options['filesystem-root']);
-    setMainSourceFilename(filename);
-    _kernelBinaryFilenameFull = _options['output-dill'] ?? '$filename.dill';
+    _mainSource = _getFileOrUri(entryPoint);
+    _kernelBinaryFilenameFull = _options['output-dill'] ?? '$entryPoint.dill';
     _kernelBinaryFilenameIncremental = _options['output-incremental-dill'] ??
         (_options['output-dill'] != null
             ? '${_options['output-dill']}.incremental.dill'
-            : '$filename.incremental.dill');
+            : '$entryPoint.incremental.dill');
     _kernelBinaryFilename = _kernelBinaryFilenameFull;
     _initializeFromDill =
         _options['initialize-from-dill'] ?? _kernelBinaryFilenameFull;
@@ -360,6 +358,8 @@
       await writeDillFile(component, _kernelBinaryFilename,
           filterExternal: importDill != null);
 
+      _outputStream.writeln(boundaryKey);
+      await _outputDependenciesDelta(component);
       _outputStream
           .writeln('$boundaryKey $_kernelBinaryFilename ${errors.length}');
       final String depfile = options['depfile'];
@@ -374,6 +374,27 @@
     return errors.isEmpty;
   }
 
+  void _outputDependenciesDelta(Component component) async {
+    Set<Uri> uris = new Set<Uri>();
+    for (Uri uri in component.uriToSource.keys) {
+      // Skip empty or corelib dependencies.
+      if (uri == null || uri.scheme == 'org-dartlang-sdk') continue;
+      uris.add(uri);
+    }
+    for (Uri uri in uris) {
+      if (previouslyReportedDependencies.contains(uri)) {
+        continue;
+      }
+      _outputStream.writeln('+${await asFileUri(_fileSystem, uri)}');
+    }
+    for (Uri uri in previouslyReportedDependencies) {
+      if (!uris.contains(uri)) {
+        _outputStream.writeln('-${await asFileUri(_fileSystem, uri)}');
+      }
+    }
+    previouslyReportedDependencies = uris;
+  }
+
   writeDillFile(Component component, String filename,
       {bool filterExternal: false}) async {
     final IOSink sink = new File(filename).openWrite();
@@ -458,12 +479,12 @@
   }
 
   @override
-  Future<Null> recompileDelta({String filename}) async {
+  Future<Null> recompileDelta({String entryPoint}) async {
     final String boundaryKey = new Uuid().generateV4();
     _outputStream.writeln('result $boundaryKey');
     await invalidateIfInitializingFromDill();
-    if (filename != null) {
-      setMainSourceFilename(filename);
+    if (entryPoint != null) {
+      _mainSource = _getFileOrUri(entryPoint);
     }
     errors.clear();
     final Component deltaProgram =
@@ -473,6 +494,8 @@
       transformer.transform(deltaProgram);
     }
     await writeDillFile(deltaProgram, _kernelBinaryFilename);
+    _outputStream.writeln(boundaryKey);
+    await _outputDependenciesDelta(deltaProgram);
     _outputStream
         .writeln('$boundaryKey $_kernelBinaryFilename ${errors.length}');
     _kernelBinaryFilename = _kernelBinaryFilenameIncremental;
@@ -683,7 +706,7 @@
   _State state = _State.READY_FOR_INSTRUCTION;
   _CompileExpressionRequest compileExpressionRequest;
   String boundaryKey;
-  String recompileFilename;
+  String recompileEntryPoint;
   input
       .transform(utf8.decoder)
       .transform(const LineSplitter())
@@ -695,17 +718,17 @@
         const String COMPILE_EXPRESSION_INSTRUCTION_SPACE =
             'compile-expression ';
         if (string.startsWith(COMPILE_INSTRUCTION_SPACE)) {
-          final String filename =
+          final String entryPoint =
               string.substring(COMPILE_INSTRUCTION_SPACE.length);
-          await compiler.compile(filename, options, generator: generator);
+          await compiler.compile(entryPoint, options, generator: generator);
         } else if (string.startsWith(RECOMPILE_INSTRUCTION_SPACE)) {
-          // 'recompile [<filename>] <boundarykey>'
+          // 'recompile [<entryPoint>] <boundarykey>'
           //   where <boundarykey> can't have spaces
           final String remainder =
               string.substring(RECOMPILE_INSTRUCTION_SPACE.length);
           final int spaceDelim = remainder.lastIndexOf(' ');
           if (spaceDelim > -1) {
-            recompileFilename = remainder.substring(0, spaceDelim);
+            recompileEntryPoint = remainder.substring(0, spaceDelim);
             boundaryKey = remainder.substring(spaceDelim + 1);
           } else {
             boundaryKey = remainder;
@@ -739,7 +762,7 @@
         break;
       case _State.RECOMPILE_LIST:
         if (string == boundaryKey) {
-          compiler.recompileDelta(filename: recompileFilename);
+          compiler.recompileDelta(entryPoint: recompileEntryPoint);
           state = _State.READY_FOR_INSTRUCTION;
         } else
           compiler.invalidate(Uri.base.resolve(string));
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 78063e2..9313820 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -517,7 +517,7 @@
 /// absolute URI.
 ///
 /// If virtual multi-root file system is used, or [input] can be parsed to a
-/// URI with 'package' scheme, then [input] is interpreted as URI.
+/// URI with 'package' or 'file' scheme, then [input] is interpreted as URI.
 /// Otherwise [input] is interpreted as a file path.
 Uri convertFileOrUriArgumentToUri(FileSystem fileSystem, String input) {
   if (input == null) {
@@ -530,7 +530,7 @@
   }
   try {
     Uri uri = Uri.parse(input);
-    if (uri.scheme == 'package') {
+    if (uri.scheme == 'package' || uri.scheme == 'file') {
       return uri;
     }
   } on FormatException {
diff --git a/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart b/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
new file mode 100644
index 0000000..fba5844
--- /dev/null
+++ b/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
@@ -0,0 +1,270 @@
+// Copyright (c) 2019, 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 'package:kernel/kernel.dart';
+import 'package:kernel/target/targets.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/transformations/constants.dart' as constants;
+import 'package:kernel/vm/constants_native_effects.dart' as vm_constants;
+import 'package:meta/meta.dart';
+import 'package:vm/transformations/type_flow/transformer.dart' as globalTypeFlow
+    show transformComponent;
+import 'package:vm/transformations/no_dynamic_invocations_annotator.dart'
+    show Selector;
+
+class TransformationInfo {
+  final List<String> removedMessageFields = <String>[];
+  final List<Class> removedMessageClasses = <Class>[];
+}
+
+TransformationInfo transformComponent(
+    Component component, Map<String, String> environment, Target target,
+    {@required bool collectInfo, @required bool enableAsserts}) {
+  final coreTypes = new CoreTypes(component);
+  component.computeCanonicalNames();
+
+  // Evaluate constants to ensure @pragma("vm:entry-point") is seen by the
+  // type-flow analysis.
+  final vmConstants = new vm_constants.VmConstantsBackend(coreTypes);
+  constants.transformComponent(component, vmConstants, environment, null,
+      keepFields: true,
+      evaluateAnnotations: true,
+      enableAsserts: enableAsserts);
+
+  TransformationInfo info = collectInfo ? TransformationInfo() : null;
+
+  _treeshakeProtos(target, component, coreTypes, info);
+  return info;
+}
+
+void _treeshakeProtos(Target target, Component component, CoreTypes coreTypes,
+    TransformationInfo info) {
+  globalTypeFlow.transformComponent(target, coreTypes, component);
+  final collector = _removeUnusedProtoReferences(component, coreTypes, info);
+  if (collector == null) {
+    return;
+  }
+  globalTypeFlow.transformComponent(target, coreTypes, component);
+  if (info != null) {
+    for (Class gmSubclass in collector.gmSubclasses) {
+      if (!gmSubclass.enclosingLibrary.classes.contains(gmSubclass)) {
+        info.removedMessageClasses.add(gmSubclass);
+      }
+    }
+  }
+  // Remove metadata added by the typeflow analysis.
+  component.metadata.clear();
+}
+
+InfoCollector _removeUnusedProtoReferences(
+    Component component, CoreTypes coreTypes, TransformationInfo info) {
+  final protobufUri = Uri.parse('package:protobuf/protobuf.dart');
+  final protobufLibs =
+      component.libraries.where((lib) => lib.importUri == protobufUri);
+  if (protobufLibs.isEmpty) {
+    return null;
+  }
+  final protobufLib = protobufLibs.single;
+
+  final gmClass = protobufLib.classes
+      .where((klass) => klass.name == 'GeneratedMessage')
+      .single;
+  final collector = InfoCollector(gmClass);
+
+  final biClass =
+      protobufLib.classes.where((klass) => klass.name == 'BuilderInfo').single;
+  final addMethod =
+      biClass.members.singleWhere((Member member) => member.name.name == 'add');
+
+  component.accept(collector);
+
+  _UnusedFieldMetadataPruner(
+          biClass, addMethod, collector.dynamicSelectors, coreTypes, info)
+      .removeMetadataForUnusedFields(
+    collector.gmSubclasses,
+    collector.gmSubclassesInvokedMethods,
+    coreTypes,
+    info,
+  );
+
+  return collector;
+}
+
+/// For protobuf fields which are not accessed, prune away its metadata.
+class _UnusedFieldMetadataPruner extends TreeVisitor<void> {
+  // All of those methods have the dart field name as second positional
+  // parameter.
+  // Method names are defined in:
+  // https://github.com/dart-lang/protobuf/blob/master/protobuf/lib/src/protobuf/builder_info.dart
+  // The code is generated by:
+  // https://github.com/dart-lang/protobuf/blob/master/protoc_plugin/lib/protobuf_field.dart.
+  static final fieldAddingMethods = Set<String>.from(const <String>[
+    'a',
+    'm',
+    'pp',
+    'pc',
+    'e',
+    'pc',
+    'aOS',
+    'aOB',
+  ]);
+
+  final Class builderInfoClass;
+  Class visitedClass;
+  final names = Set<String>();
+
+  final dynamicNames = Set<String>();
+  final CoreTypes coreTypes;
+  final TransformationInfo info;
+  final Member addMethod;
+
+  _UnusedFieldMetadataPruner(this.builderInfoClass, this.addMethod,
+      Set<Selector> dynamicSelectors, this.coreTypes, this.info) {
+    dynamicNames.addAll(dynamicSelectors.map((sel) => sel.target.name));
+  }
+
+  /// If a proto message field is never accessed (neither read nor written to),
+  /// remove its corresponding metadata in the construction of the Message._i
+  /// field (i.e. the BuilderInfo metadata).
+  void removeMetadataForUnusedFields(
+      Set<Class> gmSubclasses,
+      Map<Class, Set<Selector>> invokedMethods,
+      CoreTypes coreTypes,
+      TransformationInfo info) {
+    for (final klass in gmSubclasses) {
+      final selectors = invokedMethods[klass] ?? Set<Selector>();
+      final builderInfoFields = klass.fields.where((f) => f.name.name == '_i');
+      if (builderInfoFields.isEmpty) {
+        continue;
+      }
+      final builderInfoField = builderInfoFields.single;
+      _pruneBuilderInfoField(builderInfoField, selectors, klass);
+    }
+  }
+
+  void _pruneBuilderInfoField(
+      Field field, Set<Selector> selectors, Class gmSubclass) {
+    names.clear();
+    names.addAll(selectors.map((sel) => sel.target.name));
+    visitedClass = gmSubclass;
+    field.initializer.accept(this);
+  }
+
+  @override
+  visitLet(Let node) {
+    final initializer = node.variable.initializer;
+    if (initializer is MethodInvocation &&
+        initializer.interfaceTarget?.enclosingClass == builderInfoClass &&
+        fieldAddingMethods.contains(initializer.name.name)) {
+      final fieldName =
+          (initializer.arguments.positional[1] as StringLiteral).value;
+      final ucase = fieldName[0].toUpperCase() + fieldName.substring(1);
+      // The name of the related `clear` method.
+      final clearName = 'clear${ucase}';
+      // The name of the related `has` method.
+      final hasName = 'has${ucase}';
+
+      bool nameIsUsed(String name) =>
+          dynamicNames.contains(name) || names.contains(name);
+
+      if (!(nameIsUsed(fieldName) ||
+          nameIsUsed(clearName) ||
+          nameIsUsed(hasName))) {
+        if (info != null) {
+          info.removedMessageFields.add("${visitedClass.name}.$fieldName");
+        }
+
+        // Replace the field metadata method with a dummy call to
+        // `BuilderInfo.add`. This is to preserve the index calculations when
+        // removing a field.
+        // Change the tag-number to 0. Otherwise the decoder will get confused.
+        initializer.interfaceTarget = addMethod;
+        initializer.name = addMethod.name;
+        initializer.arguments.replaceWith(
+          Arguments(
+            <Expression>[
+              IntLiteral(0), // tagNumber
+              NullLiteral(), // name
+              NullLiteral(), // fieldType
+              NullLiteral(), // defaultOrMaker
+              NullLiteral(), // subBuilder
+              NullLiteral(), // valueOf
+              NullLiteral(), // enumValues
+            ],
+            types: <DartType>[InterfaceType(coreTypes.nullClass)],
+          ),
+        );
+      }
+    }
+    node.body.accept(this);
+  }
+}
+
+/// Finds all subclasses of [GeneratedMessage] and all methods invoked on them
+/// (potentially in a dynamic call).
+class InfoCollector extends RecursiveVisitor<void> {
+  final dynamicSelectors = Set<Selector>();
+  final Class generatedMessageClass;
+  final gmSubclasses = Set<Class>();
+  final gmSubclassesInvokedMethods = Map<Class, Set<Selector>>();
+
+  InfoCollector(this.generatedMessageClass);
+
+  @override
+  visitClass(Class klass) {
+    if (isGeneratedMethodSubclass(klass)) {
+      gmSubclasses.add(klass);
+    }
+    return super.visitClass(klass);
+  }
+
+  @override
+  visitMethodInvocation(MethodInvocation node) {
+    if (node.interfaceTarget == null) {
+      dynamicSelectors.add(Selector.doInvoke(node.name));
+    }
+
+    final targetClass = node.interfaceTarget?.enclosingClass;
+    if (isGeneratedMethodSubclass(targetClass)) {
+      addInvokedMethod(targetClass, Selector.doInvoke(node.name));
+    }
+    super.visitMethodInvocation(node);
+  }
+
+  @override
+  visitPropertyGet(PropertyGet node) {
+    if (node.interfaceTarget == null) {
+      dynamicSelectors.add(Selector.doGet(node.name));
+    }
+
+    final targetClass = node.interfaceTarget?.enclosingClass;
+    if (isGeneratedMethodSubclass(targetClass)) {
+      addInvokedMethod(targetClass, Selector.doGet(node.name));
+    }
+    super.visitPropertyGet(node);
+  }
+
+  @override
+  visitPropertySet(PropertySet node) {
+    if (node.interfaceTarget == null) {
+      dynamicSelectors.add(Selector.doSet(node.name));
+    }
+
+    final targetClass = node.interfaceTarget?.enclosingClass;
+    if (isGeneratedMethodSubclass(targetClass)) {
+      addInvokedMethod(targetClass, Selector.doSet(node.name));
+    }
+    super.visitPropertySet(node);
+  }
+
+  bool isGeneratedMethodSubclass(Class klass) {
+    return klass?.superclass == generatedMessageClass;
+  }
+
+  void addInvokedMethod(Class klass, Selector selector) {
+    final selectors =
+        gmSubclassesInvokedMethods.putIfAbsent(klass, () => Set<Selector>());
+    selectors.add(selector);
+  }
+}
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index f4e50e7..23f8d8b 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -870,6 +870,12 @@
   }
 
   @override
+  TypeExpr visitBlockExpression(BlockExpression node) {
+    _visit(node.body);
+    return _visit(node.value);
+  }
+
+  @override
   TypeExpr visitListLiteral(ListLiteral node) {
     node.expressions.forEach(_visit);
     Class concreteClass =
diff --git a/pkg/vm/test/frontend_server_test.dart b/pkg/vm/test/frontend_server_test.dart
index 4a4a7d8..bf7bf47 100644
--- a/pkg/vm/test/frontend_server_test.dart
+++ b/pkg/vm/test/frontend_server_test.dart
@@ -179,7 +179,7 @@
           new StreamController<List<int>>();
       final ReceivePort recompileCalled = new ReceivePort();
 
-      when(compiler.recompileDelta(filename: null))
+      when(compiler.recompileDelta(entryPoint: null))
           .thenAnswer((Invocation invocation) {
         recompileCalled.sendPort.send(true);
       });
@@ -195,7 +195,7 @@
       verifyInOrder(<void>[
         compiler.invalidate(Uri.base.resolve('file1.dart')),
         compiler.invalidate(Uri.base.resolve('file2.dart')),
-        await compiler.recompileDelta(filename: null),
+        await compiler.recompileDelta(entryPoint: null),
       ]);
       inputStreamController.add('quit\n'.codeUnits);
       expect(await result, 0);
@@ -207,7 +207,7 @@
           new StreamController<List<int>>();
       final ReceivePort recompileCalled = new ReceivePort();
 
-      when(compiler.recompileDelta(filename: 'file2.dart'))
+      when(compiler.recompileDelta(entryPoint: 'file2.dart'))
           .thenAnswer((Invocation invocation) {
         recompileCalled.sendPort.send(true);
       });
@@ -223,7 +223,7 @@
       verifyInOrder(<void>[
         compiler.invalidate(Uri.base.resolve('file1.dart')),
         compiler.invalidate(Uri.base.resolve('file2.dart')),
-        await compiler.recompileDelta(filename: 'file2.dart'),
+        await compiler.recompileDelta(entryPoint: 'file2.dart'),
       ]);
       inputStreamController.add('quit\n'.codeUnits);
       expect(await result, 0);
@@ -274,7 +274,7 @@
           new StreamController<List<int>>();
       final ReceivePort recompileCalled = new ReceivePort();
 
-      when(compiler.recompileDelta(filename: null))
+      when(compiler.recompileDelta(entryPoint: null))
           .thenAnswer((Invocation invocation) {
         recompileCalled.sendPort.send(true);
       });
@@ -295,7 +295,7 @@
         compiler.acceptLastDelta(),
         compiler.invalidate(Uri.base.resolve('file2.dart')),
         compiler.invalidate(Uri.base.resolve('file3.dart')),
-        await compiler.recompileDelta(filename: null),
+        await compiler.recompileDelta(entryPoint: null),
       ]);
       inputStreamController.add('quit\n'.codeUnits);
       expect(await result, 0);
@@ -426,41 +426,25 @@
       final StreamController<List<int>> stdoutStreamController =
           new StreamController<List<int>>();
       final IOSink ioSink = new IOSink(stdoutStreamController.sink);
-      StreamController<String> receivedResults = new StreamController<String>();
-
-      String boundaryKey;
+      StreamController<Result> receivedResults = new StreamController<Result>();
+      final outputParser = new OutputParser(receivedResults);
       stdoutStreamController.stream
           .transform(utf8.decoder)
           .transform(const LineSplitter())
-          .listen((String s) {
-        const String RESULT_OUTPUT_SPACE = 'result ';
-        if (boundaryKey == null) {
-          if (s.startsWith(RESULT_OUTPUT_SPACE)) {
-            boundaryKey = s.substring(RESULT_OUTPUT_SPACE.length);
-          }
-        } else {
-          if (s.startsWith(boundaryKey)) {
-            receivedResults.add(s.length > boundaryKey.length
-                ? s.substring(boundaryKey.length + 1)
-                : null);
-            boundaryKey = null;
-          }
-        }
-      });
+          .listen(outputParser.listener);
 
       Future<int> result =
           starter(args, input: streamController.stream, output: ioSink);
       streamController.add('compile ${file.path}\n'.codeUnits);
       int count = 0;
-      receivedResults.stream.listen((String outputFilenameAndErrorCount) {
+      receivedResults.stream.listen((Result compiledResult) {
+        CompilationResult result =
+            new CompilationResult.parse(compiledResult.status);
         if (count == 0) {
           // First request is to 'compile', which results in full kernel file.
-          CompilationResult result =
-              new CompilationResult.parse(outputFilenameAndErrorCount);
-
+          expect(result.errorsCount, equals(0));
           expect(dillFile.existsSync(), equals(true));
           expect(result.filename, dillFile.path);
-          expect(result.errorsCount, equals(0));
           streamController.add('accept\n'.codeUnits);
 
           // 'compile-expression <boundarykey>
@@ -474,26 +458,25 @@
           // <libraryUri: String>
           // <klass: String>
           // <isStatic: true|false>
+          outputParser.expectSources = false;
           streamController.add(
               'compile-expression abc\n2+2\nabc\nabc\n${file.uri}\n\n\n'
                   .codeUnits);
           count += 1;
         } else if (count == 1) {
+          expect(result.errorsCount, isNull);
           // Previous request should have failed because isStatic was blank
-          expect(outputFilenameAndErrorCount, isNull);
+          expect(compiledResult.status, isNull);
 
+          outputParser.expectSources = false;
           streamController.add(
               'compile-expression abc\n2+2\nabc\nabc\n${file.uri}\n\nfalse\n'
                   .codeUnits);
           count += 1;
         } else if (count == 2) {
+          expect(result.errorsCount, equals(0));
           // Second request is to 'compile-expression', which results in
           // kernel file with a function that wraps compiled expression.
-          expect(outputFilenameAndErrorCount, isNotNull);
-          CompilationResult result =
-              new CompilationResult.parse(outputFilenameAndErrorCount);
-
-          expect(result.errorsCount, equals(0));
           File outputFile = new File(result.filename);
           expect(outputFile.existsSync(), equals(true));
           expect(outputFile.lengthSync(), isPositive);
@@ -503,9 +486,6 @@
         } else {
           expect(count, 3);
           // Third request is to 'compile' non-existent file, that should fail.
-          expect(outputFilenameAndErrorCount, isNotNull);
-          CompilationResult result =
-              new CompilationResult.parse(outputFilenameAndErrorCount);
           expect(result.errorsCount, greaterThan(0));
 
           streamController.add('quit\n'.codeUnits);
@@ -515,6 +495,126 @@
       expect(await result, 0);
     });
 
+    test('compiler reports correct sources added', () async {
+      var libFile = new File('${tempDir.path}/lib.dart')
+        ..createSync(recursive: true)
+        ..writeAsStringSync("var foo = 42;");
+      var mainFile = new File('${tempDir.path}/main.dart')
+        ..createSync(recursive: true)
+        ..writeAsStringSync("main() => print('foo');\n");
+      var dillFile = new File('${tempDir.path}/app.dill');
+      expect(dillFile.existsSync(), equals(false));
+      final List<String> args = <String>[
+        '--sdk-root=${sdkRoot.toFilePath()}',
+        '--incremental',
+        '--platform=${platformKernel.path}',
+        '--output-dill=${dillFile.path}'
+      ];
+
+      final StreamController<List<int>> inputStreamController =
+          new StreamController<List<int>>();
+      final StreamController<List<int>> stdoutStreamController =
+          new StreamController<List<int>>();
+      final IOSink ioSink = new IOSink(stdoutStreamController.sink);
+      StreamController<Result> receivedResults = new StreamController<Result>();
+
+      final outputParser = new OutputParser(receivedResults);
+      stdoutStreamController.stream
+          .transform(utf8.decoder)
+          .transform(const LineSplitter())
+          .listen(outputParser.listener);
+
+      final Future<int> result =
+          starter(args, input: inputStreamController.stream, output: ioSink);
+      inputStreamController.add('compile ${mainFile.path}\n'.codeUnits);
+      int count = 0;
+      receivedResults.stream.listen((Result compiledResult) {
+        compiledResult.expectNoErrors();
+        if (count == 0) {
+          expect(compiledResult.sources.length, equals(1));
+          expect(compiledResult.sources, contains('+${mainFile.uri}'));
+
+          inputStreamController.add('accept\n'.codeUnits);
+          mainFile
+              .writeAsStringSync("import 'lib.dart';  main() => print(foo);\n");
+          inputStreamController.add('recompile ${mainFile.path} abc\n'
+              '${mainFile.uri}\n'
+              'abc\n'
+              .codeUnits);
+          count += 1;
+        } else if (count == 1) {
+          expect(compiledResult.sources.length, equals(1));
+          expect(compiledResult.sources, contains('+${libFile.uri}'));
+          inputStreamController.add('accept\n'.codeUnits);
+          inputStreamController.add('quit\n'.codeUnits);
+        }
+      });
+
+      expect(await result, 0);
+      inputStreamController.close();
+    }, timeout: Timeout.factor(100));
+
+    test('compiler reports correct sources removed', () async {
+      var libFile = new File('${tempDir.path}/lib.dart')
+        ..createSync(recursive: true)
+        ..writeAsStringSync("var foo = 42;");
+      var mainFile = new File('${tempDir.path}/main.dart')
+        ..createSync(recursive: true)
+        ..writeAsStringSync("import 'lib.dart'; main() => print(foo);\n");
+      var dillFile = new File('${tempDir.path}/app.dill');
+      expect(dillFile.existsSync(), equals(false));
+      final List<String> args = <String>[
+        '--sdk-root=${sdkRoot.toFilePath()}',
+        '--incremental',
+        '--platform=${platformKernel.path}',
+        '--output-dill=${dillFile.path}'
+      ];
+
+      final StreamController<List<int>> inputStreamController =
+          new StreamController<List<int>>();
+      final StreamController<List<int>> stdoutStreamController =
+          new StreamController<List<int>>();
+      final IOSink ioSink = new IOSink(stdoutStreamController.sink);
+      StreamController<Result> receivedResults = new StreamController<Result>();
+
+      final outputParser = new OutputParser(receivedResults);
+      stdoutStreamController.stream
+          .transform(utf8.decoder)
+          .transform(const LineSplitter())
+          .listen(outputParser.listener);
+
+      final Future<int> result =
+          starter(args, input: inputStreamController.stream, output: ioSink);
+      inputStreamController.add('compile ${mainFile.path}\n'.codeUnits);
+      int count = 0;
+      receivedResults.stream.listen((Result compiledResult) {
+        compiledResult.expectNoErrors();
+        if (count == 0) {
+          expect(compiledResult.sources.length, equals(2));
+          expect(compiledResult.sources,
+              allOf(contains('+${mainFile.uri}'), contains('+${libFile.uri}')));
+
+          inputStreamController.add('accept\n'.codeUnits);
+          mainFile.writeAsStringSync("main() => print('foo');\n");
+          inputStreamController.add('recompile ${mainFile.path} abc\n'
+              '${mainFile.uri}\n'
+              'abc\n'
+              .codeUnits);
+          count += 1;
+        } else if (count == 1) {
+          expect(compiledResult.sources.length, equals(1));
+          expect(compiledResult.sources, contains('-${libFile.uri}'));
+          inputStreamController.add('accept\n'.codeUnits);
+          inputStreamController.add('quit\n'.codeUnits);
+        }
+      });
+
+      expect(await result, 0);
+      inputStreamController.close();
+    },
+        timeout: Timeout.factor(100),
+        skip: true /* TODO(dartbug/36197): Unskip when compiler is fixed. */);
+
     test('compile expression when delta is rejected', () async {
       var fileLib = new File('${tempDir.path}/lib.dart')..createSync();
       fileLib.writeAsStringSync("foo() => 42;\n");
@@ -534,42 +634,26 @@
       final StreamController<List<int>> stdoutStreamController =
           new StreamController<List<int>>();
       final IOSink ioSink = new IOSink(stdoutStreamController.sink);
-      StreamController<String> receivedResults = new StreamController<String>();
+      StreamController<Result> receivedResults = new StreamController<Result>();
 
-      String boundaryKey;
+      final outputParser = new OutputParser(receivedResults);
       stdoutStreamController.stream
           .transform(utf8.decoder)
           .transform(const LineSplitter())
-          .listen((String s) {
-        print(s);
-        const String RESULT_OUTPUT_SPACE = 'result ';
-        if (boundaryKey == null) {
-          if (s.startsWith(RESULT_OUTPUT_SPACE)) {
-            boundaryKey = s.substring(RESULT_OUTPUT_SPACE.length);
-          }
-        } else {
-          if (s.startsWith(boundaryKey)) {
-            receivedResults.add(s.length > boundaryKey.length
-                ? s.substring(boundaryKey.length + 1)
-                : null);
-            boundaryKey = null;
-          }
-        }
-      });
+          .listen(outputParser.listener);
 
       final Future<int> result =
           starter(args, input: inputStreamController.stream, output: ioSink);
       inputStreamController.add('compile ${file.path}\n'.codeUnits);
       int count = 0;
-      receivedResults.stream.listen((String outputFilenameAndErrorCount) {
+      receivedResults.stream.listen((Result compiledResult) {
+        CompilationResult result =
+            new CompilationResult.parse(compiledResult.status);
         if (count == 0) {
           // First request was to 'compile', which resulted in full kernel file.
-          CompilationResult result =
-              new CompilationResult.parse(outputFilenameAndErrorCount);
-
+          expect(result.errorsCount, 0);
           expect(dillFile.existsSync(), equals(true));
           expect(result.filename, dillFile.path);
-          expect(result.errorsCount, equals(0));
           inputStreamController.add('accept\n'.codeUnits);
 
           // 'compile-expression <boundarykey>
@@ -583,6 +667,7 @@
           // <libraryUri: String>
           // <klass: String>
           // <isStatic: true|false>
+          outputParser.expectSources = false;
           inputStreamController.add('''
 compile-expression abc
 main1
@@ -597,12 +682,7 @@
         } else if (count == 1) {
           // Second request was to 'compile-expression', which resulted in
           // kernel file with a function that wraps compiled expression.
-          expect(outputFilenameAndErrorCount, isNotNull);
-          CompilationResult result =
-              new CompilationResult.parse(outputFilenameAndErrorCount);
-          print(outputFilenameAndErrorCount);
-
-          expect(result.errorsCount, equals(0));
+          expect(result.errorsCount, 0);
           File outputFile = new File(result.filename);
           expect(outputFile.existsSync(), equals(true));
           expect(outputFile.lengthSync(), isPositive);
@@ -616,15 +696,13 @@
           count += 1;
         } else if (count == 2) {
           // Third request was to recompile the script after renaming a function.
-          expect(outputFilenameAndErrorCount, isNotNull);
-          CompilationResult result =
-              new CompilationResult.parse(outputFilenameAndErrorCount);
-          expect(result.errorsCount, equals(0));
-
+          expect(result.errorsCount, 0);
+          outputParser.expectSources = false;
           inputStreamController.add('reject\n'.codeUnits);
           count += 1;
         } else if (count == 3) {
           // Fourth request was to reject the compilation results.
+          outputParser.expectSources = false;
           inputStreamController.add(
               'compile-expression abc\nmain1\nabc\nabc\n${file.uri}\n\ntrue\n'
                   .codeUnits);
@@ -633,10 +711,7 @@
           expect(count, 4);
           // Fifth request was to 'compile-expression' that references original
           // function, which should still be successful.
-          expect(outputFilenameAndErrorCount, isNotNull);
-          CompilationResult result =
-              new CompilationResult.parse(outputFilenameAndErrorCount);
-          expect(result.errorsCount, equals(0));
+          expect(result.errorsCount, 0);
           inputStreamController.add('quit\n'.codeUnits);
         }
       });
@@ -662,37 +737,23 @@
       final StreamController<List<int>> stdoutStreamController =
           new StreamController<List<int>>();
       final IOSink ioSink = new IOSink(stdoutStreamController.sink);
-      StreamController<String> receivedResults = new StreamController<String>();
+      StreamController<Result> receivedResults = new StreamController<Result>();
 
-      String boundaryKey;
+      final outputParser = new OutputParser(receivedResults);
       stdoutStreamController.stream
           .transform(utf8.decoder)
           .transform(const LineSplitter())
-          .listen((String s) {
-        const String RESULT_OUTPUT_SPACE = 'result ';
-        if (boundaryKey == null) {
-          if (s.startsWith(RESULT_OUTPUT_SPACE)) {
-            boundaryKey = s.substring(RESULT_OUTPUT_SPACE.length);
-          }
-        } else {
-          if (s.startsWith(boundaryKey)) {
-            receivedResults.add(s.substring(boundaryKey.length + 1));
-            boundaryKey = null;
-          }
-        }
-      });
+          .listen(outputParser.listener);
+
       Future<int> result =
           starter(args, input: inputStreamController.stream, output: ioSink);
       inputStreamController.add('compile ${file.path}\n'.codeUnits);
       int count = 0;
-      receivedResults.stream.listen((String outputFilenameAndErrorCount) {
-        CompilationResult result =
-            new CompilationResult.parse(outputFilenameAndErrorCount);
+      receivedResults.stream.listen((Result compiledResult) {
         if (count == 0) {
           // First request is to 'compile', which results in full kernel file.
           expect(dillFile.existsSync(), equals(true));
-          expect(result.filename, dillFile.path);
-          expect(result.errorsCount, 0);
+          compiledResult.expectNoErrors(filename: dillFile.path);
           count += 1;
           inputStreamController.add('accept\n'.codeUnits);
           var file2 = new File('${tempDir.path}/bar.dart')..createSync();
@@ -706,8 +767,7 @@
           // Second request is to 'recompile', which results in incremental
           // kernel file.
           var dillIncFile = new File('${dillFile.path}.incremental.dill');
-          expect(result.filename, dillIncFile.path);
-          expect(result.errorsCount, 0);
+          compiledResult.expectNoErrors(filename: dillIncFile.path);
           expect(dillIncFile.existsSync(), equals(true));
           inputStreamController.add('quit\n'.codeUnits);
         }
@@ -771,32 +831,20 @@
       final StreamController<List<int>> stdoutStreamController =
           new StreamController<List<int>>();
       final IOSink ioSink = new IOSink(stdoutStreamController.sink);
-      StreamController<String> receivedResults = new StreamController<String>();
-
-      String boundaryKey;
+      StreamController<Result> receivedResults = new StreamController<Result>();
+      final outputParser = new OutputParser(receivedResults);
       stdoutStreamController.stream
           .transform(utf8.decoder)
           .transform(const LineSplitter())
-          .listen((String s) {
-        const String RESULT_OUTPUT_SPACE = 'result ';
-        if (boundaryKey == null) {
-          if (s.startsWith(RESULT_OUTPUT_SPACE)) {
-            boundaryKey = s.substring(RESULT_OUTPUT_SPACE.length);
-          }
-        } else {
-          if (s.startsWith(boundaryKey)) {
-            receivedResults.add(s.substring(boundaryKey.length + 1));
-            boundaryKey = null;
-          }
-        }
-      });
+          .listen(outputParser.listener);
+
       Future<int> result =
           starter(args, input: inputStreamController.stream, output: ioSink);
       inputStreamController.add('compile ${file.path}\n'.codeUnits);
       int count = 0;
-      receivedResults.stream.listen((String outputFilenameAndErrorCount) {
+      receivedResults.stream.listen((Result compiledResult) {
         CompilationResult result =
-            new CompilationResult.parse(outputFilenameAndErrorCount);
+            new CompilationResult.parse(compiledResult.status);
         switch (count) {
           case 0:
             expect(dillFile.existsSync(), equals(true));
@@ -854,32 +902,21 @@
       final StreamController<List<int>> stdoutStreamController =
           new StreamController<List<int>>();
       final IOSink ioSink = new IOSink(stdoutStreamController.sink);
-      StreamController<String> receivedResults = new StreamController<String>();
+      StreamController<Result> receivedResults = new StreamController<Result>();
 
-      String boundaryKey;
+      final outputParser = new OutputParser(receivedResults);
       stdoutStreamController.stream
           .transform(utf8.decoder)
           .transform(const LineSplitter())
-          .listen((String s) {
-        const String RESULT_OUTPUT_SPACE = 'result ';
-        if (boundaryKey == null) {
-          if (s.startsWith(RESULT_OUTPUT_SPACE)) {
-            boundaryKey = s.substring(RESULT_OUTPUT_SPACE.length);
-          }
-        } else {
-          if (s.startsWith(boundaryKey)) {
-            receivedResults.add(s.substring(boundaryKey.length + 1));
-            boundaryKey = null;
-          }
-        }
-      });
+          .listen(outputParser.listener);
+
       Future<int> result =
           starter(args, input: inputStreamController.stream, output: ioSink);
-      inputStreamController.add('compile ${file.path}\n'.codeUnits);
+      inputStreamController.add('compile ${file.uri}\n'.codeUnits);
       int count = 0;
-      receivedResults.stream.listen((String outputFilenameAndErrorCount) {
+      receivedResults.stream.listen((Result compiledResult) {
         CompilationResult result =
-            new CompilationResult.parse(outputFilenameAndErrorCount);
+            new CompilationResult.parse(compiledResult.status);
         switch (count) {
           case 0:
             expect(dillFile.existsSync(), equals(true));
@@ -889,8 +926,8 @@
             inputStreamController.add('accept\n'.codeUnits);
             var file2 = new File('${tempDir.path}/bar.dart')..createSync();
             file2.writeAsStringSync("main() { baz(); }\n");
-            inputStreamController.add('recompile ${file2.path} abc\n'
-                '${file2.path}\n'
+            inputStreamController.add('recompile ${file2.uri} abc\n'
+                '${file2.uri}\n'
                 'abc\n'
                 .codeUnits);
             break;
@@ -902,8 +939,8 @@
             inputStreamController.add('accept\n'.codeUnits);
             var file2 = new File('${tempDir.path}/bar.dart')..createSync();
             file2.writeAsStringSync("main() { }\n");
-            inputStreamController.add('recompile ${file2.path} abc\n'
-                '${file2.path}\n'
+            inputStreamController.add('recompile ${file2.uri} abc\n'
+                '${file2.uri}\n'
                 'abc\n'
                 .codeUnits);
             break;
@@ -1035,36 +1072,23 @@
         final StreamController<List<int>> stdoutStreamController =
             new StreamController<List<int>>();
         final IOSink ioSink = new IOSink(stdoutStreamController.sink);
-        StreamController<String> receivedResults =
-            new StreamController<String>();
+        StreamController<Result> receivedResults =
+            new StreamController<Result>();
 
-        String boundaryKey;
+        final outputParser = new OutputParser(receivedResults);
         stdoutStreamController.stream
             .transform(utf8.decoder)
             .transform(const LineSplitter())
-            .listen((String s) {
-          const String RESULT_OUTPUT_SPACE = 'result ';
-          if (boundaryKey == null) {
-            if (s.startsWith(RESULT_OUTPUT_SPACE)) {
-              boundaryKey = s.substring(RESULT_OUTPUT_SPACE.length);
-            }
-          } else {
-            if (s.startsWith(boundaryKey)) {
-              receivedResults.add(s.substring(boundaryKey.length + 1));
-              boundaryKey = null;
-            }
-          }
-        });
+            .listen(outputParser.listener);
 
         Future<int> result =
             starter(args, input: inputStreamController.stream, output: ioSink);
         inputStreamController.add('compile ${dart2js.path}\n'.codeUnits);
         int count = 0;
-        receivedResults.stream.listen((String outputFilenameAndErrorCount) {
-          int delim = outputFilenameAndErrorCount.lastIndexOf(' ');
-          expect(delim > 0, equals(true));
-          String outputFilename =
-              outputFilenameAndErrorCount.substring(0, delim);
+        receivedResults.stream.listen((Result compiledResult) {
+          CompilationResult result =
+              CompilationResult.parse(compiledResult.status);
+          String outputFilename = result.filename;
           print("$outputFilename -- count $count");
 
           // Ensure that kernel file produced when compiler was initialized
@@ -1205,9 +1229,75 @@
   int errorsCount;
 
   CompilationResult.parse(String filenameAndErrorCount) {
+    if (filenameAndErrorCount == null) {
+      return;
+    }
     int delim = filenameAndErrorCount.lastIndexOf(' ');
     expect(delim > 0, equals(true));
     filename = filenameAndErrorCount.substring(0, delim);
     errorsCount = int.parse(filenameAndErrorCount.substring(delim + 1).trim());
   }
 }
+
+class Result {
+  String status;
+  List<String> sources;
+
+  Result(this.status, this.sources);
+
+  void expectNoErrors({String filename}) {
+    var result = CompilationResult.parse(status);
+    expect(result.errorsCount, equals(0));
+    if (filename != null) {
+      expect(result.filename, equals(filename));
+    }
+  }
+}
+
+class OutputParser {
+  OutputParser(this._receivedResults);
+  bool expectSources = true;
+
+  StreamController<Result> _receivedResults;
+  List<String> _receivedSources;
+
+  String _boundaryKey;
+  bool _readingSources;
+
+  void listener(String s) {
+    if (_boundaryKey == null) {
+      const String RESULT_OUTPUT_SPACE = 'result ';
+      if (s.startsWith(RESULT_OUTPUT_SPACE)) {
+        _boundaryKey = s.substring(RESULT_OUTPUT_SPACE.length);
+      }
+      _readingSources = false;
+      _receivedSources?.clear();
+      return;
+    }
+
+    if (s.startsWith(_boundaryKey)) {
+      // First boundaryKey separates compiler output from list of sources
+      // (if we expect list of sources, which is indicated by receivedSources
+      // being not null)
+      if (expectSources && !_readingSources) {
+        _readingSources = true;
+        return;
+      }
+      // Second boundaryKey indicates end of frontend server response
+      expectSources = true;
+      _receivedResults.add(Result(
+          s.length > _boundaryKey.length
+              ? s.substring(_boundaryKey.length + 1)
+              : null,
+          _receivedSources));
+      _boundaryKey = null;
+    } else {
+      if (_readingSources) {
+        if (_receivedSources == null) {
+          _receivedSources = <String>[];
+        }
+        _receivedSources.add(s);
+      }
+    }
+  }
+}
diff --git a/pkg/vm/test/incremental_compiler_test.dart b/pkg/vm/test/incremental_compiler_test.dart
index 7f4482d..349b566 100644
--- a/pkg/vm/test/incremental_compiler_test.dart
+++ b/pkg/vm/test/incremental_compiler_test.dart
@@ -36,12 +36,25 @@
     };
 
   group('basic', () {
-    test('compile', () async {
-      var systemTempDir = Directory.systemTemp;
-      var file = new File('${systemTempDir.path}/foo.dart')..createSync();
-      file.writeAsStringSync("main() {}\n");
+    Directory mytest;
+    File main;
 
-      IncrementalCompiler compiler = new IncrementalCompiler(options, file.uri);
+    setUpAll(() {
+      mytest = Directory.systemTemp.createTempSync('incremental');
+      main = new File('${mytest.path}/main.dart')..createSync();
+      main.writeAsStringSync("main() {}\n");
+    });
+
+    tearDownAll(() {
+      try {
+        mytest.deleteSync(recursive: true);
+      } catch (_) {
+        // Ignore errors;
+      }
+    });
+
+    test('compile', () async {
+      IncrementalCompiler compiler = new IncrementalCompiler(options, main.uri);
       Component component = await compiler.compile();
 
       final StringBuffer buffer = new StringBuffer();
@@ -56,13 +69,14 @@
     });
 
     test('compile exclude sources', () async {
-      var systemTempDir = Directory.systemTemp;
-      var file = new File('${systemTempDir.path}/foo.dart')..createSync();
-      file.writeAsStringSync("main() {}\n");
-
-      CompilerOptions optionsExcludeSources = options..embedSourceText = false;
+      CompilerOptions optionsExcludeSources = new CompilerOptions()
+        ..sdkRoot = options.sdkRoot
+        ..target = options.target
+        ..linkedDependencies = options.linkedDependencies
+        ..onDiagnostic = options.onDiagnostic
+        ..embedSourceText = false;
       IncrementalCompiler compiler =
-          new IncrementalCompiler(optionsExcludeSources, file.uri);
+          new IncrementalCompiler(optionsExcludeSources, main.uri);
       Component component = await compiler.compile();
 
       for (Source source in component.uriToSource.values) {
@@ -79,6 +93,37 @@
               '\n'
               'static method main() → dynamic {}\n'));
     });
+
+    test('compile expressions errors are not re-reported', () async {
+      var errorsReported = 0;
+      CompilerOptions optionsAcceptErrors = new CompilerOptions()
+        ..sdkRoot = options.sdkRoot
+        ..target = options.target
+        ..linkedDependencies = options.linkedDependencies
+        ..onDiagnostic = (DiagnosticMessage message) {
+          errorsReported++;
+          message.plainTextFormatted.forEach(print);
+        };
+      IncrementalCompiler compiler =
+          new IncrementalCompiler(optionsAcceptErrors, main.uri);
+      await compiler.compile();
+      compiler.accept();
+      {
+        Procedure procedure = await compiler.compileExpression(
+            'main', <String>[], <String>[], main.uri.toString(), null, true);
+        expect(procedure, isNotNull);
+        expect(errorsReported, equals(0));
+      }
+      {
+        Procedure procedure = await compiler.compileExpression(
+            'main1', <String>[], <String>[], main.uri.toString(), null, true);
+        expect(procedure, isNotNull);
+        expect(errorsReported, equals(1));
+        errorsReported = 0;
+      }
+      await compiler.compile();
+      expect(errorsReported, equals(0));
+    });
   });
 
   group('multiple kernels', () {
diff --git a/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart b/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
new file mode 100644
index 0000000..66d662e
--- /dev/null
+++ b/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2019, 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:io';
+
+import 'package:kernel/target/targets.dart';
+import 'package:kernel/ast.dart';
+import 'package:kernel/kernel.dart';
+import 'package:kernel/binary/limited_ast_to_binary.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+
+import 'package:vm/transformations/protobuf_aware_treeshaker/transformer.dart'
+    as treeshaker;
+
+import '../../common_test_utils.dart';
+
+final String pkgVmDir = Platform.script.resolve('../../..').toFilePath();
+
+runTestCase(Uri source) async {
+  final target = new TestingVmTarget(new TargetFlags());
+  Component component =
+      await compileTestCaseToKernelProgram(source, target: target);
+
+  List<Class> messageClasses = component.libraries
+      .expand(
+        (lib) => lib.classes.where((klass) =>
+            klass.superclass != null &&
+            klass.superclass.name == "GeneratedMessage"),
+      )
+      .toList();
+
+  treeshaker.transformComponent(component, {}, TestingVmTarget(TargetFlags()),
+      collectInfo: true, enableAsserts: false);
+
+  for (Class messageClass in messageClasses) {
+    expect(messageClass.enclosingLibrary.classes.contains(messageClass),
+        messageClass.name.endsWith('Keep'));
+  }
+
+  final systemTempDir = Directory.systemTemp;
+  final file =
+      new File('${systemTempDir.path}/${source.pathSegments.last}.dill');
+  try {
+    final sink = file.openWrite();
+    final printer =
+        LimitedBinaryPrinter(sink, (lib) => true, /*excludeUriToSource=*/ true);
+
+    printer.writeComponentFile(component);
+    await sink.close();
+
+    ProcessResult result =
+        Process.runSync(Platform.resolvedExecutable, [file.path]);
+    expect(result.exitCode, 0);
+  } finally {
+    if (file.existsSync()) {
+      file.deleteSync();
+    }
+  }
+}
+
+main() async {
+  final testCases = Directory(path.join(
+    pkgVmDir,
+    'testcases',
+    'transformations',
+    'protobuf_aware_treeshaker',
+    'lib',
+  )).listSync().where((f) => f.path.endsWith('_test.dart'));
+  for (final entry in testCases) {
+    test(entry.path, () => runTestCase(entry.uri));
+  }
+}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/compile_protos.sh b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/compile_protos.sh
new file mode 100755
index 0000000..b4793ee
--- /dev/null
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/compile_protos.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+# Copyright (c) 2019, 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.
+
+# Running this script requires having protoc_plugin installed in your path.
+
+rm -rf lib/generated
+mkdir lib/generated
+
+# Directory of the script
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
+GENERATED_DIR=$DIR/lib/generated
+
+protoc --dart_out=$GENERATED_DIR -I$DIR/protos $DIR/protos/*.proto
+rm $GENERATED_DIR/*.pbenum.dart $GENERATED_DIR/*.pbjson.dart $GENERATED_DIR/*.pbserver.dart
+
+dartfmt -w $DIR/lib/generated
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/create_test.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/create_test.dart
new file mode 100644
index 0000000..1912459
--- /dev/null
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/create_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2019, 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 'package:test/test.dart';
+
+import 'generated/foo.pb.dart';
+
+main() {
+  FooKeep foo = FooKeep()
+    ..barKeep = (BarKeep()..aKeep = 5)
+    ..mapKeep['foo'] = (BarKeep()..aKeep = 2)
+    ..aKeep = 43;
+  test('retrieving values', () {
+    expect(foo.barKeep.aKeep, 5);
+    expect(foo.mapKeep['foo'].aKeep, 2);
+    expect(foo.hasHasKeep(), false);
+    expect(foo.aKeep, 43);
+    foo.clearClearKeep();
+  });
+}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/decode_test.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/decode_test.dart
new file mode 100644
index 0000000..d33289f
--- /dev/null
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/decode_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2019, 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 'package:test/test.dart';
+
+import 'generated/foo.pb.dart';
+
+List<int> buffer = <int>[
+  10, 4, 8, 5, 16, //
+  4, 26, 9, 10, 3,
+  102, 111, 111, 18, 2,
+  8, 42, 34, 9, 10,
+  3, 122, 111, 112, 18,
+  2, 8, 3, 40, 43,
+  50, 0, 58, 0,
+];
+
+main() {
+  FooKeep foo = FooKeep.fromBuffer(buffer);
+  test('Kept values are restored correctly', () {
+    expect(foo.mapKeep['foo'].aKeep, 42);
+    expect(foo.barKeep.aKeep, 5);
+    expect(foo.aKeep, 43);
+    expect(foo.hasHasKeep(), true);
+    foo.clearClearKeep();
+  });
+}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/encode_all_fields.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/encode_all_fields.dart
new file mode 100644
index 0000000..de756cc
--- /dev/null
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/encode_all_fields.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2019, 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:math';
+
+import 'generated/foo.pb.dart';
+
+main() {
+  FooKeep foo = FooKeep()
+    ..barKeep = (BarKeep()
+      ..aKeep = 5
+      ..bDrop = 4)
+    ..mapKeep['foo'] = (BarKeep()..aKeep = 42)
+    ..mapDrop['zop'] = (ZopDrop()..aDrop = 3)
+    ..aKeep = 43
+    ..hasKeep = HasKeep()
+    ..clearKeep = ClearKeep();
+  final buffer = foo.writeToBuffer();
+  print('List<int> buffer = <int>[');
+  for (int i = 0; i < buffer.length; i += 5) {
+    final numbers = buffer.sublist(i, min(buffer.length, i + 5)).join(', ');
+    print('  $numbers,${i == 0 ? ' //' : ''}');
+  }
+  print('];');
+}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/generated/foo.pb.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/generated/foo.pb.dart
new file mode 100644
index 0000000..4063773
--- /dev/null
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/generated/foo.pb.dart
@@ -0,0 +1,253 @@
+///
+//  Generated code. Do not modify.
+//  source: foo.proto
+///
+// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import
+
+// ignore: UNUSED_SHOWN_NAME
+import 'dart:core' show int, bool, double, String, List, Map, override;
+
+import 'package:protobuf/protobuf.dart' as $pb;
+
+class FooKeep extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = new $pb.BuilderInfo('FooKeep')
+    ..a<BarKeep>(
+        1, 'barKeep', $pb.PbFieldType.OM, BarKeep.getDefault, BarKeep.create)
+    ..a<BarKeep>(
+        2, 'barDrop', $pb.PbFieldType.OM, BarKeep.getDefault, BarKeep.create)
+    ..m<String, BarKeep>(3, 'mapKeep', 'FooKeep.MapKeepEntry',
+        $pb.PbFieldType.OS, $pb.PbFieldType.OM, BarKeep.create, null, null)
+    ..m<String, ZopDrop>(4, 'mapDrop', 'FooKeep.MapDropEntry',
+        $pb.PbFieldType.OS, $pb.PbFieldType.OM, ZopDrop.create, null, null)
+    ..a<int>(5, 'aKeep', $pb.PbFieldType.O3)
+    ..a<HasKeep>(
+        6, 'hasKeep', $pb.PbFieldType.OM, HasKeep.getDefault, HasKeep.create)
+    ..a<ClearKeep>(7, 'clearKeep', $pb.PbFieldType.OM, ClearKeep.getDefault,
+        ClearKeep.create)
+    ..hasRequiredFields = false;
+
+  FooKeep() : super();
+  FooKeep.fromBuffer(List<int> i,
+      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+      : super.fromBuffer(i, r);
+  FooKeep.fromJson(String i,
+      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+      : super.fromJson(i, r);
+  FooKeep clone() => new FooKeep()..mergeFromMessage(this);
+  FooKeep copyWith(void Function(FooKeep) updates) =>
+      super.copyWith((message) => updates(message as FooKeep));
+  $pb.BuilderInfo get info_ => _i;
+  static FooKeep create() => new FooKeep();
+  FooKeep createEmptyInstance() => create();
+  static $pb.PbList<FooKeep> createRepeated() => new $pb.PbList<FooKeep>();
+  static FooKeep getDefault() => _defaultInstance ??= create()..freeze();
+  static FooKeep _defaultInstance;
+
+  BarKeep get barKeep => $_getN(0);
+  set barKeep(BarKeep v) {
+    setField(1, v);
+  }
+
+  bool hasBarKeep() => $_has(0);
+  void clearBarKeep() => clearField(1);
+
+  BarKeep get barDrop => $_getN(1);
+  set barDrop(BarKeep v) {
+    setField(2, v);
+  }
+
+  bool hasBarDrop() => $_has(1);
+  void clearBarDrop() => clearField(2);
+
+  Map<String, BarKeep> get mapKeep => $_getMap(2);
+
+  Map<String, ZopDrop> get mapDrop => $_getMap(3);
+
+  int get aKeep => $_get(4, 0);
+  set aKeep(int v) {
+    $_setSignedInt32(4, v);
+  }
+
+  bool hasAKeep() => $_has(4);
+  void clearAKeep() => clearField(5);
+
+  HasKeep get hasKeep => $_getN(5);
+  set hasKeep(HasKeep v) {
+    setField(6, v);
+  }
+
+  bool hasHasKeep() => $_has(5);
+  void clearHasKeep() => clearField(6);
+
+  ClearKeep get clearKeep => $_getN(6);
+  set clearKeep(ClearKeep v) {
+    setField(7, v);
+  }
+
+  bool hasClearKeep() => $_has(6);
+  void clearClearKeep() => clearField(7);
+}
+
+class BarKeep extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = new $pb.BuilderInfo('BarKeep')
+    ..a<int>(1, 'aKeep', $pb.PbFieldType.O3)
+    ..a<int>(2, 'bDrop', $pb.PbFieldType.O3)
+    ..hasRequiredFields = false;
+
+  BarKeep() : super();
+  BarKeep.fromBuffer(List<int> i,
+      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+      : super.fromBuffer(i, r);
+  BarKeep.fromJson(String i,
+      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+      : super.fromJson(i, r);
+  BarKeep clone() => new BarKeep()..mergeFromMessage(this);
+  BarKeep copyWith(void Function(BarKeep) updates) =>
+      super.copyWith((message) => updates(message as BarKeep));
+  $pb.BuilderInfo get info_ => _i;
+  static BarKeep create() => new BarKeep();
+  BarKeep createEmptyInstance() => create();
+  static $pb.PbList<BarKeep> createRepeated() => new $pb.PbList<BarKeep>();
+  static BarKeep getDefault() => _defaultInstance ??= create()..freeze();
+  static BarKeep _defaultInstance;
+
+  int get aKeep => $_get(0, 0);
+  set aKeep(int v) {
+    $_setSignedInt32(0, v);
+  }
+
+  bool hasAKeep() => $_has(0);
+  void clearAKeep() => clearField(1);
+
+  int get bDrop => $_get(1, 0);
+  set bDrop(int v) {
+    $_setSignedInt32(1, v);
+  }
+
+  bool hasBDrop() => $_has(1);
+  void clearBDrop() => clearField(2);
+}
+
+class HasKeep extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = new $pb.BuilderInfo('HasKeep')
+    ..a<int>(1, 'aDrop', $pb.PbFieldType.O3)
+    ..hasRequiredFields = false;
+
+  HasKeep() : super();
+  HasKeep.fromBuffer(List<int> i,
+      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+      : super.fromBuffer(i, r);
+  HasKeep.fromJson(String i,
+      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+      : super.fromJson(i, r);
+  HasKeep clone() => new HasKeep()..mergeFromMessage(this);
+  HasKeep copyWith(void Function(HasKeep) updates) =>
+      super.copyWith((message) => updates(message as HasKeep));
+  $pb.BuilderInfo get info_ => _i;
+  static HasKeep create() => new HasKeep();
+  HasKeep createEmptyInstance() => create();
+  static $pb.PbList<HasKeep> createRepeated() => new $pb.PbList<HasKeep>();
+  static HasKeep getDefault() => _defaultInstance ??= create()..freeze();
+  static HasKeep _defaultInstance;
+
+  int get aDrop => $_get(0, 0);
+  set aDrop(int v) {
+    $_setSignedInt32(0, v);
+  }
+
+  bool hasADrop() => $_has(0);
+  void clearADrop() => clearField(1);
+}
+
+class ClearKeep extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = new $pb.BuilderInfo('ClearKeep')
+    ..a<int>(1, 'aDrop', $pb.PbFieldType.O3)
+    ..hasRequiredFields = false;
+
+  ClearKeep() : super();
+  ClearKeep.fromBuffer(List<int> i,
+      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+      : super.fromBuffer(i, r);
+  ClearKeep.fromJson(String i,
+      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+      : super.fromJson(i, r);
+  ClearKeep clone() => new ClearKeep()..mergeFromMessage(this);
+  ClearKeep copyWith(void Function(ClearKeep) updates) =>
+      super.copyWith((message) => updates(message as ClearKeep));
+  $pb.BuilderInfo get info_ => _i;
+  static ClearKeep create() => new ClearKeep();
+  ClearKeep createEmptyInstance() => create();
+  static $pb.PbList<ClearKeep> createRepeated() => new $pb.PbList<ClearKeep>();
+  static ClearKeep getDefault() => _defaultInstance ??= create()..freeze();
+  static ClearKeep _defaultInstance;
+
+  int get aDrop => $_get(0, 0);
+  set aDrop(int v) {
+    $_setSignedInt32(0, v);
+  }
+
+  bool hasADrop() => $_has(0);
+  void clearADrop() => clearField(1);
+}
+
+class ZopDrop extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = new $pb.BuilderInfo('ZopDrop')
+    ..a<int>(1, 'aDrop', $pb.PbFieldType.O3)
+    ..hasRequiredFields = false;
+
+  ZopDrop() : super();
+  ZopDrop.fromBuffer(List<int> i,
+      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+      : super.fromBuffer(i, r);
+  ZopDrop.fromJson(String i,
+      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+      : super.fromJson(i, r);
+  ZopDrop clone() => new ZopDrop()..mergeFromMessage(this);
+  ZopDrop copyWith(void Function(ZopDrop) updates) =>
+      super.copyWith((message) => updates(message as ZopDrop));
+  $pb.BuilderInfo get info_ => _i;
+  static ZopDrop create() => new ZopDrop();
+  ZopDrop createEmptyInstance() => create();
+  static $pb.PbList<ZopDrop> createRepeated() => new $pb.PbList<ZopDrop>();
+  static ZopDrop getDefault() => _defaultInstance ??= create()..freeze();
+  static ZopDrop _defaultInstance;
+
+  int get aDrop => $_get(0, 0);
+  set aDrop(int v) {
+    $_setSignedInt32(0, v);
+  }
+
+  bool hasADrop() => $_has(0);
+  void clearADrop() => clearField(1);
+}
+
+class MobDrop extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = new $pb.BuilderInfo('MobDrop')
+    ..a<int>(1, 'aDrop', $pb.PbFieldType.O3)
+    ..hasRequiredFields = false;
+
+  MobDrop() : super();
+  MobDrop.fromBuffer(List<int> i,
+      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+      : super.fromBuffer(i, r);
+  MobDrop.fromJson(String i,
+      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
+      : super.fromJson(i, r);
+  MobDrop clone() => new MobDrop()..mergeFromMessage(this);
+  MobDrop copyWith(void Function(MobDrop) updates) =>
+      super.copyWith((message) => updates(message as MobDrop));
+  $pb.BuilderInfo get info_ => _i;
+  static MobDrop create() => new MobDrop();
+  MobDrop createEmptyInstance() => create();
+  static $pb.PbList<MobDrop> createRepeated() => new $pb.PbList<MobDrop>();
+  static MobDrop getDefault() => _defaultInstance ??= create()..freeze();
+  static MobDrop _defaultInstance;
+
+  int get aDrop => $_get(0, 0);
+  set aDrop(int v) {
+    $_setSignedInt32(0, v);
+  }
+
+  bool hasADrop() => $_has(0);
+  void clearADrop() => clearField(1);
+}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/protos/foo.proto b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/protos/foo.proto
new file mode 100644
index 0000000..0a14433
--- /dev/null
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/protos/foo.proto
@@ -0,0 +1,41 @@
+// Copyright (c) 2019, 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.
+
+syntax = "proto3";
+
+message FooKeep {
+  BarKeep barKeep = 1;
+  BarKeep barDrop = 2;
+  map<string, BarKeep> mapKeep = 3;
+  map<string, ZopDrop> mapDrop = 4;
+  int32 aKeep = 5;
+  HasKeep hasKeep = 6;
+  ClearKeep clearKeep = 7;
+}
+
+message BarKeep {
+  int32 aKeep = 1;
+  int32 bDrop = 2;
+}
+
+message HasKeep {
+  int32 aDrop = 1;
+}
+
+message ClearKeep {
+  int32 aDrop = 1;
+}
+
+message ZopDrop {
+  int32 aDrop = 1;
+}
+
+message MobDrop {
+  int32 aDrop = 1;
+}
+
+message A {
+  B unused = 1;
+  C used = 2;
+}
\ No newline at end of file
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 51c708c..5724879 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -654,6 +654,27 @@
             get_target_outputs(":platform_strong_dill_linkable")
 }
 
+action("generate_abi_version_cc_file") {
+  inputs = [
+    "../../tools/utils.py",
+    "../../tools/VERSION",
+    "abi_version_in.cc",
+  ]
+  output = "$target_gen_dir/abi_version.cc"
+  outputs = [
+    output,
+  ]
+
+  script = "../../tools/make_version.py"
+  args = [
+    "--quiet",
+    "--output",
+    rebase_path(output, root_build_dir),
+    "--input",
+    rebase_path("abi_version_in.cc", root_build_dir),
+  ]
+}
+
 template("dart_executable") {
   extra_configs = []
   if (defined(invoker.extra_configs)) {
@@ -702,6 +723,7 @@
              "//third_party/boringssl",
              "//third_party/zlib",
              ":crashpad",
+             ":generate_abi_version_cc_file",
            ] + extra_deps
 
     defines = extra_defines
@@ -731,6 +753,7 @@
                 "snapshot_utils.h",
                 "vmservice_impl.cc",
                 "vmservice_impl.h",
+                "$target_gen_dir/abi_version.cc",
               ] + extra_sources
 
     if (is_win) {
diff --git a/runtime/bin/abi_version.h b/runtime/bin/abi_version.h
new file mode 100644
index 0000000..acd0cdf
--- /dev/null
+++ b/runtime/bin/abi_version.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, 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.
+
+#ifndef RUNTIME_BIN_ABI_VERSION_H_
+#define RUNTIME_BIN_ABI_VERSION_H_
+
+namespace dart {
+
+class AbiVersion {
+ public:
+  static int GetCurrent();
+  static int GetOldestSupported();
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_BIN_ABI_VERSION_H_
diff --git a/runtime/bin/abi_version_in.cc b/runtime/bin/abi_version_in.cc
new file mode 100644
index 0000000..ad737b2
--- /dev/null
+++ b/runtime/bin/abi_version_in.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, 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 "bin/abi_version.h"
+
+namespace dart {
+
+int AbiVersion::GetCurrent() {
+  return {{ABI_VERSION}};
+}
+
+int AbiVersion::GetOldestSupported() {
+  return {{OLDEST_SUPPORTED_ABI_VERSION}};
+}
+
+}  // namespace dart
diff --git a/runtime/bin/builtin_impl_sources.gni b/runtime/bin/builtin_impl_sources.gni
index d4c7489..f329f03 100644
--- a/runtime/bin/builtin_impl_sources.gni
+++ b/runtime/bin/builtin_impl_sources.gni
@@ -7,6 +7,7 @@
 # io_impl_sources.gypi.
 
 builtin_impl_sources = [
+  "abi_version.h",
   "crypto.cc",
   "crypto.h",
   "crypto_android.cc",
diff --git a/runtime/bin/dart_embedder_api_impl.cc b/runtime/bin/dart_embedder_api_impl.cc
index ba47d33..4700774 100644
--- a/runtime/bin/dart_embedder_api_impl.cc
+++ b/runtime/bin/dart_embedder_api_impl.cc
@@ -90,8 +90,6 @@
   if (!bin::VmService::Setup(config.ip, config.port, config.dev_mode,
                              /*trace_loading=*/false, config.deterministic)) {
     *error = strdup(bin::VmService::GetErrorMessage());
-    Dart_ExitScope();
-    Dart_ShutdownIsolate();
     return nullptr;
   }
 
diff --git a/runtime/bin/ffi_test_functions.cc b/runtime/bin/ffi_test_functions.cc
index 5d95e49..248020d 100644
--- a/runtime/bin/ffi_test_functions.cc
+++ b/runtime/bin/ffi_test_functions.cc
@@ -4,13 +4,17 @@
 
 // This file contains test functions for the dart:ffi test cases.
 
-// The tests which use this don't run on Windows yet.
-#if !defined(_WIN32)
-
 #include <stddef.h>
 #include <stdlib.h>
 #include <sys/types.h>
+
+#include "platform/globals.h"
+#if defined(HOST_OS_WINDOWS)
+#include <psapi.h>
+#else
 #include <unistd.h>
+#endif
+
 #include <iostream>
 #include <limits>
 
@@ -29,6 +33,11 @@
   return retval;
 }
 
+// Test 32-bit (int32_t) -> 64-bit (Dart int) sign extension and truncation.
+DART_EXPORT int32_t TestExtension() {
+  return 1UL << 31;
+}
+
 // Performs some computation on various sized signed ints.
 // Used for testing value ranges for signed ints.
 DART_EXPORT int64_t IntComputation(int8_t a, int16_t b, int32_t c, int64_t d) {
@@ -403,9 +412,15 @@
 }
 
 DART_EXPORT void* SmallPointer() {
-  return reinterpret_cast<void*>(-0x80000000L);
+  intptr_t value = 0x80000000;
+  return reinterpret_cast<void*>(-value);
 }
 
+DART_EXPORT void* LargePointer() {
+  return reinterpret_cast<void*>(-0x8000000000000000L);
+}
+
+#if !defined(_WIN32)
 DART_EXPORT int RedirectStderr() {
   char filename[256];
   snprintf(filename, sizeof(filename), "/tmp/captured_stderr_%d", getpid());
@@ -413,7 +428,6 @@
   printf("Got file %s\n", filename);
   return getpid();
 }
+#endif
 
 }  // namespace dart
-
-#endif
diff --git a/runtime/bin/file_fuchsia.cc b/runtime/bin/file_fuchsia.cc
index 9ee69ea..9b480d5 100644
--- a/runtime/bin/file_fuchsia.cc
+++ b/runtime/bin/file_fuchsia.cc
@@ -590,11 +590,18 @@
   return "/";
 }
 
+static int fd_is_valid(int fd) {
+    return NO_RETRY_EXPECTED(fcntl(fd, F_GETFD)) != -1 || errno != EBADF;
+}
+
 File::StdioHandleType File::GetStdioHandleType(int fd) {
   struct stat buf;
   int result = TEMP_FAILURE_RETRY(fstat(fd, &buf));
   if (result == -1) {
-    return kOther;
+    // fstat() on fds 0, 1, 2 on Fuchsia return -1 with errno ENOTSUP,
+    // but if they are opened, then we can read/write them, so pretend they
+    // are kPipe.
+    return ((errno == ENOTSUP) && fd_is_valid(fd)) ? kPipe : kOther;
   }
   if (S_ISCHR(buf.st_mode)) {
     return kTerminal;
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 8dfc9202..6632130 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -424,6 +424,7 @@
     intptr_t size = 0;
     ReadFile(load_compilation_trace_filename, &buffer, &size);
     Dart_Handle result = Dart_LoadCompilationTrace(buffer, size);
+    free(buffer);
     CHECK_RESULT(result);
   }
 
@@ -433,6 +434,7 @@
     intptr_t size = 0;
     ReadFile(load_type_feedback_filename, &buffer, &size);
     Dart_Handle result = Dart_LoadTypeFeedback(buffer, size);
+    free(buffer);
     CHECK_RESULT(result);
   }
 }
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 2d7ea6f..f572e20 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -883,11 +883,20 @@
       LoadBytecode();
     }
 
+    if (Options::load_compilation_trace_filename() != NULL) {
+      uint8_t* buffer = NULL;
+      intptr_t size = 0;
+      ReadFile(Options::load_compilation_trace_filename(), &buffer, &size);
+      result = Dart_LoadCompilationTrace(buffer, size);
+      free(buffer);
+      CHECK_RESULT(result);
+    }
     if (Options::load_type_feedback_filename() != NULL) {
       uint8_t* buffer = NULL;
       intptr_t size = 0;
       ReadFile(Options::load_type_feedback_filename(), &buffer, &size);
       result = Dart_LoadTypeFeedback(buffer, size);
+      free(buffer);
       CHECK_RESULT(result);
     }
 
@@ -926,6 +935,13 @@
     }
     CHECK_RESULT(result);
 
+    if (Options::save_compilation_trace_filename() != NULL) {
+      uint8_t* buffer = NULL;
+      intptr_t size = 0;
+      result = Dart_SaveCompilationTrace(&buffer, &size);
+      CHECK_RESULT(result);
+      WriteFile(Options::save_compilation_trace_filename(), buffer, size);
+    }
     if (Options::save_type_feedback_filename() != NULL) {
       uint8_t* buffer = NULL;
       intptr_t size = 0;
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index a7181f5..d68bfaa 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -8,6 +8,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "bin/abi_version.h"
 #include "bin/log.h"
 #include "bin/options.h"
 #include "bin/platform.h"
@@ -324,6 +325,32 @@
   return true;
 }
 
+int Options::target_abi_version_ = AbiVersion::GetCurrent();
+bool Options::ProcessAbiVersionOption(const char* arg,
+                                      CommandLineOptions* vm_options) {
+  const char* value = OptionProcessor::ProcessOption(arg, "--use_abi_version=");
+  if (value == NULL) {
+    return false;
+  }
+  int ver = 0;
+  for (int i = 0; value[i]; ++i) {
+    if (value[i] >= '0' && value[i] <= '9') {
+      ver = (ver * 10) + value[i] - '0';
+    } else {
+      Log::PrintErr("--use_abi_version must be an int\n");
+      return false;
+    }
+  }
+  if (ver < AbiVersion::GetOldestSupported() ||
+      ver > AbiVersion::GetCurrent()) {
+    Log::PrintErr("--use_abi_version must be between %d and %d inclusive\n",
+                  AbiVersion::GetOldestSupported(), AbiVersion::GetCurrent());
+    return false;
+  }
+  target_abi_version_ = ver;
+  return true;
+}
+
 static bool checked_set = false;
 
 int Options::ParseArguments(int argc,
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 2b668ac..e290696 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -24,6 +24,8 @@
   V(depfile, depfile)                                                          \
   V(depfile_output_filename, depfile_output_filename)                          \
   V(shared_blobs, shared_blobs_filename)                                       \
+  V(save_compilation_trace, save_compilation_trace_filename)                   \
+  V(load_compilation_trace, load_compilation_trace_filename)                   \
   V(save_type_feedback, save_type_feedback_filename)                           \
   V(load_type_feedback, load_type_feedback_filename)                           \
   V(root_certs_file, root_certs_file)                                          \
@@ -60,7 +62,8 @@
 #define CB_OPTIONS_LIST(V)                                                     \
   V(ProcessEnvironmentOption)                                                  \
   V(ProcessEnableVmServiceOption)                                              \
-  V(ProcessObserveOption)
+  V(ProcessObserveOption)                                                      \
+  V(ProcessAbiVersionOption)
 
 // This enum must match the strings in kSnapshotKindNames in main_options.cc.
 enum SnapshotKind {
@@ -113,6 +116,8 @@
   static const char* vm_service_server_ip() { return vm_service_server_ip_; }
   static int vm_service_server_port() { return vm_service_server_port_; }
 
+  static int target_abi_version() { return target_abi_version_; }
+
 #if !defined(DART_PRECOMPILED_RUNTIME)
   static DFE* dfe() { return dfe_; }
   static void set_dfe(DFE* dfe) { dfe_ = dfe; }
@@ -157,6 +162,8 @@
                                     int default_port,
                                     const char* default_ip);
 
+  static int target_abi_version_;
+
 #define OPTION_FRIEND(flag, variable) friend class OptionProcessor_##flag;
   STRING_OPTIONS_LIST(OPTION_FRIEND)
   BOOL_OPTIONS_LIST(OPTION_FRIEND)
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index 98ab964..93c7f6c 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -546,6 +546,9 @@
               !Directory::SetCurrent(namespc_, working_directory_)) {
             ReportChildError();
           }
+          if (program_environment_ != NULL) {
+            environ = program_environment_;
+          }
 
           // Report the final PID and do the exec.
           ReportPid(getpid());  // getpid cannot fail.
diff --git a/runtime/include/dart_tools_api.h b/runtime/include/dart_tools_api.h
index 402e01d..03b38aa 100644
--- a/runtime/include/dart_tools_api.h
+++ b/runtime/include/dart_tools_api.h
@@ -360,13 +360,17 @@
 /**
  * Add a timeline event to the embedder stream.
  *
- * \param label The name of the evnet.
+ * \param label The name of the event. Its lifetime must extend at least until
+ *     Dart_Cleanup.
  * \param timestamp0 The first timestamp of the event.
  * \param timestamp1_or_async_id The second timestamp of the event or
  *     the async id.
  * \param argument_count The number of argument names and values.
- * \param argument_names An array of names of the arguments.
- * \param argument_values An array of values of the arguments.
+ * \param argument_names An array of names of the arguments. The lifetime of the
+ *     names must extend at least until Dart_Cleanup. The array may be reclaimed
+ *     when this call returns.
+ * \param argument_values An array of values of the arguments. The values and
+ *     the array may be reclaimed when this call returns.
  */
 DART_EXPORT void Dart_TimelineEvent(const char* label,
                                     int64_t timestamp0,
diff --git a/runtime/lib/bigint_patch.dart b/runtime/lib/bigint_patch.dart
index be23866..2046284 100644
--- a/runtime/lib/bigint_patch.dart
+++ b/runtime/lib/bigint_patch.dart
@@ -2312,7 +2312,9 @@
     var resultBits = new Uint8List(8);
 
     var length = _digitBits * (_used - 1) + _digits[_used - 1].bitLength;
-    if (length - 53 > maxDoubleExponent) return double.infinity;
+    if (length > maxDoubleExponent + 53) {
+      return _isNegative ? double.negativeInfinity : double.infinity;
+    }
 
     // The most significant bit is for the sign.
     if (_isNegative) resultBits[7] = 0x80;
diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc
index 4186a1e..6e1903b 100644
--- a/runtime/lib/ffi.cc
+++ b/runtime/lib/ffi.cc
@@ -6,7 +6,6 @@
 #include "include/dart_api.h"
 #include "vm/bootstrap_natives.h"
 #include "vm/class_finalizer.h"
-#include "vm/class_id.h"
 #include "vm/compiler/assembler/assembler.h"
 #include "vm/exceptions.h"
 #include "vm/log.h"
@@ -227,10 +226,10 @@
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, argCount, arguments->NativeArgAt(0));
   int64_t count = argCount.AsInt64Value();
   classid_t type_cid = type_arg.type_class_id();
-  int64_t max_count = INTPTR_MAX / ffi::ElementSizeInBytes(type_cid);
+  int64_t max_count = INTPTR_MAX / compiler::ffi::ElementSizeInBytes(type_cid);
   CheckRange(argCount, 1, max_count, "count");
 
-  size_t size = ffi::ElementSizeInBytes(type_cid) * count;
+  size_t size = compiler::ffi::ElementSizeInBytes(type_cid) * count;
   intptr_t memory = reinterpret_cast<intptr_t>(malloc(size));
   if (memory == 0) {
     const String& error = String::Handle(String::NewFormatted(
@@ -268,9 +267,9 @@
 
   classid_t class_id = pointer_type_arg.type_class_id();
   Integer& address = Integer::Handle(zone, pointer.GetCMemoryAddress());
-  address =
-      Integer::New(address.AsInt64Value() +
-                   index.AsInt64Value() * ffi::ElementSizeInBytes(class_id));
+  address = Integer::New(address.AsInt64Value() +
+                         index.AsInt64Value() *
+                             compiler::ffi::ElementSizeInBytes(class_id));
   RawPointer* result = Pointer::New(pointer_type_arg, address);
   return result;
 }
@@ -470,54 +469,7 @@
   CheckSized(type_arg);
 
   classid_t type_cid = type_arg.type_class_id();
-  return Smi::New(ffi::ElementSizeInBytes(type_cid));
-}
-
-// Generates assembly to trampoline from Dart into C++.
-//
-// Attaches assembly code to the function with the folling features:
-// - unboxes arguments
-// - puts the arguments on the c stack
-// - invokes the c function
-// - reads the the result
-// - boxes the result and returns it.
-//
-// It inspects the signature to know what to box/unbox
-// Parameter `function` has the Dart types in its signature
-// Parameter `c_signature` has the C++ types in its signature
-static RawCode* TrampolineCode(const Function& function,
-                               const Function& c_signature) {
-#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
-  // Currently we generate the trampoline when calling asFunction(), this means
-  // the ffi cannot be used in AOT.
-  // In order make it work in AOT we need to:
-  // - collect all asFunction signatures ahead of time
-  // - generate trampolines for those
-  // - store these in the object store
-  // - and read these from the object store when calling asFunction()
-  // https://github.com/dart-lang/sdk/issues/35765
-  UNREACHABLE();
-#elif !defined(TARGET_ARCH_X64)
-  // https://github.com/dart-lang/sdk/issues/35774
-  UNREACHABLE();
-#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
-  // https://github.com/dart-lang/sdk/issues/35760 Arm32 && Android
-  // https://github.com/dart-lang/sdk/issues/35771 Windows
-  // https://github.com/dart-lang/sdk/issues/35772 Arm64
-  // https://github.com/dart-lang/sdk/issues/35773 DBC
-  UNREACHABLE();
-#else
-  extern void GenerateFfiTrampoline(Assembler * assembler,
-                                    const Function& signature);
-  ObjectPoolBuilder object_pool_builder;
-  Assembler assembler(&object_pool_builder);
-  GenerateFfiTrampoline(&assembler, c_signature);
-  const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
-      function, nullptr, &assembler, Code::PoolAttachment::kAttachPool));
-  code.set_exception_handlers(
-      ExceptionHandlers::Handle(ExceptionHandlers::New(0)));
-  return code.raw();
-#endif
+  return Smi::New(compiler::ffi::ElementSizeInBytes(type_cid));
 }
 
 // TODO(dacoharkes): Cache the trampolines.
@@ -526,25 +478,37 @@
                                        const Function& c_signature) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  const String& name =
+  String& name =
       String::ZoneHandle(Symbols::New(Thread::Current(), "FfiTrampoline"));
   const Library& lib = Library::Handle(Library::FfiLibrary());
   const Class& owner_class = Class::Handle(lib.toplevel_class());
-  Function& function = Function::ZoneHandle(
-      zone, Function::New(name, RawFunction::kFfiTrampoline,
-                          true,   // is_static
-                          false,  // is_const
-                          false,  // is_abstract
-                          false,  // is_external
-                          true,   // is_native
-                          owner_class, TokenPosition::kMinSource));
-
+  Function& function =
+      Function::Handle(zone, Function::New(name, RawFunction::kFfiTrampoline,
+                                           /*is_static=*/true,
+                                           /*is_const=*/false,
+                                           /*is_abstract=*/false,
+                                           /*is_external=*/false,
+                                           /*is_native=*/false, owner_class,
+                                           TokenPosition::kMinSource));
+  function.set_is_debuggable(false);
   function.set_num_fixed_parameters(dart_signature.num_fixed_parameters());
   function.set_result_type(AbstractType::Handle(dart_signature.result_type()));
   function.set_parameter_types(Array::Handle(dart_signature.parameter_types()));
 
-  const Code& code = Code::Handle(TrampolineCode(function, c_signature));
-  function.AttachCode(code);
+  // The signature function won't have any names for the parameters. We need to
+  // assign unique names for scope building and error messages.
+  const intptr_t num_params = dart_signature.num_fixed_parameters();
+  const Array& parameter_names = Array::Handle(Array::New(num_params));
+  for (intptr_t i = 0; i < num_params; ++i) {
+    if (i == 0) {
+      name = Symbols::ClosureParameter().raw();
+    } else {
+      name = Symbols::NewFormatted(thread, ":ffiParam%" Pd, i);
+    }
+    parameter_names.SetAt(i, name);
+  }
+  function.set_parameter_names(parameter_names);
+  function.SetFfiCSignature(c_signature);
 
   return function.raw();
 }
@@ -588,9 +552,9 @@
 #elif !defined(TARGET_ARCH_X64)
   // https://github.com/dart-lang/sdk/issues/35774
   UNREACHABLE();
-#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
+#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS) &&                \
+    !defined(TARGET_OS_WINDOWS)
   // https://github.com/dart-lang/sdk/issues/35760 Arm32 && Android
-  // https://github.com/dart-lang/sdk/issues/35771 Windows
   // https://github.com/dart-lang/sdk/issues/35772 Arm64
   // https://github.com/dart-lang/sdk/issues/35773 DBC
   UNREACHABLE();
diff --git a/runtime/lib/ffi_dynamic_library.cc b/runtime/lib/ffi_dynamic_library.cc
index 3af92da..af4a52e 100644
--- a/runtime/lib/ffi_dynamic_library.cc
+++ b/runtime/lib/ffi_dynamic_library.cc
@@ -3,12 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #if !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
-// TODO(dacoharkes): implement dynamic libraries for other targets.
-// see
-// - runtime/vm/native_symbol.h
-// - runtime/vm/native_symbol_linux.cc
-// - runtime/bin/extensions.h (but we cannot import from bin)
+// TODO(dacoharkes): Implement dynamic libraries for other targets & merge the
+// implementation with:
+// - runtime/bin/extensions.h
 // - runtime/bin/extensions_linux.cc
+// TODO(dacoharkes): Make the code from bin available in a manner similar to
+// runtime/vm/dart.h Dart_FileReadCallback.
 #else
 #include <dlfcn.h>
 #endif
@@ -19,29 +19,85 @@
 
 namespace dart {
 
-DEFINE_NATIVE_ENTRY(Ffi_dl_open, 0, 1) {
-#if !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
-  UNREACHABLE();
-#else
-  GET_NON_NULL_NATIVE_ARGUMENT(String, lib_path, arguments->NativeArgAt(0));
-
-  dlerror();  // Clear any errors.
-  void* handle = dlopen(lib_path.ToCString(), RTLD_LAZY);
+static void* LoadExtensionLibrary(const char* library_file) {
+#if defined(TARGET_OS_LINUX) || defined(TARGET_OS_MACOS)
+  void* handle = dlopen(library_file, RTLD_LAZY);
   if (handle == nullptr) {
     char* error = dlerror();
     const String& msg = String::Handle(
-        String::NewFormatted("Failed to load dynamic library(%s)", error));
+        String::NewFormatted("Failed to load dynamic library (%s)", error));
     Exceptions::ThrowArgumentError(msg);
   }
 
+  return handle;
+#elif defined(TARGET_OS_WINDOWS)
+  SetLastError(0);  // Clear any errors.
+
+  // Convert to wchar_t string.
+  const int name_len =
+      MultiByteToWideChar(CP_UTF8, 0, library_file, -1, NULL, 0);
+  wchar_t* name = new wchar_t[name_len];
+  MultiByteToWideChar(CP_UTF8, 0, library_file, -1, name, name_len);
+
+  void* ext = LoadLibraryW(name);
+  delete[] name;
+
+  if (ext == nullptr) {
+    const int error = GetLastError();
+    const String& msg = String::Handle(
+        String::NewFormatted("Failed to load dynamic library (%i)", error));
+    Exceptions::ThrowArgumentError(msg);
+  }
+
+  return ext;
+#else
+  const Array& args = Array::Handle(Array::New(1));
+  args.SetAt(0,
+             String::Handle(String::New(
+                 "The dart:ffi library is not available on this platform.")));
+  Exceptions::ThrowByType(Exceptions::kUnsupported, args);
+#endif
+}
+
+DEFINE_NATIVE_ENTRY(Ffi_dl_open, 0, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(String, lib_path, arguments->NativeArgAt(0));
+
+  void* handle = LoadExtensionLibrary(lib_path.ToCString());
+
   return DynamicLibrary::New(handle);
+}
+
+static void* ResolveSymbol(void* handle, const char* symbol) {
+#if defined(TARGET_OS_LINUX) || defined(TARGET_OS_MACOS)
+  dlerror();  // Clear any errors.
+  void* pointer = dlsym(handle, symbol);
+  if (pointer == nullptr) {
+    char* error = dlerror();
+    const String& msg = String::Handle(
+        String::NewFormatted("Failed to lookup symbol (%s)", error));
+    Exceptions::ThrowArgumentError(msg);
+  }
+  return pointer;
+#elif defined(TARGET_OS_WINDOWS)
+  SetLastError(0);
+  void* pointer = GetProcAddress(reinterpret_cast<HMODULE>(handle), symbol);
+  if (pointer == nullptr) {
+    const int error = GetLastError();
+    const String& msg = String::Handle(
+        String::NewFormatted("Failed to lookup symbol (%i)", error));
+    Exceptions::ThrowArgumentError(msg);
+  }
+  return pointer;
+#else
+  const Array& args = Array::Handle(Array::New(1));
+  args.SetAt(0,
+             String::Handle(String::New(
+                 "The dart:ffi library is not available on this platform.")));
+  Exceptions::ThrowByType(Exceptions::kUnsupported, args);
 #endif
 }
 
 DEFINE_NATIVE_ENTRY(Ffi_dl_lookup, 1, 2) {
-#if !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
-  UNREACHABLE();
-#else
   GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
 
   GET_NON_NULL_NATIVE_ARGUMENT(DynamicLibrary, dlib, arguments->NativeArgAt(0));
@@ -50,22 +106,14 @@
 
   void* handle = dlib.GetHandle();
 
-  dlerror();  // Clear any errors.
-  intptr_t pointer =
-      reinterpret_cast<intptr_t>(dlsym(handle, argSymbolName.ToCString()));
-  char* error;
-  if ((error = dlerror()) != NULL) {
-    const String& msg = String::Handle(
-        String::NewFormatted("Failed to lookup symbol (%s)", error));
-    Exceptions::ThrowArgumentError(msg);
-  }
+  const intptr_t pointer = reinterpret_cast<intptr_t>(
+      ResolveSymbol(handle, argSymbolName.ToCString()));
 
-  // TODO(dacoharkes): should this return NULL if addres is 0?
+  // TODO(dacoharkes): should this return Object::null() if address is 0?
   // https://github.com/dart-lang/sdk/issues/35756
   RawPointer* result =
       Pointer::New(type_arg, Integer::Handle(zone, Integer::New(pointer)));
   return result;
-#endif
 }
 
 DEFINE_NATIVE_ENTRY(Ffi_dl_getHandle, 0, 1) {
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index 5592f20..5402def 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -328,15 +328,15 @@
       Exceptions::ThrowByType(Exceptions::kArgument, args);
     }
     return OneByteString::New(array, start, length, space);
-  } else if (RawObject::IsTypedDataViewClassId(list.GetClassId())) {
-    const Instance& view = Instance::Cast(list);
-    if (end > Smi::Value(TypedDataView::Length(view))) {
+  } else if (list.IsTypedDataView()) {
+    const auto& view = TypedDataView::Cast(list);
+    if (end > Smi::Value(view.length())) {
       const Array& args = Array::Handle(Array::New(1));
       args.SetAt(0, end_obj);
       Exceptions::ThrowByType(Exceptions::kArgument, args);
     }
-    const Instance& data_obj = Instance::Handle(TypedDataView::Data(view));
-    intptr_t data_offset = Smi::Value(TypedDataView::OffsetInBytes(view));
+    const Instance& data_obj = Instance::Handle(view.typed_data());
+    intptr_t data_offset = Smi::Value(view.offset_in_bytes());
     if (data_obj.IsTypedData()) {
       const TypedData& array = TypedData::Cast(data_obj);
       return OneByteString::New(array, data_offset + start, length, space);
@@ -422,16 +422,16 @@
     }
     return TwoByteString::New(array, start * sizeof(uint16_t), length, space);
   } else if (RawObject::IsTypedDataViewClassId(list.GetClassId())) {
+    const auto& view = TypedDataView::Cast(list);
     const intptr_t cid = list.GetClassId();
     if (cid != kTypedDataUint16ArrayViewCid) {
       Exceptions::ThrowArgumentError(list);
     }
-    if (end > Smi::Value(TypedDataView::Length(list))) {
+    if (end > Smi::Value(view.length())) {
       Exceptions::ThrowArgumentError(end_obj);
     }
-    const Instance& data_obj =
-        Instance::Handle(zone, TypedDataView::Data(list));
-    intptr_t data_offset = Smi::Value(TypedDataView::OffsetInBytes(list));
+    const auto& data_obj = Instance::Handle(zone, view.typed_data());
+    const intptr_t data_offset = Smi::Value(view.offset_in_bytes());
     if (data_obj.IsTypedData()) {
       const TypedData& array = TypedData::Cast(data_obj);
       return TwoByteString::New(array, data_offset + start * sizeof(uint16_t),
diff --git a/runtime/lib/typed_data.cc b/runtime/lib/typed_data.cc
index 4a373fc..1c55247 100644
--- a/runtime/lib/typed_data.cc
+++ b/runtime/lib/typed_data.cc
@@ -28,6 +28,15 @@
   }
 }
 
+static void AlignmentCheck(intptr_t offset_in_bytes, intptr_t element_size) {
+  if ((offset_in_bytes % element_size) != 0) {
+    const auto& error = String::Handle(String::NewFormatted(
+        "Offset in bytes (%" Pd ") must be a multiple of %" Pd "",
+        offset_in_bytes, element_size));
+    Exceptions::ThrowArgumentError(error);
+  }
+}
+
 // Checks to see if a length will not result in an OOM error.
 static void LengthCheck(intptr_t len, intptr_t max) {
   if (len < 0 || len > max) {
@@ -53,6 +62,27 @@
   return Integer::null();
 }
 
+DEFINE_NATIVE_ENTRY(TypedDataView_offsetInBytes, 0, 1) {
+  // "this" is either a _*ArrayView class or _ByteDataView.
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0));
+  ASSERT(instance.IsTypedDataView());
+  return TypedDataView::Cast(instance).offset_in_bytes();
+}
+
+DEFINE_NATIVE_ENTRY(TypedDataView_length, 0, 1) {
+  // "this" is either a _*ArrayView class or _ByteDataView.
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0));
+  ASSERT(instance.IsTypedDataView());
+  return TypedDataView::Cast(instance).length();
+}
+
+DEFINE_NATIVE_ENTRY(TypedDataView_typedData, 0, 1) {
+  // "this" is either a _*ArrayView class or _ByteDataView.
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0));
+  ASSERT(instance.IsTypedDataView());
+  return TypedDataView::Cast(instance).typed_data();
+}
+
 template <typename DstType, typename SrcType>
 static RawBool* CopyData(const Instance& dst,
                          const Instance& src,
@@ -160,9 +190,9 @@
 #define TYPED_DATA_NEW(name)                                                   \
   DEFINE_NATIVE_ENTRY(TypedData_##name##_new, 0, 2) {                          \
     GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(1));      \
-    intptr_t cid = kTypedData##name##Cid;                                      \
-    intptr_t len = length.Value();                                             \
-    intptr_t max = TypedData::MaxElements(cid);                                \
+    const intptr_t cid = kTypedData##name##Cid;                                \
+    const intptr_t len = length.Value();                                       \
+    const intptr_t max = TypedData::MaxElements(cid);                          \
     LengthCheck(len, max);                                                     \
     return TypedData::New(cid, len);                                           \
   }
@@ -170,6 +200,35 @@
 #define TYPED_DATA_NEW_NATIVE(name) TYPED_DATA_NEW(name)
 
 CLASS_LIST_TYPED_DATA(TYPED_DATA_NEW_NATIVE)
+#undef TYPED_DATA_NEW_NATIVE
+#undef TYPED_DATA_NEW
+
+#define TYPED_DATA_VIEW_NEW(native_name, cid_name)                             \
+  DEFINE_NATIVE_ENTRY(native_name, 0, 4) {                                     \
+    GET_NON_NULL_NATIVE_ARGUMENT(Instance, typed_data,                         \
+                                 arguments->NativeArgAt(1));                   \
+    GET_NON_NULL_NATIVE_ARGUMENT(Smi, offset, arguments->NativeArgAt(2));      \
+    GET_NON_NULL_NATIVE_ARGUMENT(Smi, len, arguments->NativeArgAt(3));         \
+    const intptr_t backing_length =                                            \
+        typed_data.IsTypedData()                                               \
+            ? TypedData::Cast(typed_data).LengthInBytes()                      \
+            : ExternalTypedData::Cast(typed_data).LengthInBytes();             \
+    const intptr_t cid = cid_name;                                             \
+    const intptr_t offset_in_bytes = offset.Value();                           \
+    const intptr_t length = len.Value();                                       \
+    const intptr_t element_size = TypedDataView::ElementSizeInBytes(cid);      \
+    AlignmentCheck(offset_in_bytes, element_size);                             \
+    LengthCheck(offset_in_bytes + length * element_size, backing_length);      \
+    return TypedDataView::New(cid, typed_data, offset_in_bytes, length);       \
+  }
+
+#define TYPED_DATA_NEW_NATIVE(name)                                            \
+  TYPED_DATA_VIEW_NEW(TypedDataView_##name##View_new, kTypedData##name##ViewCid)
+
+CLASS_LIST_TYPED_DATA(TYPED_DATA_NEW_NATIVE)
+TYPED_DATA_VIEW_NEW(TypedDataView_ByteDataView_new, kByteDataViewCid)
+#undef TYPED_DATA_NEW_NATIVE
+#undef TYPED_DATA_VIEW_NEW
 
 #define TYPED_DATA_GETTER(getter, object, ctor, access_size)                   \
   DEFINE_NATIVE_ENTRY(TypedData_##getter, 0, 2) {                              \
diff --git a/runtime/lib/typed_data_patch.dart b/runtime/lib/typed_data_patch.dart
index 56d4fe3..7af2181 100644
--- a/runtime/lib/typed_data_patch.dart
+++ b/runtime/lib/typed_data_patch.dart
@@ -1914,7 +1914,7 @@
     length ??= (this.lengthInBytes - offsetInBytes) ~/ Int8List.bytesPerElement;
     _rangeCheck(
         this.lengthInBytes, offsetInBytes, length * Int8List.bytesPerElement);
-    return new _Int8ArrayView(this, offsetInBytes, length);
+    return new _Int8ArrayView(this._data, offsetInBytes, length);
   }
 
   Uint8List asUint8List([int offsetInBytes = 0, int length]) {
@@ -1922,7 +1922,7 @@
         (this.lengthInBytes - offsetInBytes) ~/ Uint8List.bytesPerElement;
     _rangeCheck(
         this.lengthInBytes, offsetInBytes, length * Uint8List.bytesPerElement);
-    return new _Uint8ArrayView(this, offsetInBytes, length);
+    return new _Uint8ArrayView(this._data, offsetInBytes, length);
   }
 
   Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int length]) {
@@ -1930,7 +1930,7 @@
         Uint8ClampedList.bytesPerElement;
     _rangeCheck(this.lengthInBytes, offsetInBytes,
         length * Uint8ClampedList.bytesPerElement);
-    return new _Uint8ClampedArrayView(this, offsetInBytes, length);
+    return new _Uint8ClampedArrayView(this._data, offsetInBytes, length);
   }
 
   Int16List asInt16List([int offsetInBytes = 0, int length]) {
@@ -1938,7 +1938,8 @@
         (this.lengthInBytes - offsetInBytes) ~/ Int16List.bytesPerElement;
     _rangeCheck(
         this.lengthInBytes, offsetInBytes, length * Int16List.bytesPerElement);
-    return new _Int16ArrayView(this, offsetInBytes, length);
+    _offsetAlignmentCheck(offsetInBytes, Int16List.bytesPerElement);
+    return new _Int16ArrayView(this._data, offsetInBytes, length);
   }
 
   Uint16List asUint16List([int offsetInBytes = 0, int length]) {
@@ -1946,7 +1947,8 @@
         (this.lengthInBytes - offsetInBytes) ~/ Uint16List.bytesPerElement;
     _rangeCheck(
         this.lengthInBytes, offsetInBytes, length * Uint16List.bytesPerElement);
-    return new _Uint16ArrayView(this, offsetInBytes, length);
+    _offsetAlignmentCheck(offsetInBytes, Uint16List.bytesPerElement);
+    return new _Uint16ArrayView(this._data, offsetInBytes, length);
   }
 
   Int32List asInt32List([int offsetInBytes = 0, int length]) {
@@ -1954,7 +1956,8 @@
         (this.lengthInBytes - offsetInBytes) ~/ Int32List.bytesPerElement;
     _rangeCheck(
         this.lengthInBytes, offsetInBytes, length * Int32List.bytesPerElement);
-    return new _Int32ArrayView(this, offsetInBytes, length);
+    _offsetAlignmentCheck(offsetInBytes, Int32List.bytesPerElement);
+    return new _Int32ArrayView(this._data, offsetInBytes, length);
   }
 
   Uint32List asUint32List([int offsetInBytes = 0, int length]) {
@@ -1962,7 +1965,8 @@
         (this.lengthInBytes - offsetInBytes) ~/ Uint32List.bytesPerElement;
     _rangeCheck(
         this.lengthInBytes, offsetInBytes, length * Uint32List.bytesPerElement);
-    return new _Uint32ArrayView(this, offsetInBytes, length);
+    _offsetAlignmentCheck(offsetInBytes, Uint32List.bytesPerElement);
+    return new _Uint32ArrayView(this._data, offsetInBytes, length);
   }
 
   Int64List asInt64List([int offsetInBytes = 0, int length]) {
@@ -1970,7 +1974,8 @@
         (this.lengthInBytes - offsetInBytes) ~/ Int64List.bytesPerElement;
     _rangeCheck(
         this.lengthInBytes, offsetInBytes, length * Int64List.bytesPerElement);
-    return new _Int64ArrayView(this, offsetInBytes, length);
+    _offsetAlignmentCheck(offsetInBytes, Int64List.bytesPerElement);
+    return new _Int64ArrayView(this._data, offsetInBytes, length);
   }
 
   Uint64List asUint64List([int offsetInBytes = 0, int length]) {
@@ -1978,7 +1983,8 @@
         (this.lengthInBytes - offsetInBytes) ~/ Uint64List.bytesPerElement;
     _rangeCheck(
         this.lengthInBytes, offsetInBytes, length * Uint64List.bytesPerElement);
-    return new _Uint64ArrayView(this, offsetInBytes, length);
+    _offsetAlignmentCheck(offsetInBytes, Uint64List.bytesPerElement);
+    return new _Uint64ArrayView(this._data, offsetInBytes, length);
   }
 
   Float32List asFloat32List([int offsetInBytes = 0, int length]) {
@@ -1986,7 +1992,8 @@
         (this.lengthInBytes - offsetInBytes) ~/ Float32List.bytesPerElement;
     _rangeCheck(this.lengthInBytes, offsetInBytes,
         length * Float32List.bytesPerElement);
-    return new _Float32ArrayView(this, offsetInBytes, length);
+    _offsetAlignmentCheck(offsetInBytes, Float32List.bytesPerElement);
+    return new _Float32ArrayView(this._data, offsetInBytes, length);
   }
 
   Float64List asFloat64List([int offsetInBytes = 0, int length]) {
@@ -1994,7 +2001,8 @@
         (this.lengthInBytes - offsetInBytes) ~/ Float64List.bytesPerElement;
     _rangeCheck(this.lengthInBytes, offsetInBytes,
         length * Float64List.bytesPerElement);
-    return new _Float64ArrayView(this, offsetInBytes, length);
+    _offsetAlignmentCheck(offsetInBytes, Float64List.bytesPerElement);
+    return new _Float64ArrayView(this._data, offsetInBytes, length);
   }
 
   Float32x4List asFloat32x4List([int offsetInBytes = 0, int length]) {
@@ -2002,7 +2010,8 @@
         (this.lengthInBytes - offsetInBytes) ~/ Float32x4List.bytesPerElement;
     _rangeCheck(this.lengthInBytes, offsetInBytes,
         length * Float32x4List.bytesPerElement);
-    return new _Float32x4ArrayView(this, offsetInBytes, length);
+    _offsetAlignmentCheck(offsetInBytes, Float32x4List.bytesPerElement);
+    return new _Float32x4ArrayView(this._data, offsetInBytes, length);
   }
 
   Int32x4List asInt32x4List([int offsetInBytes = 0, int length]) {
@@ -2010,7 +2019,8 @@
         (this.lengthInBytes - offsetInBytes) ~/ Int32x4List.bytesPerElement;
     _rangeCheck(this.lengthInBytes, offsetInBytes,
         length * Int32x4List.bytesPerElement);
-    return new _Int32x4ArrayView(this, offsetInBytes, length);
+    _offsetAlignmentCheck(offsetInBytes, Int32x4List.bytesPerElement);
+    return new _Int32x4ArrayView(this._data, offsetInBytes, length);
   }
 
   Float64x2List asFloat64x2List([int offsetInBytes = 0, int length]) {
@@ -2018,7 +2028,8 @@
         (this.lengthInBytes - offsetInBytes) ~/ Float64x2List.bytesPerElement;
     _rangeCheck(this.lengthInBytes, offsetInBytes,
         length * Float64x2List.bytesPerElement);
-    return new _Float64x2ArrayView(this, offsetInBytes, length);
+    _offsetAlignmentCheck(offsetInBytes, Float64x2List.bytesPerElement);
+    return new _Float64x2ArrayView(this._data, offsetInBytes, length);
   }
 }
 
@@ -3562,11 +3573,6 @@
 }
 
 abstract class _TypedListView extends _TypedListBase implements TypedData {
-  _TypedListView(_ByteBuffer _buffer, int _offset, int _length)
-      : _typedData = _buffer._data,
-        offsetInBytes = _offset,
-        length = _length;
-
   // Method(s) implementing the TypedData interface.
 
   int get lengthInBytes {
@@ -3578,13 +3584,13 @@
   }
 
   @pragma("vm:non-nullable-result-type")
-  final _TypedList _typedData;
+  _TypedList get _typedData native "TypedDataView_typedData";
 
   @pragma("vm:exact-result-type", "dart:core#_Smi")
-  final int offsetInBytes;
+  int get offsetInBytes native "TypedDataView_offsetInBytes";
 
   @pragma("vm:exact-result-type", "dart:core#_Smi")
-  final int length;
+  int get length native "TypedDataView_length";
 }
 
 @pragma("vm:entry-point")
@@ -3592,8 +3598,9 @@
     with _IntListMixin
     implements Int8List {
   // Constructor.
-  _Int8ArrayView(_ByteBuffer buffer, int offsetInBytes, int length)
-      : super(buffer, offsetInBytes, length);
+  @pragma("vm:exact-result-type", _Int8ArrayView)
+  factory _Int8ArrayView(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Int8ArrayView_new";
 
   // Method(s) implementing List interface.
   int operator [](int index) {
@@ -3628,8 +3635,9 @@
     with _IntListMixin
     implements Uint8List {
   // Constructor.
-  _Uint8ArrayView(_ByteBuffer buffer, int offsetInBytes, int length)
-      : super(buffer, offsetInBytes, length);
+  @pragma("vm:exact-result-type", _Uint8ArrayView)
+  factory _Uint8ArrayView(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Uint8ArrayView_new";
 
   // Method(s) implementing List interface.
   int operator [](int index) {
@@ -3664,8 +3672,9 @@
     with _IntListMixin
     implements Uint8ClampedList {
   // Constructor.
-  _Uint8ClampedArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
-      : super(buffer, _offsetInBytes, _length);
+  @pragma("vm:exact-result-type", _Uint8ClampedArrayView)
+  factory _Uint8ClampedArrayView(_TypedList buffer, int offsetInBytes,
+      int length) native "TypedDataView_Uint8ClampedArrayView_new";
 
   // Method(s) implementing List interface.
   int operator [](int index) {
@@ -3700,10 +3709,9 @@
     with _IntListMixin
     implements Int16List {
   // Constructor.
-  _Int16ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
-      : super(buffer, _offsetInBytes, _length) {
-    _offsetAlignmentCheck(_offsetInBytes, Int16List.bytesPerElement);
-  }
+  @pragma("vm:exact-result-type", _Int16ArrayView)
+  factory _Int16ArrayView(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Int16ArrayView_new";
 
   // Method(s) implementing List interface.
   int operator [](int index) {
@@ -3750,10 +3758,9 @@
     with _IntListMixin
     implements Uint16List {
   // Constructor.
-  _Uint16ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
-      : super(buffer, _offsetInBytes, _length) {
-    _offsetAlignmentCheck(_offsetInBytes, Uint16List.bytesPerElement);
-  }
+  @pragma("vm:exact-result-type", _Uint16ArrayView)
+  factory _Uint16ArrayView(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Uint16ArrayView_new";
 
   // Method(s) implementing List interface.
   int operator [](int index) {
@@ -3801,10 +3808,9 @@
     with _IntListMixin
     implements Int32List {
   // Constructor.
-  _Int32ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
-      : super(buffer, _offsetInBytes, _length) {
-    _offsetAlignmentCheck(_offsetInBytes, Int32List.bytesPerElement);
-  }
+  @pragma("vm:exact-result-type", _Int32ArrayView)
+  factory _Int32ArrayView(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Int32ArrayView_new";
 
   // Method(s) implementing List interface.
   int operator [](int index) {
@@ -3839,10 +3845,9 @@
     with _IntListMixin
     implements Uint32List {
   // Constructor.
-  _Uint32ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
-      : super(buffer, _offsetInBytes, _length) {
-    _offsetAlignmentCheck(_offsetInBytes, Uint32List.bytesPerElement);
-  }
+  @pragma("vm:exact-result-type", _Uint32ArrayView)
+  factory _Uint32ArrayView(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Uint32ArrayView_new";
 
   // Method(s) implementing List interface.
   int operator [](int index) {
@@ -3877,10 +3882,9 @@
     with _IntListMixin
     implements Int64List {
   // Constructor.
-  _Int64ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
-      : super(buffer, _offsetInBytes, _length) {
-    _offsetAlignmentCheck(_offsetInBytes, Int64List.bytesPerElement);
-  }
+  @pragma("vm:exact-result-type", _Int64ArrayView)
+  factory _Int64ArrayView(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Int64ArrayView_new";
 
   // Method(s) implementing List interface.
   int operator [](int index) {
@@ -3915,10 +3919,9 @@
     with _IntListMixin
     implements Uint64List {
   // Constructor.
-  _Uint64ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
-      : super(buffer, _offsetInBytes, _length) {
-    _offsetAlignmentCheck(_offsetInBytes, Uint64List.bytesPerElement);
-  }
+  @pragma("vm:exact-result-type", _Uint64ArrayView)
+  factory _Uint64ArrayView(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Uint64ArrayView_new";
 
   // Method(s) implementing List interface.
   int operator [](int index) {
@@ -3953,10 +3956,9 @@
     with _DoubleListMixin
     implements Float32List {
   // Constructor.
-  _Float32ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
-      : super(buffer, _offsetInBytes, _length) {
-    _offsetAlignmentCheck(_offsetInBytes, Float32List.bytesPerElement);
-  }
+  @pragma("vm:exact-result-type", _Float32ArrayView)
+  factory _Float32ArrayView(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Float32ArrayView_new";
 
   // Method(s) implementing List interface.
   double operator [](int index) {
@@ -3991,10 +3993,9 @@
     with _DoubleListMixin
     implements Float64List {
   // Constructor.
-  _Float64ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
-      : super(buffer, _offsetInBytes, _length) {
-    _offsetAlignmentCheck(_offsetInBytes, Float64List.bytesPerElement);
-  }
+  @pragma("vm:exact-result-type", _Float64ArrayView)
+  factory _Float64ArrayView(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Float64ArrayView_new";
 
   // Method(s) implementing List interface.
   double operator [](int index) {
@@ -4029,10 +4030,9 @@
     with _Float32x4ListMixin
     implements Float32x4List {
   // Constructor.
-  _Float32x4ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
-      : super(buffer, _offsetInBytes, _length) {
-    _offsetAlignmentCheck(_offsetInBytes, Float32x4List.bytesPerElement);
-  }
+  @pragma("vm:exact-result-type", _Float32x4ArrayView)
+  factory _Float32x4ArrayView(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Float32x4ArrayView_new";
 
   // Method(s) implementing List interface.
   Float32x4 operator [](int index) {
@@ -4067,10 +4067,9 @@
     with _Int32x4ListMixin
     implements Int32x4List {
   // Constructor.
-  _Int32x4ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
-      : super(buffer, _offsetInBytes, _length) {
-    _offsetAlignmentCheck(_offsetInBytes, Int32x4List.bytesPerElement);
-  }
+  @pragma("vm:exact-result-type", _Int32x4ArrayView)
+  factory _Int32x4ArrayView(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Int32x4ArrayView_new";
 
   // Method(s) implementing List interface.
   Int32x4 operator [](int index) {
@@ -4105,10 +4104,9 @@
     with _Float64x2ListMixin
     implements Float64x2List {
   // Constructor.
-  _Float64x2ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
-      : super(buffer, _offsetInBytes, _length) {
-    _offsetAlignmentCheck(_offsetInBytes, Float64x2List.bytesPerElement);
-  }
+  @pragma("vm:exact-result-type", _Float64x2ArrayView)
+  factory _Float64x2ArrayView(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Float64x2ArrayView_new";
 
   // Method(s) implementing List interface.
   Float64x2 operator [](int index) {
@@ -4140,7 +4138,9 @@
 
 @pragma("vm:entry-point")
 class _ByteDataView implements ByteData {
-  _ByteDataView(this._typedData, this._offset, this.length);
+  @pragma("vm:exact-result-type", _ByteDataView)
+  factory _ByteDataView(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_ByteDataView_new";
 
   // Method(s) implementing TypedData interface.
   _ByteBuffer get buffer {
@@ -4151,10 +4151,6 @@
     return length;
   }
 
-  int get offsetInBytes {
-    return _offset;
-  }
-
   int get elementSizeInBytes {
     return 1;
   }
@@ -4165,35 +4161,35 @@
     if (byteOffset < 0 || byteOffset >= length) {
       throw new RangeError.index(byteOffset, this, "byteOffset");
     }
-    return _typedData._getInt8(_offset + byteOffset);
+    return _typedData._getInt8(offsetInBytes + byteOffset);
   }
 
   void setInt8(int byteOffset, int value) {
     if (byteOffset < 0 || byteOffset >= length) {
       throw new RangeError.index(byteOffset, this, "byteOffset");
     }
-    _typedData._setInt8(_offset + byteOffset, value);
+    _typedData._setInt8(offsetInBytes + byteOffset, value);
   }
 
   int getUint8(int byteOffset) {
     if (byteOffset < 0 || byteOffset >= length) {
       throw new RangeError.index(byteOffset, this, "byteOffset");
     }
-    return _typedData._getUint8(_offset + byteOffset);
+    return _typedData._getUint8(offsetInBytes + byteOffset);
   }
 
   void setUint8(int byteOffset, int value) {
     if (byteOffset < 0 || byteOffset >= length) {
       throw new RangeError.index(byteOffset, this, "byteOffset");
     }
-    _typedData._setUint8(_offset + byteOffset, value);
+    _typedData._setUint8(offsetInBytes + byteOffset, value);
   }
 
   int getInt16(int byteOffset, [Endian endian = Endian.big]) {
     if (byteOffset < 0 || byteOffset + 1 >= length) {
       throw new RangeError.range(byteOffset, 0, length - 2, "byteOffset");
     }
-    var result = _typedData._getInt16(_offset + byteOffset);
+    var result = _typedData._getInt16(offsetInBytes + byteOffset);
     if (identical(endian, Endian.host)) {
       return result;
     }
@@ -4204,7 +4200,7 @@
     if (byteOffset < 0 || byteOffset + 1 >= length) {
       throw new RangeError.range(byteOffset, 0, length - 2, "byteOffset");
     }
-    _typedData._setInt16(_offset + byteOffset,
+    _typedData._setInt16(offsetInBytes + byteOffset,
         identical(endian, Endian.host) ? value : _byteSwap16(value));
   }
 
@@ -4212,7 +4208,7 @@
     if (byteOffset < 0 || byteOffset + 1 >= length) {
       throw new RangeError.range(byteOffset, 0, length - 2, "byteOffset");
     }
-    var result = _typedData._getUint16(_offset + byteOffset);
+    var result = _typedData._getUint16(offsetInBytes + byteOffset);
     if (identical(endian, Endian.host)) {
       return result;
     }
@@ -4223,7 +4219,7 @@
     if (byteOffset < 0 || byteOffset + 1 >= length) {
       throw new RangeError.range(byteOffset, 0, length - 2, "byteOffset");
     }
-    _typedData._setUint16(_offset + byteOffset,
+    _typedData._setUint16(offsetInBytes + byteOffset,
         identical(endian, Endian.host) ? value : _byteSwap16(value));
   }
 
@@ -4231,7 +4227,7 @@
     if (byteOffset < 0 || byteOffset + 3 >= length) {
       throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
     }
-    var result = _typedData._getInt32(_offset + byteOffset);
+    var result = _typedData._getInt32(offsetInBytes + byteOffset);
     if (identical(endian, Endian.host)) {
       return result;
     }
@@ -4242,7 +4238,7 @@
     if (byteOffset < 0 || byteOffset + 3 >= length) {
       throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
     }
-    _typedData._setInt32(_offset + byteOffset,
+    _typedData._setInt32(offsetInBytes + byteOffset,
         identical(endian, Endian.host) ? value : _byteSwap32(value));
   }
 
@@ -4250,7 +4246,7 @@
     if (byteOffset < 0 || byteOffset + 3 >= length) {
       throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
     }
-    var result = _typedData._getUint32(_offset + byteOffset);
+    var result = _typedData._getUint32(offsetInBytes + byteOffset);
     if (identical(endian, Endian.host)) {
       return result;
     }
@@ -4261,7 +4257,7 @@
     if (byteOffset < 0 || byteOffset + 3 >= length) {
       throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
     }
-    _typedData._setUint32(_offset + byteOffset,
+    _typedData._setUint32(offsetInBytes + byteOffset,
         identical(endian, Endian.host) ? value : _byteSwap32(value));
   }
 
@@ -4269,7 +4265,7 @@
     if (byteOffset < 0 || byteOffset + 7 >= length) {
       throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
     }
-    var result = _typedData._getInt64(_offset + byteOffset);
+    var result = _typedData._getInt64(offsetInBytes + byteOffset);
     if (identical(endian, Endian.host)) {
       return result;
     }
@@ -4280,7 +4276,7 @@
     if (byteOffset < 0 || byteOffset + 7 >= length) {
       throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
     }
-    _typedData._setInt64(_offset + byteOffset,
+    _typedData._setInt64(offsetInBytes + byteOffset,
         identical(endian, Endian.host) ? value : _byteSwap64(value));
   }
 
@@ -4288,7 +4284,7 @@
     if (byteOffset < 0 || byteOffset + 7 >= length) {
       throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
     }
-    var result = _typedData._getUint64(_offset + byteOffset);
+    var result = _typedData._getUint64(offsetInBytes + byteOffset);
     if (identical(endian, Endian.host)) {
       return result;
     }
@@ -4299,7 +4295,7 @@
     if (byteOffset < 0 || byteOffset + 7 >= length) {
       throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
     }
-    _typedData._setUint64(_offset + byteOffset,
+    _typedData._setUint64(offsetInBytes + byteOffset,
         identical(endian, Endian.host) ? value : _byteSwap64(value));
   }
 
@@ -4308,9 +4304,10 @@
       throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
     }
     if (identical(endian, Endian.host)) {
-      return _typedData._getFloat32(_offset + byteOffset);
+      return _typedData._getFloat32(offsetInBytes + byteOffset);
     }
-    _convU32[0] = _byteSwap32(_typedData._getUint32(_offset + byteOffset));
+    _convU32[0] =
+        _byteSwap32(_typedData._getUint32(offsetInBytes + byteOffset));
     return _convF32[0];
   }
 
@@ -4319,11 +4316,11 @@
       throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
     }
     if (identical(endian, Endian.host)) {
-      _typedData._setFloat32(_offset + byteOffset, value);
+      _typedData._setFloat32(offsetInBytes + byteOffset, value);
       return;
     }
     _convF32[0] = value;
-    _typedData._setUint32(_offset + byteOffset, _byteSwap32(_convU32[0]));
+    _typedData._setUint32(offsetInBytes + byteOffset, _byteSwap32(_convU32[0]));
   }
 
   double getFloat64(int byteOffset, [Endian endian = Endian.big]) {
@@ -4331,9 +4328,10 @@
       throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
     }
     if (identical(endian, Endian.host)) {
-      return _typedData._getFloat64(_offset + byteOffset);
+      return _typedData._getFloat64(offsetInBytes + byteOffset);
     }
-    _convU64[0] = _byteSwap64(_typedData._getUint64(_offset + byteOffset));
+    _convU64[0] =
+        _byteSwap64(_typedData._getUint64(offsetInBytes + byteOffset));
     return _convF64[0];
   }
 
@@ -4342,11 +4340,11 @@
       throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
     }
     if (identical(endian, Endian.host)) {
-      _typedData._setFloat64(_offset + byteOffset, value);
+      _typedData._setFloat64(offsetInBytes + byteOffset, value);
       return;
     }
     _convF64[0] = value;
-    _typedData._setUint64(_offset + byteOffset, _byteSwap64(_convU64[0]));
+    _typedData._setUint64(offsetInBytes + byteOffset, _byteSwap64(_convU64[0]));
   }
 
   Float32x4 getFloat32x4(int byteOffset, [Endian endian = Endian.big]) {
@@ -4354,7 +4352,7 @@
       throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
     }
     // TODO(johnmccutchan) : Need to resolve this for endianity.
-    return _typedData._getFloat32x4(_offset + byteOffset);
+    return _typedData._getFloat32x4(offsetInBytes + byteOffset);
   }
 
   void setFloat32x4(int byteOffset, Float32x4 value,
@@ -4363,17 +4361,17 @@
       throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
     }
     // TODO(johnmccutchan) : Need to resolve this for endianity.
-    _typedData._setFloat32x4(_offset + byteOffset, value);
+    _typedData._setFloat32x4(offsetInBytes + byteOffset, value);
   }
 
   @pragma("vm:non-nullable-result-type")
-  final _TypedList _typedData;
+  _TypedList get _typedData native "TypedDataView_typedData";
 
   @pragma("vm:exact-result-type", "dart:core#_Smi")
-  final int _offset;
+  int get offsetInBytes native "TypedDataView_offsetInBytes";
 
   @pragma("vm:exact-result-type", "dart:core#_Smi")
-  final int length;
+  int get length native "TypedDataView_length";
 }
 
 int _byteSwap16(int value) {
diff --git a/runtime/observatory/lib/src/models/repositories/eval.dart b/runtime/observatory/lib/src/models/repositories/eval.dart
index e127d84..2bd4c61 100644
--- a/runtime/observatory/lib/src/models/repositories/eval.dart
+++ b/runtime/observatory/lib/src/models/repositories/eval.dart
@@ -6,5 +6,6 @@
 
 abstract class EvalRepository {
   Future<ObjectRef> evaluate(
-      IsolateRef isolate, ObjectRef context, String expression);
+      IsolateRef isolate, ObjectRef context, String expression,
+      {bool disableBreakpoints: false});
 }
diff --git a/runtime/observatory/lib/src/repositories/eval.dart b/runtime/observatory/lib/src/repositories/eval.dart
index 90b8b12..57ab1ec 100644
--- a/runtime/observatory/lib/src/repositories/eval.dart
+++ b/runtime/observatory/lib/src/repositories/eval.dart
@@ -5,12 +5,14 @@
 part of repositories;
 
 class EvalRepository extends M.EvalRepository {
-  Future<M.ObjectRef> evaluate(M.IsolateRef i, M.ObjectRef o, String e) async {
+  Future<M.ObjectRef> evaluate(M.IsolateRef i, M.ObjectRef o, String e,
+      {bool disableBreakpoints: false}) async {
     S.Isolate isolate = i as S.Isolate;
     S.ServiceObject object = o as S.HeapObject;
     assert(isolate != null);
     assert(object != null);
     assert(e != null);
-    return await isolate.eval(object, e);
+    return await isolate.eval(object, e,
+        disableBreakpoints: disableBreakpoints);
   }
 }
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index aa59574..cc8f158 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1893,10 +1893,11 @@
   }
 
   Future<ServiceObject> eval(ServiceObject target, String expression,
-      {Map<String, ServiceObject> scope}) {
+      {Map<String, ServiceObject> scope, bool disableBreakpoints: false}) {
     Map params = {
       'targetId': target.id,
       'expression': expression,
+      'disableBreakpoints': disableBreakpoints,
     };
     if (scope != null) {
       Map<String, String> scopeWithIds = new Map();
@@ -1909,10 +1910,12 @@
   }
 
   Future<ServiceObject> evalFrame(int frameIndex, String expression,
-      {Map<String, ServiceObject> scope}) async {
+      {Map<String, ServiceObject> scope,
+      bool disableBreakpoints: false}) async {
     Map params = {
       'frameIndex': frameIndex,
       'expression': expression,
+      'disableBreakpoints': disableBreakpoints,
     };
     if (scope != null) {
       Map<String, String> scopeWithIds = new Map();
@@ -2482,8 +2485,9 @@
   }
 
   Future<ServiceObject> evaluate(String expression,
-      {Map<String, ServiceObject> scope}) {
-    return isolate.eval(this, expression, scope: scope);
+      {Map<String, ServiceObject> scope, bool disableBreakpoints: false}) {
+    return isolate.eval(this, expression,
+        scope: scope, disableBreakpoints: disableBreakpoints);
   }
 
   Script get rootScript {
@@ -2661,8 +2665,9 @@
   }
 
   Future<ServiceObject> evaluate(String expression,
-      {Map<String, ServiceObject> scope}) {
-    return isolate.eval(this, expression, scope: scope);
+      {Map<String, ServiceObject> scope, disableBreakpoints: false}) {
+    return isolate.eval(this, expression,
+        scope: scope, disableBreakpoints: disableBreakpoints);
   }
 
   Future<ServiceObject> setTraceAllocations(bool enable) {
@@ -3027,8 +3032,9 @@
   }
 
   Future<ServiceObject> evaluate(String expression,
-      {Map<String, ServiceObject> scope}) {
-    return isolate.eval(this, expression, scope: scope);
+      {Map<String, ServiceObject> scope, bool disableBreakpoints: false}) {
+    return isolate.eval(this, expression,
+        scope: scope, disableBreakpoints: disableBreakpoints);
   }
 
   String toString() => 'Instance($shortName)';
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/eval.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/eval.dart
index 5f143fa..0b7a072 100644
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/eval.dart
+++ b/runtime/observatory/tests/observatory_ui/mocks/repositories/eval.dart
@@ -5,7 +5,8 @@
 part of mocks;
 
 typedef Future<M.Object> EvalRepositoryMockCallback(
-    M.IsolateRef isolate, M.ObjectRef context, String expression);
+    M.IsolateRef isolate, M.ObjectRef context, String expression,
+    {bool disableBreakpoints});
 
 class EvalRepositoryMock implements M.EvalRepository {
   final EvalRepositoryMockCallback _get;
@@ -13,9 +14,11 @@
   EvalRepositoryMock({EvalRepositoryMockCallback getter}) : _get = getter;
 
   Future<M.Object> evaluate(
-      M.IsolateRef isolate, M.ObjectRef context, String expression) {
+      M.IsolateRef isolate, M.ObjectRef context, String expression,
+      {bool disableBreakpoints: false}) {
     if (_get != null) {
-      return _get(isolate, context, expression);
+      return _get(isolate, context, expression,
+          disableBreakpoints: disableBreakpoints);
     }
     return new Future.value(null);
   }
diff --git a/runtime/observatory/tests/service/eval_skip_breakpoint.dart b/runtime/observatory/tests/service/eval_skip_breakpoint.dart
new file mode 100644
index 0000000..447852f
--- /dev/null
+++ b/runtime/observatory/tests/service/eval_skip_breakpoint.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2019, 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.
+// VMOptions=--verbose_debug
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:developer';
+
+const int LINE_A = 21;
+const int LINE_B = 16;
+
+bar() {
+  print('bar');
+}
+
+testMain() {
+  debugger();
+  bar();
+  print("Done");
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+// Add breakpoint
+  setBreakpointAtLine(LINE_B),
+// Evaluate 'bar()'
+  (Isolate isolate) async {
+    final lib = isolate.rootLibrary;
+    await lib.evaluate('bar()', disableBreakpoints: true);
+  },
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  resumeIsolate,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory/tests/service/get_memory_usage.dart b/runtime/observatory/tests/service/get_memory_usage.dart
new file mode 100644
index 0000000..96832c2
--- /dev/null
+++ b/runtime/observatory/tests/service/get_memory_usage.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2019, 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 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  (VM vm) async {
+    var params = {
+      'isolateId': vm.isolates.first.id,
+    };
+    var result = await vm.invokeRpcNoUpgrade('getMemoryUsage', params);
+    expect(result['type'], equals('MemoryUsage'));
+    expect(result['heapUsage'], isPositive);
+    expect(result['heapCapacity'], isPositive);
+    expect(result['externalUsage'], isPositive);
+  },
+  (VM vm) async {
+    var params = {
+      'isolateId': 'badid',
+    };
+    bool caughtException;
+    try {
+      await vm.invokeRpcNoUpgrade('getMemoryUsage', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message, "getMemoryUsage: invalid 'isolateId' parameter: badid");
+    }
+    expect(caughtException, isTrue);
+  },
+
+  // Plausible isolate id, not found.
+  (VM vm) async {
+    var params = {
+      'isolateId': 'isolates/9999999999',
+    };
+    var result = await vm.invokeRpcNoUpgrade('getMemoryUsage', params);
+    expect(result['type'], equals('Sentinel'));
+    expect(result['kind'], equals('Collected'));
+    expect(result['valueAsString'], equals('<collected>'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory/tests/service/invoke_skip_breakpoint.dart b/runtime/observatory/tests/service/invoke_skip_breakpoint.dart
new file mode 100644
index 0000000..d2d258c
--- /dev/null
+++ b/runtime/observatory/tests/service/invoke_skip_breakpoint.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2019, 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:developer';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const int LINE_A = 21;
+const int LINE_B = 16;
+
+bar() {
+  print('bar');
+  return 'bar';
+}
+
+testMain() {
+  debugger();
+  bar();
+  print("Done");
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  setBreakpointAtLine(LINE_B),
+  (Isolate isolate) async {
+    Library lib = isolate.rootLibrary;
+    await lib.load();
+
+    dynamic result = await isolate.invokeRpc("invoke", {
+      "targetId": lib.id,
+      "selector": "bar",
+      "argumentIds": [],
+      "disableBreakpoints": true
+    });
+    print(result);
+    expect(result.valueAsString, equals('bar'));
+  },
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory/tests/service/step_through_mixin_from_sdk_test.dart b/runtime/observatory/tests/service/step_through_mixin_from_sdk_test.dart
index a38c966..9f70deb 100644
--- a/runtime/observatory/tests/service/step_through_mixin_from_sdk_test.dart
+++ b/runtime/observatory/tests/service/step_through_mixin_from_sdk_test.dart
@@ -33,23 +33,23 @@
 
 List<String> stops = [];
 List<String> expected = [
-  "$file:${LINE+0}:17", // on "Foo" (in "new Foo()")
-  "$file:${LINE+1}:11", // on "="
-  "list.dart:105:24", // on parameter to "contains"
-  "list.dart:106:23", // on "length" in "this.length"
-  "list.dart:107:16", // on "=" in "i = 0"
-  "list.dart:107:23", // on "<" in "i < length"
-  "list.dart:108:15", // on "[" in "this[i]"
-  "$file:${LINE+13}:23", // on parameter in "operator []"
-  "$file:${LINE+14}:5", // on "return"
-  "list.dart:108:19", // on "=="
-  "list.dart:109:26", // on "length" in "this.length"
-  "list.dart:109:18", // on "!="
-  "list.dart:107:34", // on "++" in "i++"
-  "list.dart:107:23", // on "<" in "i < length"
-  "list.dart:113:5", // on "return"
-  "$file:${LINE+4}:5", // on "print"
-  "$file:${LINE+6}:1" // on ending '}'
+  "$file:${LINE + 0}:17", // on "Foo" (in "new Foo()")
+  "$file:${LINE + 1}:11", // on "="
+  "list.dart:100:24", // on parameter to "contains"
+  "list.dart:101:23", // on "length" in "this.length"
+  "list.dart:102:16", // on "=" in "i = 0"
+  "list.dart:102:23", // on "<" in "i < length"
+  "list.dart:103:15", // on "[" in "this[i]"
+  "$file:${LINE + 13}:23", // on parameter in "operator []"
+  "$file:${LINE + 14}:5", // on "return"
+  "list.dart:103:19", // on "=="
+  "list.dart:104:26", // on "length" in "this.length"
+  "list.dart:104:18", // on "!="
+  "list.dart:102:34", // on "++" in "i++"
+  "list.dart:102:23", // on "<" in "i < length"
+  "list.dart:108:5", // on "return"
+  "$file:${LINE + 4}:5", // on "print"
+  "$file:${LINE + 6}:1" // on ending '}'
 ];
 
 var tests = <IsolateTest>[
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 6171827..07d2d03 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -352,12 +352,6 @@
 #error Unknown architecture.
 #endif
 
-// Disable background threads by default on armv5te. The relevant
-// implementations are uniprocessors.
-#if !defined(TARGET_ARCH_ARM_5TE)
-#define ARCH_IS_MULTI_CORE 1
-#endif
-
 #if !defined(TARGET_OS_ANDROID) && !defined(TARGET_OS_FUCHSIA) &&              \
     !defined(TARGET_OS_MACOS_IOS) && !defined(TARGET_OS_LINUX) &&              \
     !defined(TARGET_OS_MACOS) && !defined(TARGET_OS_WINDOWS)
@@ -380,6 +374,19 @@
 #endif
 #endif
 
+// Determine whether dual mapping of code pages is supported.
+// We test dual mapping on linux x64 and deploy it on fuchsia.
+#if defined(TARGET_OS_LINUX) && defined(TARGET_ARCH_X64) ||                    \
+    defined(TARGET_OS_FUCHSIA)
+#define DUAL_MAPPING_SUPPORTED 1
+#endif
+
+// Disable background threads by default on armv5te. The relevant
+// implementations are uniprocessors.
+#if !defined(TARGET_ARCH_ARM_5TE)
+#define ARCH_IS_MULTI_CORE 1
+#endif
+
 // Short form printf format specifiers
 #define Pd PRIdPTR
 #define Pu PRIuPTR
diff --git a/runtime/tests/vm/dart/compilation_trace_test.dart b/runtime/tests/vm/dart/compilation_trace_test.dart
new file mode 100644
index 0000000..4ebafb5
--- /dev/null
+++ b/runtime/tests/vm/dart/compilation_trace_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2019, 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:async";
+import "dart:io";
+
+import "package:path/path.dart" as p;
+
+import "snapshot_test_helper.dart";
+
+int fib(int n) {
+  if (n <= 1) return 1;
+  return fib(n - 1) + fib(n - 2);
+}
+
+Future<void> main(List<String> args) async {
+  if (args.contains("--child")) {
+    print(fib(35));
+    return;
+  }
+
+  if (!Platform.script.toString().endsWith(".dart")) {
+    print("This test must run from source");
+    return;
+  }
+
+  await withTempDir((String tmp) async {
+    final String tracePath = p.join(tmp, "compilation_trace.txt");
+
+    final result1 = await runDart("generate compilation trace", [
+      "--save_compilation_trace=$tracePath",
+      Platform.script.toFilePath(),
+      "--child",
+    ]);
+    expectOutput("14930352", result1);
+
+    final result2 = await runDart("use compilation trace", [
+      "--load_compilation_trace=$tracePath",
+      Platform.script.toFilePath(),
+      "--child",
+    ]);
+    expectOutput("14930352", result2);
+  });
+}
diff --git a/runtime/tests/vm/dart/licm_and_assert_strengthening_test.dart b/runtime/tests/vm/dart/licm_and_assert_strengthening_test.dart
new file mode 100644
index 0000000..a1c962e
--- /dev/null
+++ b/runtime/tests/vm/dart/licm_and_assert_strengthening_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2019, 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.
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+// This test checks for obscure interaction between LICM and AssertAssignable
+// strengthening performed by Type Propagator. The later would use deopt_id
+// from an environment attached to AssertAssignable, and this deopt id under
+// certain conditions would be set to -1. The code was changed to never
+// use deopt_id from the environment but this regression test is provided for
+// completeness.
+
+class A<T> {
+  var foo = 42;
+}
+
+class B extends A<String> {}
+
+class C extends B {}
+
+void foo(dynamic a) {
+  // To prevent AssertAssignable strengthening from occuring too early we
+  // need to hide the fact that CheckClass and AssertAssignable are performed
+  // against the same SSA value. To achieve that we store a into an array and
+  // then load it back. Load Forwarding would happen just before LICM and
+  // will remove the indirection. Then LICM would hoist both CheckClass
+  // and AssertAssignable out of the loop and then strengthening would happen.
+  final box = <dynamic>[null];
+  box[0] = a;
+
+  for (var i = 0; i < 1; i++) {
+    a as A<String>;
+    if (box[0].foo != 42) {
+      throw "unexpected";
+    }
+  }
+}
+
+void main() {
+  for (var i = 0; i < 100; i++) {
+    foo(B());
+  }
+
+  // Trigger deoptimization on the CheckClass produced by strengthened
+  // AssertAssignable - if this CheckClass has wrong deoptimization id a crash
+  // would occur.
+  foo(C());
+}
diff --git a/runtime/tests/vm/dart/reused_instructions_test.dart b/runtime/tests/vm/dart/reused_instructions_test.dart
new file mode 100644
index 0000000..a2316c8
--- /dev/null
+++ b/runtime/tests/vm/dart/reused_instructions_test.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2019, 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:async";
+import "dart:io";
+
+import "package:path/path.dart" as p;
+
+import "snapshot_test_helper.dart";
+
+int fib(int n) {
+  if (n <= 1) return 1;
+  return fib(n - 1) + fib(n - 2);
+}
+
+Future<void> main(List<String> args) async {
+  if (args.contains("--child")) {
+    print(fib(35));
+    return;
+  }
+
+  if (!Platform.script.toString().endsWith(".dart")) {
+    print("This test must run from source");
+    return;
+  }
+
+  await withTempDir((String tmp) async {
+    final String coreVMDataPath = p.join(tmp, "core_vm_snapshot_data.bin");
+    final String coreIsoDataPath =
+        p.join(tmp, "core_isolate_snapshot_data.bin");
+    final String baselineIsoDataPath =
+        p.join(tmp, "baseline_isolate_snapshot_data.bin");
+    final String baselineIsoInstrPath =
+        p.join(tmp, "baseline_isolate_snapshot_instructions.bin");
+    final String patchIsoDataPath =
+        p.join(tmp, "patch_isolate_snapshot_data.bin");
+    final String patchIsoInstrPath =
+        p.join(tmp, "patch_isolate_snapshot_instr.bin");
+    final String kernelPath = p.join(tmp, "app.dill");
+    final String tracePath = p.join(tmp, "compilation_trace.txt");
+
+    // We don't support snapshot with code on IA32.
+    final String appSnapshotKind =
+        Platform.version.contains("ia32") ? "app" : "app-jit";
+
+    final result1 = await runGenKernel("generate kernel", [
+      Platform.script.toFilePath(),
+      "--output",
+      kernelPath,
+    ]);
+    expectOutput("", result1);
+
+    final result2 = await runDart("generate compilation trace", [
+      "--save_compilation_trace=$tracePath",
+      kernelPath,
+      "--child",
+    ]);
+    expectOutput("14930352", result2);
+
+    final result3 = await runGenSnapshot("generate core snapshot", [
+      "--snapshot_kind=core",
+      "--vm_snapshot_data=${coreVMDataPath}",
+      "--isolate_snapshot_data=${coreIsoDataPath}",
+      platformDill,
+    ]);
+    expectOutput("", result3);
+
+    final result4 = await runGenSnapshot("generate baseline app snapshot", [
+      "--snapshot_kind=${appSnapshotKind}",
+      "--load_vm_snapshot_data=${coreVMDataPath}",
+      "--load_isolate_snapshot_data=${coreIsoDataPath}",
+      "--isolate_snapshot_data=${baselineIsoDataPath}",
+      "--isolate_snapshot_instructions=${baselineIsoInstrPath}",
+      "--load_compilation_trace=$tracePath",
+      kernelPath,
+    ]);
+    expectOutput("", result4);
+
+    final result5 = await runGenSnapshot("generate patch app snapshot", [
+      "--snapshot_kind=${appSnapshotKind}",
+      "--load_vm_snapshot_data=${coreVMDataPath}",
+      "--load_isolate_snapshot_data=${coreIsoDataPath}",
+      "--isolate_snapshot_data=${patchIsoDataPath}",
+      "--isolate_snapshot_instructions=${patchIsoInstrPath}",
+      "--reused_instructions=${baselineIsoInstrPath}",
+      "--load_compilation_trace=$tracePath",
+      kernelPath,
+    ]);
+    expectOutput("", result5);
+  });
+}
diff --git a/runtime/tests/vm/dart/shared_snapshot_test.dart b/runtime/tests/vm/dart/shared_snapshot_test.dart
new file mode 100644
index 0000000..eff8068
--- /dev/null
+++ b/runtime/tests/vm/dart/shared_snapshot_test.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2019, 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:async";
+import "dart:io";
+
+import "package:path/path.dart" as p;
+
+import "snapshot_test_helper.dart";
+
+int fib(int n) {
+  if (n <= 1) return 1;
+  return fib(n - 1) + fib(n - 2);
+}
+
+Future<void> main(List<String> args) async {
+  if (args.contains("--child")) {
+    print(fib(35));
+    return;
+  }
+
+  if (!Platform.script.toString().endsWith(".dart")) {
+    print("This test must run from source");
+    return;
+  }
+
+  await withTempDir((String tmp) async {
+    final String coreVMDataPath = p.join(tmp, "core_vm_snapshot_data.bin");
+    final String coreIsoDataPath =
+        p.join(tmp, "core_isolate_snapshot_data.bin");
+    final String baselineIsoDataPath =
+        p.join(tmp, "baseline_isolate_snapshot_data.bin");
+    final String baselineIsoInstrPath =
+        p.join(tmp, "baseline_isolate_snapshot_instructions.bin");
+    final String patchIsoDataPath =
+        p.join(tmp, "patch_isolate_snapshot_data.bin");
+    final String patchIsoInstrPath =
+        p.join(tmp, "patch_isolate_snapshot_instr.bin");
+    final String kernelPath = p.join(tmp, "app.dill");
+    final String tracePath = p.join(tmp, "compilation_trace.txt");
+
+    // We don't support snapshot with code on IA32.
+    final String appSnapshotKind =
+        Platform.version.contains("ia32") ? "app" : "app-jit";
+
+    final result1 = await runGenKernel("generate kernel", [
+      Platform.script.toFilePath(),
+      "--output",
+      kernelPath,
+    ]);
+    expectOutput("", result1);
+
+    final result2 = await runDart("generate compilation trace", [
+      "--save_compilation_trace=$tracePath",
+      kernelPath,
+      "--child",
+    ]);
+    expectOutput("14930352", result2);
+
+    final result3 = await runGenSnapshot("generate core snapshot", [
+      "--snapshot_kind=core",
+      "--vm_snapshot_data=${coreVMDataPath}",
+      "--isolate_snapshot_data=${coreIsoDataPath}",
+      platformDill,
+    ]);
+    expectOutput("", result3);
+
+    final result4 = await runGenSnapshot("generate baseline app snapshot", [
+      "--snapshot_kind=${appSnapshotKind}",
+      "--load_vm_snapshot_data=${coreVMDataPath}",
+      "--load_isolate_snapshot_data=${coreIsoDataPath}",
+      "--isolate_snapshot_data=${baselineIsoDataPath}",
+      "--isolate_snapshot_instructions=${baselineIsoInstrPath}",
+      "--load_compilation_trace=$tracePath",
+      kernelPath,
+    ]);
+    expectOutput("", result4);
+
+    final result5 = await runGenSnapshot("generate patch app snapshot", [
+      "--snapshot_kind=${appSnapshotKind}",
+      "--load_vm_snapshot_data=${coreVMDataPath}",
+      "--load_isolate_snapshot_data=${coreIsoDataPath}",
+      "--isolate_snapshot_data=${patchIsoDataPath}",
+      "--isolate_snapshot_instructions=${patchIsoInstrPath}",
+      "--shared_data=${baselineIsoDataPath}",
+      "--shared_instructions=${baselineIsoInstrPath}",
+      "--load_compilation_trace=$tracePath",
+      kernelPath,
+    ]);
+    expectOutput("", result5);
+  });
+}
diff --git a/runtime/tests/vm/dart/snapshot_test_helper.dart b/runtime/tests/vm/dart/snapshot_test_helper.dart
index 5c27ced..0a043af 100644
--- a/runtime/tests/vm/dart/snapshot_test_helper.dart
+++ b/runtime/tests/vm/dart/snapshot_test_helper.dart
@@ -41,15 +41,39 @@
   }
 }
 
-Future<Result> runDartBinary(String prefix, List<String> arguments) async {
-  final binary = Platform.executable;
-  final actualArguments = <String>[]
+final String scriptSuffix = Platform.isWindows ? ".bat" : "";
+final String executableSuffix = Platform.isWindows ? ".exe" : "";
+final String buildDir = p.dirname(Platform.executable);
+final String platformDill = p.join(buildDir, "vm_platform_strong.dill");
+final String genSnapshot = p.join(buildDir, "gen_snapshot${executableSuffix}");
+final String genKernel =
+    p.join("pkg", "vm", "tool", "gen_kernel${scriptSuffix}");
+
+Future<Result> runDart(String prefix, List<String> arguments) {
+  final augmentedArguments = <String>[]
     ..addAll(Platform.executableArguments)
     ..addAll(arguments);
-  print("+ $binary " + actualArguments.join(" "));
-  final processResult = await Process.run(binary, actualArguments);
-  final result = new Result(
-      '[$prefix] ${binary} ${actualArguments.join(' ')}', processResult);
+  return runBinary(prefix, Platform.executable, augmentedArguments);
+}
+
+Future<Result> runGenKernel(String prefix, List<String> arguments) {
+  final augmentedArguments = <String>[]
+    ..add("--platform")
+    ..add(platformDill)
+    ..addAll(arguments);
+  return runBinary(prefix, genKernel, augmentedArguments);
+}
+
+Future<Result> runGenSnapshot(String prefix, List<String> arguments) {
+  return runBinary(prefix, genSnapshot, arguments);
+}
+
+Future<Result> runBinary(
+    String prefix, String binary, List<String> arguments) async {
+  print("+ $binary " + arguments.join(" "));
+  final processResult = await Process.run(binary, arguments);
+  final result =
+      new Result('[$prefix] ${binary} ${arguments.join(' ')}', processResult);
 
   if (processResult.stdout.isNotEmpty) {
     print('''
@@ -72,16 +96,23 @@
   return result;
 }
 
-Future<Null> checkDeterministicSnapshot(
-    String snapshotKind, String expectedStdout) async {
-  final Directory temp = Directory.systemTemp.createTempSync();
-  final snapshot1Path = p.join(temp.path, 'snapshot1');
-  final snapshot2Path = p.join(temp.path, 'snapshot2');
-
+withTempDir(Future fun(String dir)) async {
+  final Directory tempDir = Directory.systemTemp.createTempSync();
   try {
+    await fun(tempDir.path);
+  } finally {
+    tempDir.deleteSync(recursive: true);
+  }
+}
+
+checkDeterministicSnapshot(String snapshotKind, String expectedStdout) async {
+  await withTempDir((String temp) async {
+    final snapshot1Path = p.join(temp, 'snapshot1');
+    final snapshot2Path = p.join(temp, 'snapshot2');
+
     print("Version ${Platform.version}");
 
-    final generate1Result = await runDartBinary('GENERATE SNAPSHOT 1', [
+    final generate1Result = await runDart('GENERATE SNAPSHOT 1', [
       '--deterministic',
       '--trace_class_finalization',
       '--trace_type_finalization',
@@ -94,7 +125,7 @@
     ]);
     expectOutput(expectedStdout, generate1Result);
 
-    final generate2Result = await runDartBinary('GENERATE SNAPSHOT 2', [
+    final generate2Result = await runDart('GENERATE SNAPSHOT 2', [
       '--deterministic',
       '--trace_class_finalization',
       '--trace_type_finalization',
@@ -117,42 +148,36 @@
       }
     }
     Expect.equals(snapshot1Bytes.length, snapshot2Bytes.length);
-  } finally {
-    await temp.delete(recursive: true);
-  }
+  });
 }
 
-Future<void> runAppJitTest() async {
-  final Directory temp = Directory.systemTemp.createTempSync();
-  final snapshotPath = p.join(temp.path, 'app.jit');
-  final testPath = Platform.script
-      .toFilePath()
-      .replaceAll(new RegExp(r'_test.dart$'), '_test_body.dart');
+runAppJitTest() async {
+  await withTempDir((String temp) async {
+    final snapshotPath = p.join(temp, 'app.jit');
+    final testPath = Platform.script
+        .toFilePath()
+        .replaceAll(new RegExp(r'_test.dart$'), '_test_body.dart');
 
-  try {
-    final trainingResult = await runDartBinary('TRAINING RUN', [
+    final trainingResult = await runDart('TRAINING RUN', [
       '--snapshot=$snapshotPath',
       '--snapshot-kind=app-jit',
       testPath,
       '--train'
     ]);
     expectOutput("OK(Trained)", trainingResult);
-    final runResult = await runDartBinary('RUN FROM SNAPSHOT', [snapshotPath]);
+    final runResult = await runDart('RUN FROM SNAPSHOT', [snapshotPath]);
     expectOutput("OK(Run)", runResult);
-  } finally {
-    await temp.delete(recursive: true);
-  }
+  });
 }
 
 Future<void> runAppJitBytecodeTest() async {
-  final Directory temp = Directory.systemTemp.createTempSync();
-  final snapshotPath = p.join(temp.path, 'app.jit');
-  final testPath = Platform.script
-      .toFilePath()
-      .replaceAll(new RegExp(r'_test.dart$'), '_test_body.dart');
+  await withTempDir((String temp) async {
+    final snapshotPath = p.join(temp, 'app.jit');
+    final testPath = Platform.script
+        .toFilePath()
+        .replaceAll(new RegExp(r'_test.dart$'), '_test_body.dart');
 
-  try {
-    final trainingResult = await runDartBinary('TRAINING RUN', [
+    final trainingResult = await runDart('TRAINING RUN', [
       '--enable_interpreter',
       '--snapshot=$snapshotPath',
       '--snapshot-kind=app-jit',
@@ -160,10 +185,8 @@
       '--train'
     ]);
     expectOutput("OK(Trained)", trainingResult);
-    final runResult = await runDartBinary(
+    final runResult = await runDart(
         'RUN FROM SNAPSHOT', ['--enable_interpreter', snapshotPath]);
     expectOutput("OK(Run)", runResult);
-  } finally {
-    await temp.delete(recursive: true);
-  }
+  });
 }
diff --git a/runtime/tests/vm/dart/type_feedback_test.dart b/runtime/tests/vm/dart/type_feedback_test.dart
new file mode 100644
index 0000000..6211c70
--- /dev/null
+++ b/runtime/tests/vm/dart/type_feedback_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2019, 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:async";
+import "dart:io";
+
+import "package:path/path.dart" as p;
+
+import "snapshot_test_helper.dart";
+
+int fib(int n) {
+  if (n <= 1) return 1;
+  return fib(n - 1) + fib(n - 2);
+}
+
+Future<void> main(List<String> args) async {
+  if (args.contains("--child")) {
+    print(fib(35));
+    return;
+  }
+
+  if (!Platform.script.toString().endsWith(".dart")) {
+    print("This test must run from source");
+    return;
+  }
+
+  await withTempDir((String tmp) async {
+    final String feedbackPath = p.join(tmp, "type_feedback.bin");
+
+    final result1 = await runDart("generate type feedback", [
+      "--save_type_feedback=$feedbackPath",
+      Platform.script.toFilePath(),
+      "--child",
+    ]);
+    expectOutput("14930352", result1);
+
+    final result2 = await runDart("use type feedback", [
+      "--load_type_feedback=$feedbackPath",
+      Platform.script.toFilePath(),
+      "--child",
+    ]);
+    expectOutput("14930352", result2);
+  });
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index a56a92eb..6554bb2 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -4,6 +4,7 @@
 
 cc/AllocGeneric_Overflow: Crash, Fail # These tests are expected to crash on all platforms.
 cc/ArrayNew_Overflow_Crash: Crash, Fail # These tests are expected to crash on all platforms.
+cc/CodeExecutability: Crash, Fail # These tests are expected to crash on all platforms.
 cc/CodeImmutability: Crash, Fail # These tests are expected to crash on all platforms.
 cc/Dart2JSCompileAll: Fail, Crash # Issue 27369
 cc/Dart2JSCompilerStats: Fail, Crash # Issue 27369
@@ -28,6 +29,7 @@
 dart/appjit_cha_deopt_test: Pass, Slow # Quite slow in debug mode, uses --optimization-counter-threshold=100
 
 [ $builder_tag == asan ]
+cc/CodeExecutability: Fail, OK # Address Sanitizer turns a crash into a failure.
 cc/CodeImmutability: Fail, OK # Address Sanitizer turns a crash into a failure.
 
 [ $builder_tag == optimization_counter_threshold ]
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 194a86c..da9161f 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -211,6 +211,24 @@
   V(TypedData_SetInt32x4, 3)                                                   \
   V(TypedData_GetFloat64x2, 2)                                                 \
   V(TypedData_SetFloat64x2, 3)                                                 \
+  V(TypedDataView_ByteDataView_new, 4)                                         \
+  V(TypedDataView_Int8ArrayView_new, 4)                                        \
+  V(TypedDataView_Uint8ArrayView_new, 4)                                       \
+  V(TypedDataView_Uint8ClampedArrayView_new, 4)                                \
+  V(TypedDataView_Int16ArrayView_new, 4)                                       \
+  V(TypedDataView_Uint16ArrayView_new, 4)                                      \
+  V(TypedDataView_Int32ArrayView_new, 4)                                       \
+  V(TypedDataView_Uint32ArrayView_new, 4)                                      \
+  V(TypedDataView_Int64ArrayView_new, 4)                                       \
+  V(TypedDataView_Uint64ArrayView_new, 4)                                      \
+  V(TypedDataView_Float32ArrayView_new, 4)                                     \
+  V(TypedDataView_Float64ArrayView_new, 4)                                     \
+  V(TypedDataView_Float32x4ArrayView_new, 4)                                   \
+  V(TypedDataView_Int32x4ArrayView_new, 4)                                     \
+  V(TypedDataView_Float64x2ArrayView_new, 4)                                   \
+  V(TypedDataView_length, 1)                                                   \
+  V(TypedDataView_offsetInBytes, 1)                                            \
+  V(TypedDataView_typedData, 1)                                                \
   V(Float32x4_fromDoubles, 5)                                                  \
   V(Float32x4_splat, 2)                                                        \
   V(Float32x4_fromInt32x4Bits, 2)                                              \
diff --git a/runtime/vm/catch_entry_moves_test.cc b/runtime/vm/catch_entry_moves_test.cc
new file mode 100644
index 0000000..faa41f6
--- /dev/null
+++ b/runtime/vm/catch_entry_moves_test.cc
@@ -0,0 +1,198 @@
+// Copyright (c) 2019, 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 <functional>
+#include <utility>
+
+#include "platform/assert.h"
+#include "vm/code_descriptors.h"
+#include "vm/exceptions.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+static CatchEntryMove NewMove(intptr_t src, intptr_t dst) {
+  return CatchEntryMove::FromSlot(CatchEntryMove::SourceKind::kTaggedSlot, src,
+                                  dst);
+}
+const auto kA = NewMove(1, 10);
+const auto kB = NewMove(2, 20);
+const auto kC = NewMove(3, 30);
+const auto kD = NewMove(4, 40);
+const auto kE = NewMove(5, 50);
+const auto kX = NewMove(-1, -10);
+
+const CatchEntryMove abcde[] = {kA, kB, kC, kD, kE};
+const CatchEntryMove abcdx[] = {kA, kB, kC, kD, kX};
+const CatchEntryMove xbcde[] = {kX, kB, kC, kD, kE};
+const CatchEntryMove abxde[] = {kA, kB, kX, kD, kE};
+const CatchEntryMove ab[] = {kA, kB};
+const CatchEntryMove de[] = {kD, kE};
+
+struct TestCaseMoves {
+  const CatchEntryMove* moves;
+  const intptr_t count;
+};
+
+void RunTestCaseWithPermutations(const TestCaseMoves* mapping,
+                                 intptr_t* insert_permutation,
+                                 intptr_t count) {
+  CatchEntryMovesMapBuilder b;
+
+  for (intptr_t i = 0; i < count; ++i) {
+    auto expected_moves = mapping[insert_permutation[i]];
+    b.NewMapping(/*pc_offset=*/insert_permutation[i]);
+    for (intptr_t j = 0; j < expected_moves.count; ++j) {
+      b.Append(expected_moves.moves[j]);
+    }
+    b.EndMapping();
+  }
+
+  const auto& bytes = TypedData::Handle(b.FinalizeCatchEntryMovesMap());
+  CatchEntryMovesMapReader reader(bytes);
+
+  for (intptr_t i = 0; i < count; ++i) {
+    auto expected_moves = mapping[i];
+    auto read_moves = reader.ReadMovesForPcOffset(i);
+    EXPECT_EQ(expected_moves.count, read_moves->count());
+    for (intptr_t j = 0; j < expected_moves.count; ++j) {
+      EXPECT(expected_moves.moves[j] == read_moves->At(j));
+    }
+    free(read_moves);
+  }
+}
+
+void RunTestCase(const TestCaseMoves* mapping, intptr_t count) {
+  std::unique_ptr<intptr_t[]> permutation(new intptr_t[count]);
+  for (intptr_t i = 0; i < count; ++i) {
+    permutation[i] = i;
+  }
+
+  std::function<void(intptr_t)> run_all_permutations = [&](intptr_t offset) {
+    if (offset == count) {
+      RunTestCaseWithPermutations(mapping, &permutation[0], count);
+    } else {
+      for (intptr_t i = offset; i < count; ++i) {
+        const intptr_t start = permutation[offset];
+        const intptr_t replacement = permutation[i];
+
+        permutation[offset] = replacement;
+        permutation[i] = start;
+
+        run_all_permutations(offset + 1);
+
+        permutation[offset] = start;
+        permutation[i] = replacement;
+      }
+    }
+  };
+
+  run_all_permutations(0);
+}
+
+ISOLATE_UNIT_TEST_CASE(CatchEntryMoves) {
+  // Common prefix.
+  const TestCaseMoves test1[] = {
+      TestCaseMoves{
+          abcde,
+          ARRAY_SIZE(abcde),
+      },
+      TestCaseMoves{
+          abcdx,
+          ARRAY_SIZE(abcdx),
+      },
+  };
+  RunTestCase(test1, ARRAY_SIZE(test1));
+
+  // Common suffix.
+  const TestCaseMoves test2[] = {
+      TestCaseMoves{
+          abcde,
+          ARRAY_SIZE(abcde),
+      },
+      TestCaseMoves{
+          xbcde,
+          ARRAY_SIZE(xbcde),
+      },
+  };
+  RunTestCase(test2, ARRAY_SIZE(test2));
+
+  // Common prefix and suffix.
+  const TestCaseMoves test3[] = {
+      TestCaseMoves{
+          abcde,
+          ARRAY_SIZE(abcde),
+      },
+      TestCaseMoves{
+          abxde,
+          ARRAY_SIZE(abxde),
+      },
+  };
+  RunTestCase(test3, ARRAY_SIZE(test3));
+
+  // Subset of suffix.
+  const TestCaseMoves test4[] = {
+      TestCaseMoves{
+          abcde,
+          ARRAY_SIZE(abcde),
+      },
+      TestCaseMoves{
+          de,
+          ARRAY_SIZE(de),
+      },
+  };
+  RunTestCase(test4, ARRAY_SIZE(test4));
+
+  // Subset of prefix.
+  const TestCaseMoves test5[] = {
+      TestCaseMoves{
+          abcde,
+          ARRAY_SIZE(abcde),
+      },
+      TestCaseMoves{
+          ab,
+          ARRAY_SIZE(ab),
+      },
+  };
+  RunTestCase(test5, ARRAY_SIZE(test5));
+
+  // All moves (with duplicates).
+  const TestCaseMoves test6[] = {
+      TestCaseMoves{
+          abcde,
+          ARRAY_SIZE(abcde),
+      },
+      TestCaseMoves{
+          abcde,
+          ARRAY_SIZE(abcde),
+      },
+      TestCaseMoves{
+          abcdx,
+          ARRAY_SIZE(abcdx),
+      },
+      TestCaseMoves{
+          xbcde,
+          ARRAY_SIZE(xbcde),
+      },
+      TestCaseMoves{
+          abxde,
+          ARRAY_SIZE(abxde),
+      },
+      TestCaseMoves{
+          ab,
+          ARRAY_SIZE(ab),
+      },
+      TestCaseMoves{
+          de,
+          ARRAY_SIZE(de),
+      },
+      TestCaseMoves{
+          de,
+          ARRAY_SIZE(de),
+      },
+  };
+  RunTestCase(test6, ARRAY_SIZE(test6));
+}
+
+}  // namespace dart
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index fb88a4c..eb79223 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -1225,6 +1225,12 @@
   sentinel.SetStaticValue(enum_value, true);
   sentinel.RecordStore(enum_value);
 
+  const GrowableObjectArray& pending_unevaluated_const_fields =
+      GrowableObjectArray::Handle(zone,
+                                  thread->isolate()
+                                      ->object_store()
+                                      ->pending_unevaluated_const_fields());
+
   if (enum_cls.kernel_offset() > 0) {
     Error& error = Error::Handle(zone);
     for (intptr_t i = 0; i < fields.Length(); i++) {
@@ -1234,12 +1240,19 @@
         continue;
       }
       // The eager evaluation of the enum values is required for hot-reload (see
-      // commit e3ecc87).
+      // commit e3ecc87). However, while busy loading the constant table, we
+      // need to postpone this evaluation until table is done.
       if (!FLAG_precompiled_mode) {
         if (field.IsUninitialized()) {
-          error = field.EvaluateInitializer();
-          if (!error.IsNull()) {
-            ReportError(error);
+          if (pending_unevaluated_const_fields.IsNull()) {
+            // Evaluate right away.
+            error = field.EvaluateInitializer();
+            if (!error.IsNull()) {
+              ReportError(error);
+            }
+          } else {
+            // Postpone evaluation until we have a constant table.
+            pending_unevaluated_const_fields.Add(field);
           }
         }
       }
@@ -1387,52 +1400,6 @@
   Error& error = Error::Handle(zone);
   TypeParameter& type_param = TypeParameter::Handle(zone);
 
-  // First verify field offsets of all the TypedDataView classes.
-  for (intptr_t cid = kTypedDataInt8ArrayViewCid;
-       cid <= kTypedDataFloat32x4ArrayViewCid; cid++) {
-    cls = class_table.At(cid);  // Get the TypedDataView class.
-    error = cls.EnsureIsFinalized(thread);
-    ASSERT(error.IsNull());
-    cls = cls.SuperClass();  // Get it's super class '_TypedListView'.
-    cls = cls.SuperClass();
-    fields_array ^= cls.fields();
-    ASSERT(fields_array.Length() == TypedDataView::NumberOfFields());
-    field ^= fields_array.At(0);
-    ASSERT(field.Offset() == TypedDataView::data_offset());
-    name ^= field.name();
-    expected_name ^= String::New("_typedData");
-    ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name));
-    field ^= fields_array.At(1);
-    ASSERT(field.Offset() == TypedDataView::offset_in_bytes_offset());
-    name ^= field.name();
-    ASSERT(name.Equals("offsetInBytes"));
-    field ^= fields_array.At(2);
-    ASSERT(field.Offset() == TypedDataView::length_offset());
-    name ^= field.name();
-    ASSERT(name.Equals("length"));
-  }
-
-  // Now verify field offsets of '_ByteDataView' class.
-  cls = class_table.At(kByteDataViewCid);
-  error = cls.EnsureIsFinalized(thread);
-  ASSERT(error.IsNull());
-  fields_array ^= cls.fields();
-  ASSERT(fields_array.Length() == TypedDataView::NumberOfFields());
-  field ^= fields_array.At(0);
-  ASSERT(field.Offset() == TypedDataView::data_offset());
-  name ^= field.name();
-  expected_name ^= String::New("_typedData");
-  ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name));
-  field ^= fields_array.At(1);
-  ASSERT(field.Offset() == TypedDataView::offset_in_bytes_offset());
-  name ^= field.name();
-  expected_name ^= String::New("_offset");
-  ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name));
-  field ^= fields_array.At(2);
-  ASSERT(field.Offset() == TypedDataView::length_offset());
-  name ^= field.name();
-  ASSERT(name.Equals("length"));
-
   // Now verify field offsets of '_ByteBuffer' class.
   cls = class_table.At(kByteBufferCid);
   error = cls.EnsureIsFinalized(thread);
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index ddbd7a0..22cf733 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -66,6 +66,7 @@
   V(Float64x2)                                                                 \
   V(TypedData)                                                                 \
   V(ExternalTypedData)                                                         \
+  V(TypedDataView)                                                             \
   V(Pointer)                                                                   \
   V(DynamicLibrary)                                                            \
   V(Capability)                                                                \
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 97e81e1..972d93e 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -3372,7 +3372,8 @@
       Deserializer::InitializeHeader(
           data, cid_, TypedData::InstanceSize(length_in_bytes), is_canonical);
       data->ptr()->length_ = Smi::New(length);
-      uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data());
+      data->ResetData();
+      uint8_t* cdata = data->ptr()->data();
       d->ReadBytes(cdata, length_in_bytes);
     }
   }
@@ -4251,7 +4252,10 @@
   ASSERT(code != Code::null());
 
   const intptr_t offset = image_writer_->GetTextOffsetFor(instr, code);
-  ASSERT(offset != 0);
+  if (offset == 0) {
+    // Code should have been removed by DropCodeWithoutReusableInstructions.
+    UnexpectedObject(code, "Expected instructions to reuse");
+  }
   Write<int32_t>(offset);
 
   // If offset < 0, it's pointing to a shared instruction. We don't profile
diff --git a/runtime/vm/code_patcher.cc b/runtime/vm/code_patcher.cc
index 4926926..7168231 100644
--- a/runtime/vm/code_patcher.cc
+++ b/runtime/vm/code_patcher.cc
@@ -12,6 +12,13 @@
 
 DEFINE_FLAG(bool, write_protect_code, true, "Write protect jitted code");
 
+#if defined(DUAL_MAPPING_SUPPORTED)
+DEFINE_FLAG(bool, dual_map_code, true, "Dual map jitted code, RW and RX");
+#else
+DEFINE_FLAG(bool, dual_map_code, false, "Dual map jitted code, RW and RX");
+#endif  // defined(DUAL_MAPPING_SUPPORTED)
+
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC)
 WritableInstructionsScope::WritableInstructionsScope(uword address,
                                                      intptr_t size)
     : address_(address), size_(size) {
@@ -27,6 +34,7 @@
                            VirtualMemory::kReadExecute);
   }
 }
+#endif  // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC)
 
 bool MatchesPattern(uword end, const int16_t* pattern, intptr_t size) {
   // When breaking within generated code in GDB, it may overwrite individual
diff --git a/runtime/vm/code_patcher.h b/runtime/vm/code_patcher.h
index 6aa62af..239a69d 100644
--- a/runtime/vm/code_patcher.h
+++ b/runtime/vm/code_patcher.h
@@ -19,10 +19,12 @@
 class RawFunction;
 class RawObject;
 
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC)
 // Stack-allocated class to create a scope where the specified region
 // [address, address + size] has write access enabled. This is used
 // when patching generated code. Access is reset to read-execute in
 // the destructor of this scope.
+// Dual mapping of instructions pages is not supported on these target arch.
 class WritableInstructionsScope : public ValueObject {
  public:
   WritableInstructionsScope(uword address, intptr_t size);
@@ -32,6 +34,7 @@
   const uword address_;
   const intptr_t size_;
 };
+#endif  // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC)
 
 class CodePatcher : public AllStatic {
  public:
diff --git a/runtime/vm/compilation_trace.cc b/runtime/vm/compilation_trace.cc
index 4c4db1e..65791e4 100644
--- a/runtime/vm/compilation_trace.cc
+++ b/runtime/vm/compilation_trace.cc
@@ -302,6 +302,11 @@
   if (function.is_abstract()) {
     return Object::null();
   }
+  // Prevent premature code collection due to major GC during startup.
+  const intptr_t kFakeInitialUsage = 32;
+  if (function.usage_counter() < kFakeInitialUsage) {
+    function.set_usage_counter(kFakeInitialUsage);
+  }
   return Compiler::CompileFunction(thread_, function);
 }
 
@@ -467,6 +472,7 @@
     : thread_(thread),
       zone_(thread->zone()),
       stream_(nullptr),
+      cid_map_(nullptr),
       uri_(String::Handle(zone_)),
       lib_(Library::Handle(zone_)),
       cls_name_(String::Handle(zone_)),
@@ -485,6 +491,10 @@
           GrowableObjectArray::Handle(zone_, GrowableObjectArray::New())),
       error_(Error::Handle(zone_)) {}
 
+TypeFeedbackLoader::~TypeFeedbackLoader() {
+  delete[] cid_map_;
+}
+
 RawObject* TypeFeedbackLoader::LoadFeedback(ReadStream* stream) {
   stream_ = stream;
 
diff --git a/runtime/vm/compilation_trace.h b/runtime/vm/compilation_trace.h
index 106dbbe..699f08c 100644
--- a/runtime/vm/compilation_trace.h
+++ b/runtime/vm/compilation_trace.h
@@ -85,6 +85,7 @@
 class TypeFeedbackLoader : public ValueObject {
  public:
   explicit TypeFeedbackLoader(Thread* thread);
+  ~TypeFeedbackLoader();
 
   RawObject* LoadFeedback(ReadStream* stream);
 
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
index c00607e..cf5264e 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -165,6 +165,8 @@
   __ LoadImmediate(R8, 0);                                                     \
   __ mov(R9, Operand(R8));                                                     \
   __ AddImmediate(R3, R0, target::TypedData::InstanceSize() - 1);              \
+  __ StoreIntoObjectNoBarrier(                                                 \
+      R0, FieldAddress(R0, target::TypedData::data_offset()), R3);             \
   Label init_loop;                                                             \
   __ Bind(&init_loop);                                                         \
   __ AddImmediate(R3, 2 * target::kWordSize);                                  \
@@ -693,13 +695,12 @@
   // R4 = n ~/ _DIGIT_BITS
   __ Asr(R4, R3, Operand(5));
   // R8 = &x_digits[0]
-  __ add(R8, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R8, FieldAddress(R1, target::TypedData::data_offset()));
   // NOTFP = &x_digits[x_used]
   __ add(NOTFP, R8, Operand(R0, LSL, 1));
   // R6 = &r_digits[1]
-  __ add(R6, R2,
-         Operand(target::TypedData::data_offset() - kHeapObjectTag +
-                 kBytesPerBigIntDigit));
+  __ ldr(R6, FieldAddress(R2, target::TypedData::data_offset()));
+  __ add(R6, R6, Operand(kBytesPerBigIntDigit));
   // R6 = &r_digits[x_used + n ~/ _DIGIT_BITS + 1]
   __ add(R4, R4, Operand(R0, ASR, 1));
   __ add(R6, R6, Operand(R4, LSL, 2));
@@ -733,9 +734,9 @@
   // R4 = n ~/ _DIGIT_BITS
   __ Asr(R4, R3, Operand(5));
   // R6 = &r_digits[0]
-  __ add(R6, R2, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R6, FieldAddress(R2, target::TypedData::data_offset()));
   // NOTFP = &x_digits[n ~/ _DIGIT_BITS]
-  __ add(NOTFP, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(NOTFP, FieldAddress(R1, target::TypedData::data_offset()));
   __ add(NOTFP, NOTFP, Operand(R4, LSL, 2));
   // R8 = &r_digits[x_used - n ~/ _DIGIT_BITS - 1]
   __ add(R4, R4, Operand(1));
@@ -773,17 +774,17 @@
   // R0 = used, R1 = digits
   __ ldrd(R0, R1, SP, 3 * target::kWordSize);
   // R1 = &digits[0]
-  __ add(R1, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset()));
 
   // R2 = a_used, R3 = a_digits
   __ ldrd(R2, R3, SP, 1 * target::kWordSize);
   // R3 = &a_digits[0]
-  __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R3, FieldAddress(R3, target::TypedData::data_offset()));
 
   // R8 = r_digits
   __ ldr(R8, Address(SP, 0 * target::kWordSize));
   // R8 = &r_digits[0]
-  __ add(R8, R8, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R8, FieldAddress(R8, target::TypedData::data_offset()));
 
   // NOTFP = &digits[a_used >> 1], a_used is Smi.
   __ add(NOTFP, R1, Operand(R2, LSL, 1));
@@ -833,17 +834,17 @@
   // R0 = used, R1 = digits
   __ ldrd(R0, R1, SP, 3 * target::kWordSize);
   // R1 = &digits[0]
-  __ add(R1, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset()));
 
   // R2 = a_used, R3 = a_digits
   __ ldrd(R2, R3, SP, 1 * target::kWordSize);
   // R3 = &a_digits[0]
-  __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R3, FieldAddress(R3, target::TypedData::data_offset()));
 
   // R8 = r_digits
   __ ldr(R8, Address(SP, 0 * target::kWordSize));
   // R8 = &r_digits[0]
-  __ add(R8, R8, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R8, FieldAddress(R8, target::TypedData::data_offset()));
 
   // NOTFP = &digits[a_used >> 1], a_used is Smi.
   __ add(NOTFP, R1, Operand(R2, LSL, 1));
@@ -912,8 +913,8 @@
   Label done;
   // R3 = x, no_op if x == 0
   __ ldrd(R0, R1, SP, 5 * target::kWordSize);  // R0 = xi as Smi, R1 = x_digits.
-  __ add(R1, R1, Operand(R0, LSL, 1));
   __ ldr(R3, FieldAddress(R1, target::TypedData::data_offset()));
+  __ ldr(R3, Address(R3, R0, LSL, 1));
   __ tst(R3, Operand(R3));
   __ b(&done, EQ);
 
@@ -924,13 +925,13 @@
 
   // R4 = mip = &m_digits[i >> 1]
   __ ldrd(R0, R1, SP, 3 * target::kWordSize);  // R0 = i as Smi, R1 = m_digits.
-  __ add(R1, R1, Operand(R0, LSL, 1));
-  __ add(R4, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R4, FieldAddress(R1, target::TypedData::data_offset()));
+  __ add(R4, R4, Operand(R0, LSL, 1));
 
   // R9 = ajp = &a_digits[j >> 1]
   __ ldrd(R0, R1, SP, 1 * target::kWordSize);  // R0 = j as Smi, R1 = a_digits.
-  __ add(R1, R1, Operand(R0, LSL, 1));
-  __ add(R9, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R9, FieldAddress(R1, target::TypedData::data_offset()));
+  __ add(R9, R9, Operand(R0, LSL, 1));
 
   // R1 = c = 0
   __ mov(R1, Operand(0));
@@ -1012,8 +1013,8 @@
 
   // R4 = xip = &x_digits[i >> 1]
   __ ldrd(R2, R3, SP, 2 * target::kWordSize);  // R2 = i as Smi, R3 = x_digits
-  __ add(R3, R3, Operand(R2, LSL, 1));
-  __ add(R4, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R4, FieldAddress(R3, target::TypedData::data_offset()));
+  __ add(R4, R4, Operand(R2, LSL, 1));
 
   // R3 = x = *xip++, return if x == 0
   Label x_zero;
@@ -1023,8 +1024,8 @@
 
   // NOTFP = ajp = &a_digits[i]
   __ ldr(R1, Address(SP, 1 * target::kWordSize));  // a_digits
-  __ add(R1, R1, Operand(R2, LSL, 2));             // j == 2*i, i is Smi.
-  __ add(NOTFP, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(NOTFP, FieldAddress(R1, target::TypedData::data_offset()));
+  __ add(NOTFP, NOTFP, Operand(R2, LSL, 2));  // j == 2*i, i is Smi.
 
   // R8:R0 = t = x*x + *ajp
   __ ldr(R0, Address(NOTFP, 0));
@@ -1112,24 +1113,24 @@
   //   return 1;
   // }
 
-  // R4 = args
+  // R4 = &args[0]
   __ ldr(R4, Address(SP, 2 * target::kWordSize));  // args
+  __ ldr(R4, FieldAddress(R4, target::TypedData::data_offset()));
 
   // R3 = rho = args[2]
-  __ ldr(R3, FieldAddress(R4, target::TypedData::data_offset() +
-                                  2 * kBytesPerBigIntDigit));
+  __ ldr(R3, Address(R4, 2 * kBytesPerBigIntDigit));
 
   // R2 = digits[i >> 1]
   __ ldrd(R0, R1, SP, 0 * target::kWordSize);  // R0 = i as Smi, R1 = digits
-  __ add(R1, R1, Operand(R0, LSL, 1));
   __ ldr(R2, FieldAddress(R1, target::TypedData::data_offset()));
+  __ add(R2, R2, Operand(R0, LSL, 1));
+  __ ldr(R2, Address(R2));
 
   // R1:R0 = t = rho*d
   __ umull(R0, R1, R2, R3);
 
   // args[4] = t mod DIGIT_BASE = low32(t)
-  __ str(R0, FieldAddress(R4, target::TypedData::data_offset() +
-                                  4 * kBytesPerBigIntDigit));
+  __ str(R0, Address(R4, 4 * kBytesPerBigIntDigit));
 
   __ mov(R0, Operand(target::ToRawSmi(1)));  // One digit processed.
   __ Ret();
@@ -1495,6 +1496,7 @@
   // Field '_state'.
   __ ldr(R1, FieldAddress(R0, LookupFieldOffsetInBytes(state_field)));
   // Addresses of _state[0] and _state[1].
+  __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset()));
 
   const int64_t disp_0 =
       target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
@@ -1502,13 +1504,13 @@
       disp_0 + target::Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
 
   __ LoadImmediate(R0, a_int32_value);
-  __ LoadFromOffset(kWord, R2, R1, disp_0 - kHeapObjectTag);
-  __ LoadFromOffset(kWord, R3, R1, disp_1 - kHeapObjectTag);
+  __ LoadFromOffset(kWord, R2, R1, disp_0);
+  __ LoadFromOffset(kWord, R3, R1, disp_1);
   __ mov(R8, Operand(0));  // Zero extend unsigned _state[kSTATE_HI].
   // Unsigned 32-bit multiply and 64-bit accumulate into R8:R3.
   __ umlal(R3, R8, R0, R2);  // R8:R3 <- R8:R3 + R0 * R2.
-  __ StoreToOffset(kWord, R3, R1, disp_0 - kHeapObjectTag);
-  __ StoreToOffset(kWord, R8, R1, disp_1 - kHeapObjectTag);
+  __ StoreToOffset(kWord, R3, R1, disp_0);
+  __ StoreToOffset(kWord, R8, R1, disp_1);
   ASSERT(target::ToRawSmi(0) == 0);
   __ eor(R0, R0, Operand(R0));
   __ Ret();
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
index 6ba42cd..0153c00 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -177,6 +177,8 @@
   /* data area to be initialized. */                                           \
   __ mov(R3, ZR);                                                              \
   __ AddImmediate(R2, R0, target::TypedData::InstanceSize() - 1);              \
+  __ StoreIntoObjectNoBarrier(                                                 \
+      R0, FieldAddress(R0, target::TypedData::data_offset()), R2);             \
   Label init_loop, done;                                                       \
   __ Bind(&init_loop);                                                         \
   __ cmp(R2, Operand(R1));                                                     \
@@ -601,13 +603,12 @@
   // R0 = n ~/ (2*_DIGIT_BITS)
   __ AsrImmediate(R0, R5, 6);
   // R6 = &x_digits[0]
-  __ add(R6, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R6, FieldAddress(R3, target::TypedData::data_offset()));
   // R7 = &x_digits[2*R2]
   __ add(R7, R6, Operand(R2, LSL, 3));
   // R8 = &r_digits[2*1]
-  __ add(R8, R4,
-         Operand(target::TypedData::data_offset() - kHeapObjectTag +
-                 2 * kBytesPerBigIntDigit));
+  __ ldr(R8, FieldAddress(R4, target::TypedData::data_offset()));
+  __ add(R8, R8, Operand(2 * kBytesPerBigIntDigit));
   // R8 = &r_digits[2*(R2 + n ~/ (2*_DIGIT_BITS) + 1)]
   __ add(R0, R0, Operand(R2));
   __ add(R8, R8, Operand(R0, LSL, 3));
@@ -645,9 +646,9 @@
   // R0 = n ~/ (2*_DIGIT_BITS)
   __ AsrImmediate(R0, R5, 6);
   // R8 = &r_digits[0]
-  __ add(R8, R4, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R8, FieldAddress(R4, target::TypedData::data_offset()));
   // R7 = &x_digits[2*(n ~/ (2*_DIGIT_BITS))]
-  __ add(R7, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R7, FieldAddress(R3, target::TypedData::data_offset()));
   __ add(R7, R7, Operand(R0, LSL, 3));
   // R6 = &r_digits[2*(R2 - n ~/ (2*_DIGIT_BITS) - 1)]
   __ add(R0, R0, Operand(1));
@@ -689,19 +690,19 @@
   __ add(R2, R2, Operand(2));  // used > 0, Smi. R2 = used + 1, round up.
   __ add(R2, ZR, Operand(R2, ASR, 2));  // R2 = num of digit pairs to process.
   // R3 = &digits[0]
-  __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R3, FieldAddress(R3, target::TypedData::data_offset()));
 
   // R4 = a_used, R5 = a_digits
   __ ldp(R4, R5, Address(SP, 1 * target::kWordSize, Address::PairOffset));
   __ add(R4, R4, Operand(2));  // a_used > 0, Smi. R4 = a_used + 1, round up.
   __ add(R4, ZR, Operand(R4, ASR, 2));  // R4 = num of digit pairs to process.
   // R5 = &a_digits[0]
-  __ add(R5, R5, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R5, FieldAddress(R5, target::TypedData::data_offset()));
 
   // R6 = r_digits
   __ ldr(R6, Address(SP, 0 * target::kWordSize));
   // R6 = &r_digits[0]
-  __ add(R6, R6, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R6, FieldAddress(R6, target::TypedData::data_offset()));
 
   // R7 = &digits[a_used rounded up to even number].
   __ add(R7, R3, Operand(R4, LSL, 3));
@@ -755,19 +756,19 @@
   __ add(R2, R2, Operand(2));  // used > 0, Smi. R2 = used + 1, round up.
   __ add(R2, ZR, Operand(R2, ASR, 2));  // R2 = num of digit pairs to process.
   // R3 = &digits[0]
-  __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R3, FieldAddress(R3, target::TypedData::data_offset()));
 
   // R4 = a_used, R5 = a_digits
   __ ldp(R4, R5, Address(SP, 1 * target::kWordSize, Address::PairOffset));
   __ add(R4, R4, Operand(2));  // a_used > 0, Smi. R4 = a_used + 1, round up.
   __ add(R4, ZR, Operand(R4, ASR, 2));  // R4 = num of digit pairs to process.
   // R5 = &a_digits[0]
-  __ add(R5, R5, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R5, FieldAddress(R5, target::TypedData::data_offset()));
 
   // R6 = r_digits
   __ ldr(R6, Address(SP, 0 * target::kWordSize));
   // R6 = &r_digits[0]
-  __ add(R6, R6, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R6, FieldAddress(R6, target::TypedData::data_offset()));
 
   // R7 = &digits[a_used rounded up to even number].
   __ add(R7, R3, Operand(R4, LSL, 3));
@@ -838,8 +839,9 @@
   // R3 = x, no_op if x == 0
   // R0 = xi as Smi, R1 = x_digits.
   __ ldp(R0, R1, Address(SP, 5 * target::kWordSize, Address::PairOffset));
-  __ add(R1, R1, Operand(R0, LSL, 1));
   __ ldr(R3, FieldAddress(R1, target::TypedData::data_offset()));
+  __ add(R3, R3, Operand(R0, LSL, 1));
+  __ ldr(R3, Address(R3, 0));
   __ tst(R3, Operand(R3));
   __ b(&done, EQ);
 
@@ -852,14 +854,14 @@
   // R4 = mip = &m_digits[i >> 1]
   // R0 = i as Smi, R1 = m_digits.
   __ ldp(R0, R1, Address(SP, 3 * target::kWordSize, Address::PairOffset));
-  __ add(R1, R1, Operand(R0, LSL, 1));
-  __ add(R4, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R4, FieldAddress(R1, target::TypedData::data_offset()));
+  __ add(R4, R4, Operand(R0, LSL, 1));
 
   // R5 = ajp = &a_digits[j >> 1]
   // R0 = j as Smi, R1 = a_digits.
   __ ldp(R0, R1, Address(SP, 1 * target::kWordSize, Address::PairOffset));
-  __ add(R1, R1, Operand(R0, LSL, 1));
-  __ add(R5, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R5, FieldAddress(R1, target::TypedData::data_offset()));
+  __ add(R5, R5, Operand(R0, LSL, 1));
 
   // R1 = c = 0
   __ mov(R1, ZR);
@@ -946,8 +948,8 @@
   // R4 = xip = &x_digits[i >> 1]
   // R2 = i as Smi, R3 = x_digits
   __ ldp(R2, R3, Address(SP, 2 * target::kWordSize, Address::PairOffset));
-  __ add(R3, R3, Operand(R2, LSL, 1));
-  __ add(R4, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R4, FieldAddress(R3, target::TypedData::data_offset()));
+  __ add(R4, R4, Operand(R2, LSL, 1));
 
   // R3 = x = *xip++, return if x == 0
   Label x_zero;
@@ -957,8 +959,8 @@
 
   // R5 = ajp = &a_digits[i]
   __ ldr(R1, Address(SP, 1 * target::kWordSize));  // a_digits
-  __ add(R1, R1, Operand(R2, LSL, 2));             // j == 2*i, i is Smi.
-  __ add(R5, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R5, FieldAddress(R1, target::TypedData::data_offset()));
+  __ add(R5, R5, Operand(R2, LSL, 2));  // j == 2*i, i is Smi.
 
   // R6:R1 = t = x*x + *ajp
   __ ldr(R0, Address(R5, 0));
@@ -1076,18 +1078,19 @@
   //   return 2;
   // }
 
-  // R4 = args
+  // R4 = &args[0]
   __ ldr(R4, Address(SP, 2 * target::kWordSize));  // args
+  __ ldr(R4, FieldAddress(R4, target::TypedData::data_offset()));
 
   // R3 = yt = args[0..1]
-  __ ldr(R3, FieldAddress(R4, target::TypedData::data_offset()));
+  __ ldr(R3, Address(R4, 0));
 
   // R2 = dh = digits[(i >> 1) - 1 .. i >> 1]
   // R0 = i as Smi, R1 = digits
   __ ldp(R0, R1, Address(SP, 0 * target::kWordSize, Address::PairOffset));
+  __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset()));
   __ add(R1, R1, Operand(R0, LSL, 1));
-  __ ldr(R2, FieldAddress(
-                 R1, target::TypedData::data_offset() - kBytesPerBigIntDigit));
+  __ ldr(R2, Address(R1, -kBytesPerBigIntDigit));
 
   // R0 = qd = (DIGIT_MASK << 32) | DIGIT_MASK = -1
   __ movn(R0, Immediate(0), 0);
@@ -1098,8 +1101,7 @@
   __ b(&return_qd, EQ);
 
   // R1 = dl = digits[(i >> 1) - 3 .. (i >> 1) - 2]
-  __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset() -
-                                  3 * kBytesPerBigIntDigit));
+  __ ldr(R1, Address(R1, -3 * kBytesPerBigIntDigit));
 
   // R5 = yth = yt >> 32
   __ orr(R5, ZR, Operand(R3, LSR, 32));
@@ -1203,8 +1205,7 @@
 
   __ Bind(&return_qd);
   // args[2..3] = qd
-  __ str(R0, FieldAddress(R4, target::TypedData::data_offset() +
-                                  2 * kBytesPerBigIntDigit));
+  __ str(R0, Address(R4, 2 * kBytesPerBigIntDigit));
 
   __ LoadImmediate(R0, target::ToRawSmi(2));  // Two digits processed.
   __ ret();
@@ -1221,25 +1222,25 @@
   //   return 2;
   // }
 
-  // R4 = args
+  // R4 = &args[0]
   __ ldr(R4, Address(SP, 2 * target::kWordSize));  // args
+  __ ldr(R4, FieldAddress(R4, target::TypedData::data_offset()));
 
   // R3 = rho = args[2..3]
-  __ ldr(R3, FieldAddress(R4, target::TypedData::data_offset() +
-                                  2 * kBytesPerBigIntDigit));
+  __ ldr(R3, Address(R4, 2 * kBytesPerBigIntDigit));
 
   // R2 = digits[i >> 1 .. (i >> 1) + 1]
   // R0 = i as Smi, R1 = digits
   __ ldp(R0, R1, Address(SP, 0 * target::kWordSize, Address::PairOffset));
-  __ add(R1, R1, Operand(R0, LSL, 1));
   __ ldr(R2, FieldAddress(R1, target::TypedData::data_offset()));
+  __ add(R2, R2, Operand(R0, LSL, 1));
+  __ ldr(R2, Address(R2, 0));
 
   // R0 = rho*d mod DIGIT_BASE
   __ mul(R0, R2, R3);  // R0 = low64(R2*R3).
 
   // args[4 .. 5] = R0
-  __ str(R0, FieldAddress(R4, target::TypedData::data_offset() +
-                                  4 * kBytesPerBigIntDigit));
+  __ str(R0, Address(R4, 4 * kBytesPerBigIntDigit));
 
   __ LoadImmediate(R0, target::ToRawSmi(2));  // Two digits processed.
   __ ret();
@@ -1557,10 +1558,10 @@
   // Field '_state'.
   __ ldr(R1, FieldAddress(R0, LookupFieldOffsetInBytes(state_field)));
 
-  // Addresses of _state[0].
+  // Address of _state[0].
+  __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset()));
   const int64_t disp =
-      target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid) -
-      kHeapObjectTag;
+      target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
 
   __ LoadImmediate(R0, a_int_value);
   __ LoadFromOffset(R2, R1, disp);
diff --git a/runtime/vm/compiler/asm_intrinsifier_ia32.cc b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
index 392d129..88c48f9 100644
--- a/runtime/vm/compiler/asm_intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
@@ -167,6 +167,8 @@
   /* data area to be initialized. */                                           \
   __ xorl(ECX, ECX); /* Zero. */                                               \
   __ leal(EDI, FieldAddress(EAX, target::TypedData::InstanceSize()));          \
+  __ StoreIntoObjectNoBarrier(                                                 \
+      EAX, FieldAddress(EAX, target::TypedData::data_offset()), EDI);          \
   Label done, init_loop;                                                       \
   __ Bind(&init_loop);                                                         \
   __ cmpl(EDI, EBX);                                                           \
@@ -713,14 +715,14 @@
   __ movl(EBX, Address(ESP, 2 * target::kWordSize));  // r_digits
   __ movl(ESI, ECX);
   __ sarl(ESI, Immediate(5));  // ESI = n ~/ _DIGIT_BITS.
-  __ leal(EBX,
-          FieldAddress(EBX, ESI, TIMES_4, target::TypedData::data_offset()));
+  __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
+  __ leal(EBX, Address(EBX, ESI, TIMES_4, 0));
   __ movl(ESI, Address(ESP, 4 * target::kWordSize));  // x_used > 0, Smi.
   __ SmiUntag(ESI);
   __ decl(ESI);
   __ xorl(EAX, EAX);  // EAX = 0.
-  __ movl(EDX,
-          FieldAddress(EDI, ESI, TIMES_4, target::TypedData::data_offset()));
+  __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
+  __ movl(EDX, Address(EDI, ESI, TIMES_4, 0));
   __ shldl(EAX, EDX, ECX);
   __ movl(Address(EBX, ESI, TIMES_4, kBytesPerBigIntDigit), EAX);
   Label last;
@@ -729,9 +731,7 @@
   Label loop;
   __ Bind(&loop);
   __ movl(EAX, EDX);
-  __ movl(EDX, FieldAddress(
-                   EDI, ESI, TIMES_4,
-                   target::TypedData::data_offset() - kBytesPerBigIntDigit));
+  __ movl(EDX, Address(EDI, ESI, TIMES_4, -kBytesPerBigIntDigit));
   __ shldl(EAX, EDX, ECX);
   __ movl(Address(EBX, ESI, TIMES_4, 0), EAX);
   __ decl(ESI);
@@ -764,12 +764,12 @@
   __ SmiUntag(ESI);
   __ decl(ESI);
   // EDI = &x_digits[x_used - 1].
-  __ leal(EDI,
-          FieldAddress(EDI, ESI, TIMES_4, target::TypedData::data_offset()));
+  __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
+  __ leal(EDI, Address(EDI, ESI, TIMES_4, 0));
   __ subl(ESI, EDX);
   // EBX = &r_digits[x_used - 1 - (n ~/ 32)].
-  __ leal(EBX,
-          FieldAddress(EBX, ESI, TIMES_4, target::TypedData::data_offset()));
+  __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
+  __ leal(EBX, Address(EBX, ESI, TIMES_4, 0));
   __ negl(ESI);
   __ movl(EDX, Address(EDI, ESI, TIMES_4, 0));
   Label last;
@@ -811,6 +811,10 @@
   __ SmiUntag(ECX);                                   // a_used > 0.
   __ movl(EBX, Address(ESP, 2 * target::kWordSize));  // r_digits
 
+  __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
+  __ movl(ESI, FieldAddress(ESI, target::TypedData::data_offset()));
+  __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
+
   // Precompute 'used - a_used' now so that carry flag is not lost later.
   __ subl(EAX, ECX);
   __ incl(EAX);  // To account for the extra test between loops.
@@ -820,12 +824,9 @@
   Label add_loop;
   __ Bind(&add_loop);
   // Loop a_used times, ECX = a_used, ECX > 0.
-  __ movl(EAX,
-          FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
-  __ adcl(EAX,
-          FieldAddress(ESI, EDX, TIMES_4, target::TypedData::data_offset()));
-  __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
-          EAX);
+  __ movl(EAX, Address(EDI, EDX, TIMES_4, 0));
+  __ adcl(EAX, Address(ESI, EDX, TIMES_4, 0));
+  __ movl(Address(EBX, EDX, TIMES_4, 0), EAX);
   __ incl(EDX);  // Does not affect carry flag.
   __ decl(ECX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &add_loop, Assembler::kNearJump);
@@ -838,11 +839,9 @@
   Label carry_loop;
   __ Bind(&carry_loop);
   // Loop used - a_used times, ECX = used - a_used, ECX > 0.
-  __ movl(EAX,
-          FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
+  __ movl(EAX, Address(EDI, EDX, TIMES_4, 0));
   __ adcl(EAX, Immediate(0));
-  __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
-          EAX);
+  __ movl(Address(EBX, EDX, TIMES_4, 0), EAX);
   __ incl(EDX);  // Does not affect carry flag.
   __ decl(ECX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
@@ -850,8 +849,7 @@
   __ Bind(&last_carry);
   __ movl(EAX, Immediate(0));
   __ adcl(EAX, Immediate(0));
-  __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
-          EAX);
+  __ movl(Address(EBX, EDX, TIMES_4, 0), EAX);
 
   // Restore THR and return.
   __ popl(THR);
@@ -877,6 +875,10 @@
   __ SmiUntag(ECX);                                   // a_used > 0.
   __ movl(EBX, Address(ESP, 2 * target::kWordSize));  // r_digits
 
+  __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
+  __ movl(ESI, FieldAddress(ESI, target::TypedData::data_offset()));
+  __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
+
   // Precompute 'used - a_used' now so that carry flag is not lost later.
   __ subl(EAX, ECX);
   __ incl(EAX);  // To account for the extra test between loops.
@@ -886,12 +888,9 @@
   Label sub_loop;
   __ Bind(&sub_loop);
   // Loop a_used times, ECX = a_used, ECX > 0.
-  __ movl(EAX,
-          FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
-  __ sbbl(EAX,
-          FieldAddress(ESI, EDX, TIMES_4, target::TypedData::data_offset()));
-  __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
-          EAX);
+  __ movl(EAX, Address(EDI, EDX, TIMES_4, 0));
+  __ sbbl(EAX, Address(ESI, EDX, TIMES_4, 0));
+  __ movl(Address(EBX, EDX, TIMES_4, 0), EAX);
   __ incl(EDX);  // Does not affect carry flag.
   __ decl(ECX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &sub_loop, Assembler::kNearJump);
@@ -904,11 +903,9 @@
   Label carry_loop;
   __ Bind(&carry_loop);
   // Loop used - a_used times, ECX = used - a_used, ECX > 0.
-  __ movl(EAX,
-          FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
+  __ movl(EAX, Address(EDI, EDX, TIMES_4, 0));
   __ sbbl(EAX, Immediate(0));
-  __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
-          EAX);
+  __ movl(Address(EBX, EDX, TIMES_4, 0), EAX);
   __ incl(EDX);  // Does not affect carry flag.
   __ decl(ECX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
@@ -953,8 +950,8 @@
   // EBX = x, no_op if x == 0
   __ movl(ECX, Address(ESP, 7 * target::kWordSize));  // x_digits
   __ movl(EAX, Address(ESP, 6 * target::kWordSize));  // xi is Smi
-  __ movl(EBX,
-          FieldAddress(ECX, EAX, TIMES_2, target::TypedData::data_offset()));
+  __ movl(EBX, FieldAddress(ECX, target::TypedData::data_offset()));
+  __ movl(EBX, Address(EBX, EAX, TIMES_2, 0));
   __ testl(EBX, EBX);
   __ j(ZERO, &no_op, Assembler::kNearJump);
 
@@ -970,14 +967,14 @@
   // EDI = mip = &m_digits[i >> 1]
   __ movl(EDI, Address(ESP, 6 * target::kWordSize));  // m_digits
   __ movl(EAX, Address(ESP, 5 * target::kWordSize));  // i is Smi
-  __ leal(EDI,
-          FieldAddress(EDI, EAX, TIMES_2, target::TypedData::data_offset()));
+  __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
+  __ leal(EDI, Address(EDI, EAX, TIMES_2, 0));
 
   // ESI = ajp = &a_digits[j >> 1]
   __ movl(ESI, Address(ESP, 4 * target::kWordSize));  // a_digits
   __ movl(EAX, Address(ESP, 3 * target::kWordSize));  // j is Smi
-  __ leal(ESI,
-          FieldAddress(ESI, EAX, TIMES_2, target::TypedData::data_offset()));
+  __ movl(ESI, FieldAddress(ESI, target::TypedData::data_offset()));
+  __ leal(ESI, Address(ESI, EAX, TIMES_2, 0));
 
   // Save n
   __ pushl(EDX);
@@ -1074,8 +1071,8 @@
   // EDI = xip = &x_digits[i >> 1]
   __ movl(EDI, Address(ESP, 4 * target::kWordSize));  // x_digits
   __ movl(EAX, Address(ESP, 3 * target::kWordSize));  // i is Smi
-  __ leal(EDI,
-          FieldAddress(EDI, EAX, TIMES_2, target::TypedData::data_offset()));
+  __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
+  __ leal(EDI, Address(EDI, EAX, TIMES_2, 0));
 
   // EBX = x = *xip++, return if x == 0
   Label x_zero;
@@ -1090,8 +1087,8 @@
 
   // ESI = ajp = &a_digits[i]
   __ movl(ESI, Address(ESP, 3 * target::kWordSize));  // a_digits
-  __ leal(ESI,
-          FieldAddress(ESI, EAX, TIMES_4, target::TypedData::data_offset()));
+  __ movl(ESI, FieldAddress(ESI, target::TypedData::data_offset()));
+  __ leal(ESI, Address(ESI, EAX, TIMES_4, 0));
 
   // EDX:EAX = t = x*x + *ajp
   __ movl(EAX, EBX);
@@ -1196,18 +1193,18 @@
   //   return 1;
   // }
 
-  // EDI = args
+  // EDI = &args[0]
   __ movl(EDI, Address(ESP, 3 * target::kWordSize));  // args
+  __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
 
   // ECX = yt = args[1]
-  __ movl(ECX, FieldAddress(EDI, target::TypedData::data_offset() +
-                                     kBytesPerBigIntDigit));
+  __ movl(ECX, Address(EDI, kBytesPerBigIntDigit));
 
   // EBX = dp = &digits[i >> 1]
   __ movl(EBX, Address(ESP, 2 * target::kWordSize));  // digits
   __ movl(EAX, Address(ESP, 1 * target::kWordSize));  // i is Smi
-  __ leal(EBX,
-          FieldAddress(EBX, EAX, TIMES_2, target::TypedData::data_offset()));
+  __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
+  __ leal(EBX, Address(EBX, EAX, TIMES_2, 0));
 
   // EDX = dh = dp[0]
   __ movl(EDX, Address(EBX, 0));
@@ -1228,9 +1225,7 @@
 
   __ Bind(&return_qd);
   // args[2] = qd
-  __ movl(FieldAddress(
-              EDI, target::TypedData::data_offset() + 2 * kBytesPerBigIntDigit),
-          EAX);
+  __ movl(Address(EDI, 2 * kBytesPerBigIntDigit), EAX);
 
   __ movl(EAX, Immediate(target::ToRawSmi(1)));  // One digit processed.
   __ ret();
@@ -1247,26 +1242,24 @@
   //   return 1;
   // }
 
-  // EDI = args
+  // EDI = &args[0]
   __ movl(EDI, Address(ESP, 3 * target::kWordSize));  // args
+  __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
 
   // ECX = rho = args[2]
-  __ movl(ECX, FieldAddress(EDI, target::TypedData::data_offset() +
-                                     2 * kBytesPerBigIntDigit));
+  __ movl(ECX, Address(EDI, 2 * kBytesPerBigIntDigit));
 
   // EAX = digits[i >> 1]
   __ movl(EBX, Address(ESP, 2 * target::kWordSize));  // digits
   __ movl(EAX, Address(ESP, 1 * target::kWordSize));  // i is Smi
-  __ movl(EAX,
-          FieldAddress(EBX, EAX, TIMES_2, target::TypedData::data_offset()));
+  __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
+  __ movl(EAX, Address(EBX, EAX, TIMES_2, 0));
 
   // EDX:EAX = t = rho*d
   __ mull(ECX);
 
   // args[4] = t mod DIGIT_BASE = low32(t)
-  __ movl(FieldAddress(
-              EDI, target::TypedData::data_offset() + 4 * kBytesPerBigIntDigit),
-          EAX);
+  __ movl(Address(EDI, 4 * kBytesPerBigIntDigit), EAX);
 
   __ movl(EAX, Immediate(target::ToRawSmi(1)));  // One digit processed.
   __ ret();
@@ -1596,12 +1589,13 @@
   // Field '_state'.
   __ movl(EBX, FieldAddress(EAX, LookupFieldOffsetInBytes(state_field)));
   // Addresses of _state[0] and _state[1].
+  __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
   const intptr_t scale =
       target::Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
   const intptr_t offset =
       target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
-  Address addr_0 = FieldAddress(EBX, 0 * scale + offset);
-  Address addr_1 = FieldAddress(EBX, 1 * scale + offset);
+  Address addr_0 = Address(EBX, 0 * scale + offset);
+  Address addr_1 = Address(EBX, 1 * scale + offset);
   __ movl(EAX, Immediate(a_int32_value));
   // 64-bit multiply EAX * value -> EDX:EAX.
   __ mull(addr_0);
diff --git a/runtime/vm/compiler/asm_intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc
index 1c34df5..1532070 100644
--- a/runtime/vm/compiler/asm_intrinsifier_x64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc
@@ -169,6 +169,8 @@
   /* data area to be initialized. */                                           \
   __ xorq(RBX, RBX); /* Zero. */                                               \
   __ leaq(RDI, FieldAddress(RAX, target::TypedData::InstanceSize()));          \
+  __ StoreIntoObjectNoBarrier(                                                 \
+      RAX, FieldAddress(RAX, target::TypedData::data_offset()), RDI);          \
   Label done, init_loop;                                                       \
   __ Bind(&init_loop);                                                         \
   __ cmpq(RDI, RCX);                                                           \
@@ -684,11 +686,11 @@
   __ movq(RBX, Address(RSP, 1 * target::kWordSize));  // r_digits
   __ movq(RSI, RCX);
   __ sarq(RSI, Immediate(6));  // RSI = n ~/ (2*_DIGIT_BITS).
-  __ leaq(RBX,
-          FieldAddress(RBX, RSI, TIMES_8, target::TypedData::data_offset()));
+  __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
+  __ leaq(RBX, Address(RBX, RSI, TIMES_8, 0));
   __ xorq(RAX, RAX);  // RAX = 0.
-  __ movq(RDX,
-          FieldAddress(RDI, R8, TIMES_8, target::TypedData::data_offset()));
+  __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
+  __ movq(RDX, Address(RDI, R8, TIMES_8, 0));
   __ shldq(RAX, RDX, RCX);
   __ movq(Address(RBX, R8, TIMES_8, 2 * kBytesPerBigIntDigit), RAX);
   Label last;
@@ -697,9 +699,7 @@
   Label loop;
   __ Bind(&loop);
   __ movq(RAX, RDX);
-  __ movq(RDX, FieldAddress(RDI, R8, TIMES_8,
-                            target::TypedData::data_offset() -
-                                2 * kBytesPerBigIntDigit));
+  __ movq(RDX, Address(RDI, R8, TIMES_8, -2 * kBytesPerBigIntDigit));
   __ shldq(RAX, RDX, RCX);
   __ movq(Address(RBX, R8, TIMES_8, 0), RAX);
   __ decq(R8);
@@ -724,11 +724,11 @@
   __ movq(RSI, Address(RSP, 3 * target::kWordSize));  // x_used is Smi
   __ subq(RSI, Immediate(2));  // x_used > 0, Smi. RSI = x_used - 1, round up.
   __ sarq(RSI, Immediate(2));
-  __ leaq(RDI,
-          FieldAddress(RDI, RSI, TIMES_8, target::TypedData::data_offset()));
+  __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
+  __ leaq(RDI, Address(RDI, RSI, TIMES_8, 0));
   __ subq(RSI, RDX);  // RSI + 1 = number of digit pairs to read.
-  __ leaq(RBX,
-          FieldAddress(RBX, RSI, TIMES_8, target::TypedData::data_offset()));
+  __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
+  __ leaq(RBX, Address(RBX, RSI, TIMES_8, 0));
   __ negq(RSI);
   __ movq(RDX, Address(RDI, RSI, TIMES_8, 0));
   Label last;
@@ -765,6 +765,10 @@
   __ sarq(RCX, Immediate(2));  // R8 = number of digit pairs to process.
   __ movq(RBX, Address(RSP, 1 * target::kWordSize));  // r_digits
 
+  __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
+  __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
+  __ movq(RSI, FieldAddress(RSI, target::TypedData::data_offset()));
+
   // Precompute 'used - a_used' now so that carry flag is not lost later.
   __ subq(R8, RCX);
   __ incq(R8);  // To account for the extra test between loops.
@@ -773,12 +777,9 @@
   Label add_loop;
   __ Bind(&add_loop);
   // Loop (a_used+1)/2 times, RCX > 0.
-  __ movq(RAX,
-          FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
-  __ adcq(RAX,
-          FieldAddress(RSI, RDX, TIMES_8, target::TypedData::data_offset()));
-  __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
-          RAX);
+  __ movq(RAX, Address(RDI, RDX, TIMES_8, 0));
+  __ adcq(RAX, Address(RSI, RDX, TIMES_8, 0));
+  __ movq(Address(RBX, RDX, TIMES_8, 0), RAX);
   __ incq(RDX);  // Does not affect carry flag.
   __ decq(RCX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &add_loop, Assembler::kNearJump);
@@ -790,11 +791,9 @@
   Label carry_loop;
   __ Bind(&carry_loop);
   // Loop (used+1)/2 - (a_used+1)/2 times, R8 > 0.
-  __ movq(RAX,
-          FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
+  __ movq(RAX, Address(RDI, RDX, TIMES_8, 0));
   __ adcq(RAX, Immediate(0));
-  __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
-          RAX);
+  __ movq(Address(RBX, RDX, TIMES_8, 0), RAX);
   __ incq(RDX);  // Does not affect carry flag.
   __ decq(R8);   // Does not affect carry flag.
   __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
@@ -802,8 +801,7 @@
   __ Bind(&last_carry);
   Label done;
   __ j(NOT_CARRY, &done);
-  __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
-          Immediate(1));
+  __ movq(Address(RBX, RDX, TIMES_8, 0), Immediate(1));
 
   __ Bind(&done);
   __ LoadObject(RAX, NullObject());
@@ -826,6 +824,10 @@
   __ sarq(RCX, Immediate(2));  // R8 = number of digit pairs to process.
   __ movq(RBX, Address(RSP, 1 * target::kWordSize));  // r_digits
 
+  __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
+  __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
+  __ movq(RSI, FieldAddress(RSI, target::TypedData::data_offset()));
+
   // Precompute 'used - a_used' now so that carry flag is not lost later.
   __ subq(R8, RCX);
   __ incq(R8);  // To account for the extra test between loops.
@@ -834,12 +836,9 @@
   Label sub_loop;
   __ Bind(&sub_loop);
   // Loop (a_used+1)/2 times, RCX > 0.
-  __ movq(RAX,
-          FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
-  __ sbbq(RAX,
-          FieldAddress(RSI, RDX, TIMES_8, target::TypedData::data_offset()));
-  __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
-          RAX);
+  __ movq(RAX, Address(RDI, RDX, TIMES_8, 0));
+  __ sbbq(RAX, Address(RSI, RDX, TIMES_8, 0));
+  __ movq(Address(RBX, RDX, TIMES_8, 0), RAX);
   __ incq(RDX);  // Does not affect carry flag.
   __ decq(RCX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &sub_loop, Assembler::kNearJump);
@@ -851,11 +850,9 @@
   Label carry_loop;
   __ Bind(&carry_loop);
   // Loop (used+1)/2 - (a_used+1)/2 times, R8 > 0.
-  __ movq(RAX,
-          FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
+  __ movq(RAX, Address(RDI, RDX, TIMES_8, 0));
   __ sbbq(RAX, Immediate(0));
-  __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
-          RAX);
+  __ movq(Address(RBX, RDX, TIMES_8, 0), RAX);
   __ incq(RDX);  // Does not affect carry flag.
   __ decq(R8);   // Does not affect carry flag.
   __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
@@ -899,8 +896,8 @@
   // RBX = x, done if x == 0
   __ movq(RCX, Address(RSP, 7 * target::kWordSize));  // x_digits
   __ movq(RAX, Address(RSP, 6 * target::kWordSize));  // xi is Smi
-  __ movq(RBX,
-          FieldAddress(RCX, RAX, TIMES_2, target::TypedData::data_offset()));
+  __ movq(RBX, FieldAddress(RCX, target::TypedData::data_offset()));
+  __ movq(RBX, Address(RBX, RAX, TIMES_2, 0));
   __ testq(RBX, RBX);
   __ j(ZERO, &done, Assembler::kNearJump);
 
@@ -913,14 +910,14 @@
   // RDI = mip = &m_digits[i >> 1]
   __ movq(RDI, Address(RSP, 5 * target::kWordSize));  // m_digits
   __ movq(RAX, Address(RSP, 4 * target::kWordSize));  // i is Smi
-  __ leaq(RDI,
-          FieldAddress(RDI, RAX, TIMES_2, target::TypedData::data_offset()));
+  __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
+  __ leaq(RDI, Address(RDI, RAX, TIMES_2, 0));
 
   // RSI = ajp = &a_digits[j >> 1]
   __ movq(RSI, Address(RSP, 3 * target::kWordSize));  // a_digits
   __ movq(RAX, Address(RSP, 2 * target::kWordSize));  // j is Smi
-  __ leaq(RSI,
-          FieldAddress(RSI, RAX, TIMES_2, target::TypedData::data_offset()));
+  __ movq(RSI, FieldAddress(RSI, target::TypedData::data_offset()));
+  __ leaq(RSI, Address(RSI, RAX, TIMES_2, 0));
 
   // RCX = c = 0
   __ xorq(RCX, RCX);
@@ -1007,8 +1004,8 @@
   // RDI = xip = &x_digits[i >> 1]
   __ movq(RDI, Address(RSP, 4 * target::kWordSize));  // x_digits
   __ movq(RAX, Address(RSP, 3 * target::kWordSize));  // i is Smi
-  __ leaq(RDI,
-          FieldAddress(RDI, RAX, TIMES_2, target::TypedData::data_offset()));
+  __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
+  __ leaq(RDI, Address(RDI, RAX, TIMES_2, 0));
 
   // RBX = x = *xip++, return if x == 0
   Label x_zero;
@@ -1019,8 +1016,8 @@
 
   // RSI = ajp = &a_digits[i]
   __ movq(RSI, Address(RSP, 2 * target::kWordSize));  // a_digits
-  __ leaq(RSI,
-          FieldAddress(RSI, RAX, TIMES_4, target::TypedData::data_offset()));
+  __ movq(RSI, FieldAddress(RSI, target::TypedData::data_offset()));
+  __ leaq(RSI, Address(RSI, RAX, TIMES_4, 0));
 
   // RDX:RAX = t = x*x + *ajp
   __ movq(RAX, RBX);
@@ -1116,18 +1113,18 @@
   //   return 2;
   // }
 
-  // RDI = args
+  // RDI = &args[0]
   __ movq(RDI, Address(RSP, 3 * target::kWordSize));  // args
+  __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
 
   // RCX = yt = args[0..1]
-  __ movq(RCX, FieldAddress(RDI, target::TypedData::data_offset()));
+  __ movq(RCX, Address(RDI, 0));
 
   // RBX = dp = &digits[(i >> 1) - 1]
   __ movq(RBX, Address(RSP, 2 * target::kWordSize));  // digits
   __ movq(RAX, Address(RSP, 1 * target::kWordSize));  // i is Smi and odd.
-  __ leaq(RBX, FieldAddress(
-                   RBX, RAX, TIMES_2,
-                   target::TypedData::data_offset() - kBytesPerBigIntDigit));
+  __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
+  __ leaq(RBX, Address(RBX, RAX, TIMES_2, -kBytesPerBigIntDigit));
 
   // RDX = dh = dp[0]
   __ movq(RDX, Address(RBX, 0));
@@ -1148,9 +1145,7 @@
 
   __ Bind(&return_qd);
   // args[2..3] = qd
-  __ movq(FieldAddress(
-              RDI, target::TypedData::data_offset() + 2 * kBytesPerBigIntDigit),
-          RAX);
+  __ movq(Address(RDI, 2 * kBytesPerBigIntDigit), RAX);
 
   __ movq(RAX, Immediate(target::ToRawSmi(2)));  // Two digits processed.
   __ ret();
@@ -1167,26 +1162,24 @@
   //   return 2;
   // }
 
-  // RDI = args
+  // RDI = &args[0]
   __ movq(RDI, Address(RSP, 3 * target::kWordSize));  // args
+  __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
 
   // RCX = rho = args[2 .. 3]
-  __ movq(RCX, FieldAddress(RDI, target::TypedData::data_offset() +
-                                     2 * kBytesPerBigIntDigit));
+  __ movq(RCX, Address(RDI, 2 * kBytesPerBigIntDigit));
 
   // RAX = digits[i >> 1 .. (i >> 1) + 1]
   __ movq(RBX, Address(RSP, 2 * target::kWordSize));  // digits
   __ movq(RAX, Address(RSP, 1 * target::kWordSize));  // i is Smi
-  __ movq(RAX,
-          FieldAddress(RBX, RAX, TIMES_2, target::TypedData::data_offset()));
+  __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
+  __ movq(RAX, Address(RBX, RAX, TIMES_2, 0));
 
   // RDX:RAX = t = rho*d
   __ mulq(RCX);
 
   // args[4 .. 5] = t mod DIGIT_BASE^2 = low64(t)
-  __ movq(FieldAddress(
-              RDI, target::TypedData::data_offset() + 4 * kBytesPerBigIntDigit),
-          RAX);
+  __ movq(Address(RDI, 4 * kBytesPerBigIntDigit), RAX);
 
   __ movq(RAX, Immediate(target::ToRawSmi(2)));  // Two digits processed.
   __ ret();
@@ -1503,12 +1496,13 @@
   // Field '_state'.
   __ movq(RBX, FieldAddress(RAX, LookupFieldOffsetInBytes(state_field)));
   // Addresses of _state[0] and _state[1].
+  __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
   const intptr_t scale =
       target::Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
   const intptr_t offset =
       target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
-  Address addr_0 = FieldAddress(RBX, 0 * scale + offset);
-  Address addr_1 = FieldAddress(RBX, 1 * scale + offset);
+  Address addr_0 = Address(RBX, 0 * scale + offset);
+  Address addr_1 = Address(RBX, 1 * scale + offset);
   __ movq(RAX, Immediate(a_int_value));
   __ movl(RCX, addr_0);
   __ imulq(RCX, RAX);
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index d441d61..c7b7037 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -3446,7 +3446,9 @@
                                              intptr_t index,
                                              Register temp) {
   const int64_t offset_base =
-      (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+      ((is_external || RawObject::IsTypedDataClassId(cid))
+           ? 0
+           : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
   const int64_t offset =
       offset_base + static_cast<int64_t>(index) * index_scale;
   ASSERT(Utils::IsInt(32, offset));
@@ -3468,7 +3470,9 @@
                                               Register array,
                                               intptr_t index) {
   const int64_t offset_base =
-      (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+      ((is_external || RawObject::IsTypedDataClassId(cid))
+           ? 0
+           : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
   const int64_t offset =
       offset_base + static_cast<int64_t>(index) * index_scale;
   ASSERT(Utils::IsInt(32, offset));
@@ -3483,8 +3487,9 @@
                                              Register index) {
   // Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays.
   const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift;
-  int32_t offset =
-      is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
+  int32_t offset = (is_external || RawObject::IsTypedDataClassId(cid))
+                       ? 0
+                       : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
   const OperandSize size = Address::OperandSizeFor(cid);
   ASSERT(array != IP);
   ASSERT(index != IP);
@@ -3524,8 +3529,9 @@
                                               Register index) {
   // Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays.
   const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift;
-  int32_t offset =
-      is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
+  int32_t offset = (is_external || RawObject::IsTypedDataClassId(cid))
+                       ? 0
+                       : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
   if (shift < 0) {
     ASSERT(shift == -1);
     add(address, array, Operand(index, ASR, 1));
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index b41c7a4..a7eaf8d 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -1566,7 +1566,9 @@
                                              intptr_t index) const {
   const int64_t offset =
       index * index_scale +
-      (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+      ((is_external || RawObject::IsTypedDataClassId(cid))
+           ? 0
+           : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
   ASSERT(Utils::IsInt(32, offset));
   const OperandSize size = Address::OperandSizeFor(cid);
   ASSERT(Address::CanHoldOffset(offset, Address::Offset, size));
@@ -1581,7 +1583,9 @@
                                               intptr_t index) {
   const int64_t offset =
       index * index_scale +
-      (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+      ((is_external || RawObject::IsTypedDataClassId(cid))
+           ? 0
+           : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
   AddImmediate(address, array, offset);
 }
 
@@ -1593,8 +1597,9 @@
                                              Register index) {
   // Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays.
   const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift;
-  const int32_t offset =
-      is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
+  const int32_t offset = (is_external || RawObject::IsTypedDataClassId(cid))
+                             ? 0
+                             : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
   ASSERT(array != TMP);
   ASSERT(index != TMP);
   const Register base = is_load ? TMP : index;
@@ -1620,8 +1625,9 @@
                                               Register index) {
   // Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays.
   const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift;
-  const int32_t offset =
-      is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
+  const int32_t offset = (is_external || RawObject::IsTypedDataClassId(cid))
+                             ? 0
+                             : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
   if (shift == 0) {
     add(address, array, Operand(index));
   } else if (shift < 0) {
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index f1ef6b1..38c3771 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2535,7 +2535,7 @@
                                              Register array,
                                              intptr_t index,
                                              intptr_t extra_disp) {
-  if (is_external) {
+  if (is_external || RawObject::IsTypedDataClassId(cid)) {
     return Address(array, index * index_scale + extra_disp);
   } else {
     const int64_t disp = static_cast<int64_t>(index) * index_scale +
@@ -2573,7 +2573,7 @@
                                              Register array,
                                              Register index,
                                              intptr_t extra_disp) {
-  if (is_external) {
+  if (is_external || RawObject::IsTypedDataClassId(cid)) {
     return Address(array, index, ToScaleFactor(index_scale), extra_disp);
   } else {
     return FieldAddress(array, index, ToScaleFactor(index_scale),
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index af6b564..ebccda6 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -2075,7 +2075,7 @@
                                              intptr_t index_scale,
                                              Register array,
                                              intptr_t index) {
-  if (is_external) {
+  if (is_external || RawObject::IsTypedDataClassId(cid)) {
     return Address(array, index * index_scale);
   } else {
     const int64_t disp = static_cast<int64_t>(index) * index_scale +
@@ -2112,7 +2112,7 @@
                                              intptr_t index_scale,
                                              Register array,
                                              Register index) {
-  if (is_external) {
+  if (is_external || RawObject::IsTypedDataClassId(cid)) {
     return Address(array, index, ToScaleFactor(index_scale), 0);
   } else {
     return FieldAddress(array, index, ToScaleFactor(index_scale),
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index db70602..8f2d56b 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -836,7 +836,7 @@
   //   ....
   //   locals space  <=== RSP
   //   saved PP
-  //   pc (used to derive the RawInstruction Object of the dart code)
+  //   code object (used to derive the RawInstruction Object of the dart code)
   //   saved RBP     <=== RBP
   //   ret PC
   //   .....
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 12b10eb..7eab5b9 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -669,6 +669,10 @@
   SetValue(instr, non_constant_);
 }
 
+void ConstantPropagator::VisitFfiCall(FfiCallInstr* instr) {
+  SetValue(instr, non_constant_);
+}
+
 void ConstantPropagator::VisitDebugStepCheck(DebugStepCheckInstr* instr) {
   // Nothing to do.
 }
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index b6d2fd9..41adc25 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -123,7 +123,8 @@
 
 bool FlowGraph::ShouldReorderBlocks(const Function& function,
                                     bool is_optimized) {
-  return is_optimized && FLAG_reorder_basic_blocks && !function.is_intrinsic();
+  return is_optimized && FLAG_reorder_basic_blocks &&
+         !function.is_intrinsic() && !function.IsFfiTrampoline();
 }
 
 GrowableArray<BlockEntryInstr*>* FlowGraph::CodegenBlockOrder(
@@ -1236,9 +1237,6 @@
     Value* use = it.CurrentValue();
     use->definition()->AddEnvUse(use);
   }
-  if (instr->ComputeCanDeoptimize()) {
-    instr->env()->set_deopt_id(instr->deopt_id());
-  }
 }
 
 void FlowGraph::RenameRecursive(
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 9313103..f36f34f 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -174,14 +174,13 @@
       (SupportsUnboxedDoubles() && (field.guarded_cid() == kDoubleCid)) ||
       (SupportsUnboxedSimd128() && (field.guarded_cid() == kFloat32x4Cid)) ||
       (SupportsUnboxedSimd128() && (field.guarded_cid() == kFloat64x2Cid));
-  return field.is_unboxing_candidate() && !field.is_final() &&
-         !field.is_nullable() && valid_class;
+  return field.is_unboxing_candidate() && !field.is_nullable() && valid_class;
 }
 
 bool FlowGraphCompiler::IsPotentialUnboxedField(const Field& field) {
   return field.is_unboxing_candidate() &&
          (FlowGraphCompiler::IsUnboxedField(field) ||
-          (!field.is_final() && (field.guarded_cid() == kIllegalCid)));
+          (field.guarded_cid() == kIllegalCid));
 }
 
 void FlowGraphCompiler::InitCompiler() {
@@ -1822,6 +1821,7 @@
 
 const Class& FlowGraphCompiler::BoxClassFor(Representation rep) {
   switch (rep) {
+    case kUnboxedFloat:
     case kUnboxedDouble:
       return double_class();
     case kUnboxedFloat32x4:
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 4dbdd20..3d2a546 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -15,6 +15,7 @@
 #include "vm/compiler/backend/locations.h"
 #include "vm/compiler/backend/loops.h"
 #include "vm/compiler/backend/range_analysis.h"
+#include "vm/compiler/ffi.h"
 #include "vm/compiler/frontend/flow_graph_builder.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/compiler/method_recognizer.h"
@@ -1293,14 +1294,12 @@
       flow_graph->zone(), this, call->ArgumentCount(),
       flow_graph->constant_dead(),
       result != NULL ? result : flow_graph->constant_dead());
-  env()->set_deopt_id(deopt_id_);
 }
 
 void Instruction::InheritDeoptTarget(Zone* zone, Instruction* other) {
   ASSERT(other->env() != NULL);
   CopyDeoptIdFrom(*other);
   other->env()->DeepCopyTo(zone, this);
-  env()->set_deopt_id(deopt_id_);
 }
 
 void BranchInstr::InheritDeoptTarget(Zone* zone, Instruction* other) {
@@ -2555,6 +2554,7 @@
   switch (slot().kind()) {
     case Slot::Kind::kArray_length:
     case Slot::Kind::kTypedData_length:
+    case Slot::Kind::kTypedDataView_length:
     case Slot::Kind::kString_length:
       return true;
     case Slot::Kind::kGrowableObjectArray_length:
@@ -2570,6 +2570,8 @@
     case Slot::Kind::kArgumentsDescriptor_positional_count:
     case Slot::Kind::kArgumentsDescriptor_count:
     case Slot::Kind::kTypeArguments:
+    case Slot::Kind::kTypedDataView_offset_in_bytes:
+    case Slot::Kind::kTypedDataView_data:
     case Slot::Kind::kGrowableObjectArray_data:
     case Slot::Kind::kContext_parent:
     case Slot::Kind::kClosure_context:
@@ -2580,6 +2582,7 @@
     case Slot::Kind::kClosure_hash:
     case Slot::Kind::kCapturedVariable:
     case Slot::Kind::kDartField:
+    case Slot::Kind::kPointer_c_memory_address:
       return false;
   }
   UNREACHABLE();
@@ -3474,6 +3477,7 @@
       return new BoxInt64Instr(value);
 
     case kUnboxedDouble:
+    case kUnboxedFloat:
     case kUnboxedFloat32x4:
     case kUnboxedFloat64x2:
     case kUnboxedInt32x4:
@@ -3491,8 +3495,12 @@
                                SpeculativeMode speculative_mode) {
   switch (to) {
     case kUnboxedInt32:
-      return new UnboxInt32Instr(UnboxInt32Instr::kNoTruncation, value,
-                                 deopt_id, speculative_mode);
+      // We must truncate if we can't deoptimize.
+      return new UnboxInt32Instr(
+          speculative_mode == SpeculativeMode::kNotSpeculative
+              ? UnboxInt32Instr::kTruncate
+              : UnboxInt32Instr::kNoTruncation,
+          value, deopt_id, speculative_mode);
 
     case kUnboxedUint32:
       return new UnboxUint32Instr(value, deopt_id, speculative_mode);
@@ -3501,6 +3509,7 @@
       return new UnboxInt64Instr(value, deopt_id, speculative_mode);
 
     case kUnboxedDouble:
+    case kUnboxedFloat:
     case kUnboxedFloat32x4:
     case kUnboxedFloat64x2:
     case kUnboxedInt32x4:
@@ -3729,10 +3738,10 @@
 #endif
   __ Bind(compiler->GetJumpLabel(this));
 
-  // In the AOT compiler we want to reduce code size, so generate no
-  // fall-through code in [FlowGraphCompiler::CompileGraph()].
-  // (As opposed to here where we don't check for the return value of
-  // [Intrinsify]).
+// In the AOT compiler we want to reduce code size, so generate no
+// fall-through code in [FlowGraphCompiler::CompileGraph()].
+// (As opposed to here where we don't check for the return value of
+// [Intrinsify]).
 #if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM)
   if (FLAG_precompiled_mode) {
     const Function& function = compiler->parsed_function().function();
@@ -4633,6 +4642,7 @@
   if (speculative_mode() == kNotSpeculative) {
     switch (representation()) {
       case kUnboxedDouble:
+      case kUnboxedFloat:
         EmitLoadFromBox(compiler);
         break;
 
@@ -4673,9 +4683,8 @@
                                const GrowableArray<Definition*>& definitions,
                                intptr_t fixed_parameter_count,
                                const ParsedFunction& parsed_function) {
-  Environment* env =
-      new (zone) Environment(definitions.length(), fixed_parameter_count,
-                             DeoptId::kNone, parsed_function, NULL);
+  Environment* env = new (zone) Environment(
+      definitions.length(), fixed_parameter_count, parsed_function, NULL);
   for (intptr_t i = 0; i < definitions.length(); ++i) {
     env->values_.Add(new (zone) Value(definitions[i]));
   }
@@ -4688,9 +4697,10 @@
 
 Environment* Environment::DeepCopy(Zone* zone, intptr_t length) const {
   ASSERT(length <= values_.length());
-  Environment* copy = new (zone)
-      Environment(length, fixed_parameter_count_, deopt_id_, parsed_function_,
-                  (outer_ == NULL) ? NULL : outer_->DeepCopy(zone));
+  Environment* copy =
+      new (zone) Environment(length, fixed_parameter_count_, parsed_function_,
+                             (outer_ == NULL) ? NULL : outer_->DeepCopy(zone));
+  copy->deopt_id_ = this->deopt_id_;
   if (locations_ != NULL) {
     Location* new_locations = zone->Alloc<Location>(length);
     copy->set_locations(new_locations);
@@ -4742,12 +4752,15 @@
 
 // Copies the environment as outer on an inlined instruction and updates the
 // environment use lists.
-void Environment::DeepCopyToOuter(Zone* zone, Instruction* instr) const {
+void Environment::DeepCopyToOuter(Zone* zone,
+                                  Instruction* instr,
+                                  intptr_t outer_deopt_id) const {
   // Create a deep copy removing caller arguments from the environment.
   ASSERT(this != NULL);
   ASSERT(instr->env()->outer() == NULL);
   intptr_t argument_count = instr->env()->fixed_parameter_count();
   Environment* copy = DeepCopy(zone, values_.length() - argument_count);
+  copy->deopt_id_ = outer_deopt_id;
   instr->env()->outer_ = copy;
   intptr_t use_index = instr->env()->Length();  // Start index after inner.
   for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
@@ -5179,6 +5192,74 @@
   set_native_c_function(native_function);
 }
 
+#if defined(TARGET_ARCH_X64)
+
+#define Z zone_
+
+Representation FfiCallInstr::RequiredInputRepresentation(intptr_t idx) const {
+  if (idx == TargetAddressIndex()) {
+    return kUnboxedIntPtr;
+  } else {
+    return arg_representations_[idx];
+  }
+}
+
+LocationSummary* FfiCallInstr::MakeLocationSummary(Zone* zone,
+                                                   bool is_optimizing) const {
+  // The temporary register needs to be callee-saved and not an argument
+  // register.
+  ASSERT(((1 << CallingConventions::kFirstCalleeSavedCpuReg) &
+          CallingConventions::kArgumentRegisters) == 0);
+
+  LocationSummary* summary =
+      new (zone) LocationSummary(zone, /*num_inputs=*/InputCount(),
+                                 /*num_temps=*/1, LocationSummary::kCall);
+
+  summary->set_in(TargetAddressIndex(),
+                  Location::RegisterLocation(
+                      CallingConventions::kFirstNonArgumentRegister));
+  summary->set_temp(0, Location::RegisterLocation(
+                           CallingConventions::kSecondNonArgumentRegister));
+  summary->set_out(0, compiler::ffi::ResultLocation(
+                          compiler::ffi::ResultRepresentation(signature_)));
+
+  for (intptr_t i = 0, n = NativeArgCount(); i < n; ++i) {
+    Location target = arg_locations_[i];
+    if (target.IsMachineRegister()) {
+      summary->set_in(i, target);
+    } else {
+      // Since we have to push this input on the stack, there's no point in
+      // pinning it to any specific register.
+      summary->set_in(i, Location::Any());
+    }
+  }
+
+  return summary;
+}
+
+Representation FfiCallInstr::representation() const {
+  return compiler::ffi::ResultRepresentation(signature_);
+}
+
+#undef Z
+
+#else
+
+Representation FfiCallInstr::RequiredInputRepresentation(intptr_t idx) const {
+  UNREACHABLE();
+}
+
+LocationSummary* FfiCallInstr::MakeLocationSummary(Zone* zone,
+                                                   bool is_optimizing) const {
+  UNREACHABLE();
+}
+
+Representation FfiCallInstr::representation() const {
+  UNREACHABLE();
+}
+
+#endif
+
 // SIMD
 
 SimdOpInstr* SimdOpInstr::CreateFromCall(Zone* zone,
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 2d815ae..a16b035 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -11,6 +11,7 @@
 #include "vm/compiler/backend/locations.h"
 #include "vm/compiler/backend/slot.h"
 #include "vm/compiler/compiler_state.h"
+#include "vm/compiler/ffi.h"
 #include "vm/compiler/method_recognizer.h"
 #include "vm/flags.h"
 #include "vm/growable_array.h"
@@ -355,6 +356,7 @@
   M(AssertBoolean, _)                                                          \
   M(SpecialParameter, kNoGC)                                                   \
   M(ClosureCall, _)                                                            \
+  M(FfiCall, _)                                                                \
   M(InstanceCall, _)                                                           \
   M(PolymorphicInstanceCall, _)                                                \
   M(StaticCall, _)                                                             \
@@ -4087,6 +4089,63 @@
   DISALLOW_COPY_AND_ASSIGN(NativeCallInstr);
 };
 
+// Performs a call to native C code. In contrast to NativeCall, the arguments
+// are unboxed and passed through the native calling convention. However, not
+// all dart objects can be passed as arguments. Please see the FFI documentation
+// for more details.
+// TODO(35775): Add link to the documentation when it's written.
+class FfiCallInstr : public Definition {
+ public:
+  FfiCallInstr(Zone* zone,
+               intptr_t deopt_id,
+               const Function& signature,
+               const ZoneGrowableArray<Representation>& arg_reps,
+               const ZoneGrowableArray<Location>& arg_locs)
+      : Definition(deopt_id),
+        zone_(zone),
+        signature_(signature),
+        inputs_(arg_reps.length() + 1),
+        arg_representations_(arg_reps),
+        arg_locations_(arg_locs) {
+    inputs_.FillWith(nullptr, 0, arg_reps.length() + 1);
+    ASSERT(signature.IsZoneHandle());
+  }
+
+  DECLARE_INSTRUCTION(FfiCall)
+
+  // Number of arguments to the native function.
+  intptr_t NativeArgCount() const { return InputCount() - 1; }
+
+  // Input index of the function pointer to invoke.
+  intptr_t TargetAddressIndex() const { return NativeArgCount(); }
+
+  virtual intptr_t InputCount() const { return inputs_.length(); }
+  virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
+  virtual bool MayThrow() const { return false; }
+
+  // FfiCallInstr calls C code, which can call back into Dart.
+  virtual bool ComputeCanDeoptimize() const { return true; }
+
+  virtual bool HasUnknownSideEffects() const { return true; }
+
+  virtual Representation RequiredInputRepresentation(intptr_t idx) const;
+  virtual Representation representation() const;
+
+  PRINT_OPERANDS_TO_SUPPORT
+
+ private:
+  virtual void RawSetInputAt(intptr_t i, Value* value) { inputs_[i] = value; }
+
+  Zone* const zone_;
+  const Function& signature_;
+
+  GrowableArray<Value*> inputs_;
+  const ZoneGrowableArray<Representation>& arg_representations_;
+  const ZoneGrowableArray<Location>& arg_locations_;
+
+  DISALLOW_COPY_AND_ASSIGN(FfiCallInstr);
+};
+
 class DebugStepCheckInstr : public TemplateInstruction<0, NoThrow> {
  public:
   DebugStepCheckInstr(TokenPosition token_pos,
@@ -5362,6 +5421,7 @@
 
   static intptr_t ValueOffset(Representation rep) {
     switch (rep) {
+      case kUnboxedFloat:
       case kUnboxedDouble:
         return Double::value_offset();
 
@@ -5388,6 +5448,7 @@
       case kUnboxedInt64:
         return kMintCid;
       case kUnboxedDouble:
+      case kUnboxedFloat:
         return kDoubleCid;
       case kUnboxedFloat32x4:
         return kFloat32x4Cid;
@@ -6926,6 +6987,7 @@
   DISALLOW_COPY_AND_ASSIGN(FloatToDoubleInstr);
 };
 
+// TODO(sjindel): Replace with FFICallInstr.
 class InvokeMathCFunctionInstr : public PureDefinition {
  public:
   InvokeMathCFunctionInstr(ZoneGrowableArray<Value*>* inputs,
@@ -7786,8 +7848,13 @@
     locations_ = locations;
   }
 
-  void set_deopt_id(intptr_t deopt_id) { deopt_id_ = deopt_id; }
-  intptr_t deopt_id() const { return deopt_id_; }
+  // Get deopt_id associated with this environment.
+  // Note that only outer environments have deopt id associated with
+  // them (set by DeepCopyToOuter).
+  intptr_t deopt_id() const {
+    ASSERT(deopt_id_ != DeoptId::kNone);
+    return deopt_id_;
+  }
 
   Environment* outer() const { return outer_; }
 
@@ -7837,7 +7904,9 @@
   Environment* DeepCopy(Zone* zone) const { return DeepCopy(zone, Length()); }
 
   void DeepCopyTo(Zone* zone, Instruction* instr) const;
-  void DeepCopyToOuter(Zone* zone, Instruction* instr) const;
+  void DeepCopyToOuter(Zone* zone,
+                       Instruction* instr,
+                       intptr_t outer_deopt_id) const;
 
   void DeepCopyAfterTo(Zone* zone,
                        Instruction* instr,
@@ -7870,20 +7939,19 @@
 
   Environment(intptr_t length,
               intptr_t fixed_parameter_count,
-              intptr_t deopt_id,
               const ParsedFunction& parsed_function,
               Environment* outer)
       : values_(length),
-        locations_(NULL),
         fixed_parameter_count_(fixed_parameter_count),
-        deopt_id_(deopt_id),
         parsed_function_(parsed_function),
         outer_(outer) {}
 
   GrowableArray<Value*> values_;
-  Location* locations_;
+  Location* locations_ = nullptr;
   const intptr_t fixed_parameter_count_;
-  intptr_t deopt_id_;
+  // Deoptimization id associated with this environment. Only set for
+  // outer environments.
+  intptr_t deopt_id_ = DeoptId::kNone;
   const ParsedFunction& parsed_function_;
   Environment* outer_;
 
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 033b200..e6766dc 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -982,6 +982,10 @@
   __ Drop(ArgumentCount());  // Drop the arguments.
 }
 
+void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNREACHABLE();
+}
+
 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
@@ -1180,7 +1184,9 @@
   const int64_t index = Smi::Cast(constant->value()).AsInt64Value();
   const intptr_t scale = Instance::ElementSizeFor(cid);
   const intptr_t base_offset =
-      (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+      (is_external || RawObject::IsTypedDataClassId(cid)
+           ? 0
+           : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
   const int64_t offset = index * scale + base_offset;
   if (!Utils::IsAbsoluteUint(12, offset)) {
     return false;
@@ -4048,6 +4054,11 @@
     case kUnboxedDouble:
       __ StoreDToOffset(value, out_reg, ValueOffset() - kHeapObjectTag);
       break;
+    case kUnboxedFloat:
+      __ vcvtds(DTMP, EvenSRegisterOf(value));
+      __ StoreDToOffset(EvenDRegisterOf(FpuTMP), out_reg,
+                        ValueOffset() - kHeapObjectTag);
+      break;
     case kUnboxedFloat32x4:
     case kUnboxedFloat64x2:
     case kUnboxedInt32x4:
@@ -4098,6 +4109,13 @@
       break;
     }
 
+    case kUnboxedFloat: {
+      const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg());
+      __ LoadDFromOffset(result, box, ValueOffset() - kHeapObjectTag);
+      __ vcvtsd(EvenSRegisterOf(result), result);
+      break;
+    }
+
     case kUnboxedFloat32x4:
     case kUnboxedFloat64x2:
     case kUnboxedInt32x4: {
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 64296ab..b10e64d 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -872,6 +872,10 @@
   __ Drop(ArgumentCount());  // Drop the arguments.
 }
 
+void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNREACHABLE();
+}
+
 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
@@ -1060,8 +1064,9 @@
   const int64_t index = Smi::Cast(constant->value()).AsInt64Value();
   const intptr_t scale = Instance::ElementSizeFor(cid);
   const int64_t offset =
-      index * scale +
-      (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+      index * scale + (is_external || RawObject::IsTypedDataClassId(cid)
+                           ? 0
+                           : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
   if (!Utils::IsInt(32, offset)) {
     return false;
   }
@@ -2778,9 +2783,7 @@
   compiler->AddSlowPathCode(slow_path);
 
   __ ldr(TMP, Address(THR, Thread::stack_limit_offset()));
-  // Compare to CSP not SP because CSP is closer to the stack limit. See
-  // Assembler::EnterFrame.
-  __ CompareRegisters(CSP, TMP);
+  __ CompareRegisters(SP, TMP);
   __ b(slow_path->entry_label(), LS);
   if (compiler->CanOSRFunction() && in_loop()) {
     const Register temp = locs()->temp(0).reg();
@@ -3507,6 +3510,10 @@
     case kUnboxedDouble:
       __ StoreDFieldToOffset(value, out_reg, ValueOffset());
       break;
+    case kUnboxedFloat:
+      __ fcvtds(FpuTMP, value);
+      __ StoreDFieldToOffset(FpuTMP, out_reg, ValueOffset());
+      break;
     case kUnboxedFloat32x4:
     case kUnboxedFloat64x2:
     case kUnboxedInt32x4:
@@ -3546,6 +3553,13 @@
       break;
     }
 
+    case kUnboxedFloat: {
+      const VRegister result = locs()->out(0).fpu_reg();
+      __ LoadDFieldFromOffset(result, box, ValueOffset());
+      __ fcvtsd(result, result);
+      break;
+    }
+
     case kUnboxedFloat32x4:
     case kUnboxedFloat64x2:
     case kUnboxedInt32x4: {
diff --git a/runtime/vm/compiler/backend/il_dbc.cc b/runtime/vm/compiler/backend/il_dbc.cc
index 70f8e2b..0ffd8d9 100644
--- a/runtime/vm/compiler/backend/il_dbc.cc
+++ b/runtime/vm/compiler/backend/il_dbc.cc
@@ -958,6 +958,10 @@
   }
 }
 
+void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNREACHABLE();
+}
+
 EMIT_NATIVE_CODE(NativeCall,
                  0,
                  Location::NoLocation(),
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 3f6ee68..1d0b013 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -12,6 +12,7 @@
 #include "vm/compiler/backend/locations.h"
 #include "vm/compiler/backend/locations_helpers.h"
 #include "vm/compiler/backend/range_analysis.h"
+#include "vm/compiler/ffi.h"
 #include "vm/compiler/frontend/flow_graph_builder.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/dart_entry.h"
@@ -844,6 +845,10 @@
   __ Drop(ArgumentCount());  // Drop the arguments.
 }
 
+void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNREACHABLE();
+}
+
 static bool CanBeImmediateIndex(Value* value, intptr_t cid) {
   ConstantInstr* constant = value->definition()->AsConstant();
   if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) {
@@ -3358,6 +3363,10 @@
     case kUnboxedDouble:
       __ movsd(FieldAddress(out_reg, ValueOffset()), value);
       break;
+    case kUnboxedFloat:
+      __ cvtss2sd(FpuTMP, value);
+      __ movsd(FieldAddress(out_reg, ValueOffset()), FpuTMP);
+      break;
     case kUnboxedFloat32x4:
     case kUnboxedFloat64x2:
     case kUnboxedInt32x4:
@@ -3410,6 +3419,13 @@
       break;
     }
 
+    case kUnboxedFloat: {
+      const FpuRegister result = locs()->out(0).fpu_reg();
+      __ movsd(result, FieldAddress(box, ValueOffset()));
+      __ cvtsd2ss(result, result);
+      break;
+    }
+
     case kUnboxedFloat32x4:
     case kUnboxedFloat64x2:
     case kUnboxedInt32x4: {
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index a2a26ea..c6ab009 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -511,6 +511,18 @@
   }
 }
 
+void FfiCallInstr::PrintOperandsTo(BufferFormatter* f) const {
+  f->Print(" pointer=");
+  InputAt(TargetAddressIndex())->PrintTo(f);
+  f->Print(" signature=%s",
+           Type::Handle(signature_.SignatureType()).ToCString());
+  for (intptr_t i = 0, n = InputCount(); i < n - 1; ++i) {
+    f->Print(", ");
+    InputAt(i)->PrintTo(f);
+    f->Print(" (at %s) ", arg_locations_[i].ToCString());
+  }
+}
+
 void InstanceCallInstr::PrintOperandsTo(BufferFormatter* f) const {
   f->Print(" %s<%" Pd ">", function_name().ToCString(), type_args_len());
   for (intptr_t i = 0; i < ArgumentCount(); ++i) {
@@ -910,6 +922,8 @@
       return "untagged";
     case kUnboxedDouble:
       return "double";
+    case kUnboxedFloat:
+      return "float";
     case kUnboxedInt32:
       return "int32";
     case kUnboxedUint32:
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 2c632c8..53c0b02 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -7,11 +7,13 @@
 
 #include "vm/compiler/backend/il.h"
 
+#include "vm/compiler/assembler/assembler.h"
 #include "vm/compiler/backend/flow_graph.h"
 #include "vm/compiler/backend/flow_graph_compiler.h"
 #include "vm/compiler/backend/locations.h"
 #include "vm/compiler/backend/locations_helpers.h"
 #include "vm/compiler/backend/range_analysis.h"
+#include "vm/compiler/ffi.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/dart_entry.h"
 #include "vm/instructions.h"
@@ -877,6 +879,99 @@
   __ Drop(ArgumentCount());  // Drop the arguments.
 }
 
+void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Register saved_fp = locs()->temp(0).reg();
+  Register target_address = locs()->in(TargetAddressIndex()).reg();
+
+  // Save frame pointer because we're going to update it when we enter the exit
+  // frame.
+  __ movq(saved_fp, FPREG);
+
+  // Make a space to put the return address.
+  __ pushq(Immediate(0));
+
+  // We need to create a dummy "exit frame". It will share the same pool pointer
+  // but have a null code object.
+  __ LoadObject(CODE_REG, Object::null_object());
+  __ set_constant_pool_allowed(false);
+  __ EnterDartFrame(
+      compiler::ffi::NumStackArguments(arg_locations_) * kWordSize, PP);
+
+  // Save exit frame information to enable stack walking as we are about to
+  // transition to Dart VM C++ code.
+  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), FPREG);
+
+  // Align frame before entering C++ world.
+  if (OS::ActivationFrameAlignment() > 1) {
+    __ andq(SPREG, Immediate(~(OS::ActivationFrameAlignment() - 1)));
+  }
+
+  for (intptr_t i = 0, n = NativeArgCount(); i < n; ++i) {
+    Location origin = locs()->in(i);
+    Location target = arg_locations_[i];
+
+    if (target.IsStackSlot()) {
+      if (origin.IsRegister()) {
+        __ movq(target.ToStackSlotAddress(), origin.reg());
+      } else if (origin.IsFpuRegister()) {
+        __ movq(TMP, origin.fpu_reg());
+        __ movq(target.ToStackSlotAddress(), TMP);
+      } else if (origin.IsStackSlot() || origin.IsDoubleStackSlot()) {
+        // The base register cannot be SPREG because we've moved it.
+        ASSERT(origin.base_reg() == FPREG);
+        __ movq(TMP, Address(saved_fp, origin.ToStackSlotOffset()));
+        __ movq(target.ToStackSlotAddress(), TMP);
+      }
+    } else {
+      ASSERT(origin.Equals(target));
+    }
+  }
+
+  // Mark that the thread is executing VM code.
+  __ movq(Assembler::VMTagAddress(), target_address);
+
+// We need to copy the return address up into the dummy stack frame so the
+// stack walker will know which safepoint to use.
+#if defined(TARGET_OS_WINDOWS)
+  constexpr intptr_t kCallSequenceLength = 10;
+#else
+  constexpr intptr_t kCallSequenceLength = 6;
+#endif
+
+  // RIP points to the *next* instruction, so 'AddressRIPRelative' loads the
+  // address of the following 'movq'.
+  __ leaq(TMP, Address::AddressRIPRelative(kCallSequenceLength));
+
+  const intptr_t call_sequence_start = __ CodeSize();
+  __ movq(Address(FPREG, kSavedCallerPcSlotFromFp * kWordSize), TMP);
+  __ CallCFunction(target_address);
+
+  ASSERT(__ CodeSize() - call_sequence_start == kCallSequenceLength);
+
+  compiler->EmitCallsiteMetadata(TokenPosition::kNoSource, DeoptId::kNone,
+                                 RawPcDescriptors::Kind::kOther, locs());
+
+  // Mark that the thread is executing Dart code.
+  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
+
+  // Reset exit frame information in Isolate structure.
+  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
+
+  // Although PP is a callee-saved register, it may have been moved by the GC.
+  __ LeaveDartFrame(compiler::kRestoreCallerPP);
+
+  // Restore the global object pool after returning from runtime (old space is
+  // moving, so the GOP could have been relocated).
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+    __ movq(PP, Address(THR, Thread::global_object_pool_offset()));
+  }
+
+  __ set_constant_pool_allowed(true);
+
+  // Instead of returning to the "fake" return address, we just pop it.
+  __ popq(TMP);
+}
+
 static bool CanBeImmediateIndex(Value* index, intptr_t cid) {
   if (!index->definition()->IsConstant()) return false;
   const Object& constant = index->definition()->AsConstant()->value();
@@ -3698,6 +3793,11 @@
     case kUnboxedDouble:
       __ movsd(FieldAddress(out_reg, ValueOffset()), value);
       break;
+    case kUnboxedFloat: {
+      __ cvtss2sd(FpuTMP, value);
+      __ movsd(FieldAddress(out_reg, ValueOffset()), FpuTMP);
+      break;
+    }
     case kUnboxedFloat32x4:
     case kUnboxedFloat64x2:
     case kUnboxedInt32x4:
@@ -3743,6 +3843,13 @@
       break;
     }
 
+    case kUnboxedFloat: {
+      const FpuRegister result = locs()->out(0).fpu_reg();
+      __ movsd(result, FieldAddress(box, ValueOffset()));
+      __ cvtsd2ss(result, result);
+      break;
+    }
+
     case kUnboxedFloat32x4:
     case kUnboxedFloat64x2:
     case kUnboxedInt32x4: {
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index afde064..a81b2cc 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -535,8 +535,11 @@
         if (!function.always_inline() && !function.IsRecognized()) {
           return false;
         }
-        static constexpr intptr_t kAvgListedMethodSize = 20;
-        instruction_count += (inl_size == 0 ? kAvgListedMethodSize : inl_size);
+        if (!function.always_inline()) {
+          static constexpr intptr_t kAvgListedMethodSize = 20;
+          instruction_count +=
+              (inl_size == 0 ? kAvgListedMethodSize : inl_size);
+        }
       }
     }
   }
@@ -2436,9 +2439,11 @@
     // Load from the data from backing store which is a fixed-length array.
     *array = elements;
     array_cid = kArrayCid;
-  } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
-    LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr(
-        new (Z) Value(*array), ExternalTypedData::data_offset());
+  } else if (RawObject::IsTypedDataClassId(array_cid) ||
+             RawObject::IsExternalTypedDataClassId(array_cid)) {
+    ASSERT(TypedData::data_offset() == ExternalTypedData::data_offset());
+    LoadUntaggedInstr* elements = new (Z)
+        LoadUntaggedInstr(new (Z) Value(*array), TypedData::data_offset());
     *cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue);
     *array = elements;
   }
@@ -2853,64 +2858,6 @@
                                  FlowGraph::kValue);
 }
 
-// Emits preparatory code for a typed getter/setter.
-// Handles three cases:
-//   (1) dynamic:  generates a conditional on the receiver cid
-//                 that handles external (load untagged) and
-//                 internal storage at runtime.
-//   (2) external: generates load untagged.
-//   (3) internal: no code required.
-static void PrepareInlineByteArrayBaseOp(FlowGraph* flow_graph,
-                                         Instruction* call,
-                                         Definition* receiver,
-                                         intptr_t array_cid,
-                                         Definition** array,
-                                         Instruction** cursor,
-                                         TargetEntryInstr** block_external,
-                                         TargetEntryInstr** block_internal) {
-  if (array_cid == kDynamicCid) {
-    // Dynamic case:   runtime resolution between external/internal typed data.
-    //                 cid = LoadCid
-    //                 if cid in [ kExternalTypedDataInt8ArrayCid,
-    //                             kExternalTypedDataFloat64x2ArrayCid ]
-    // block_external: LoadUntagged
-    //                 ..
-    //                 else
-    // block_internal: ..
-    //
-    // TODO(ajcbik): as suggested above, subtract + single unsigned test.
-    //
-    LoadClassIdInstr* load_cid =
-        new (Z) LoadClassIdInstr(new (Z) Value(receiver));
-    *cursor = flow_graph->AppendTo(*cursor, load_cid, NULL, FlowGraph::kValue);
-    ConstantInstr* cid_lo = flow_graph->GetConstant(
-        Smi::ZoneHandle(Smi::New(kExternalTypedDataInt8ArrayCid)));
-    RelationalOpInstr* le_lo = new (Z)
-        RelationalOpInstr(call->token_pos(), Token::kLTE, new (Z) Value(cid_lo),
-                          new (Z) Value(load_cid), kSmiCid, call->deopt_id());
-    ConstantInstr* cid_hi = flow_graph->GetConstant(
-        Smi::ZoneHandle(Smi::New(kExternalTypedDataFloat64x2ArrayCid)));
-    RelationalOpInstr* le_hi = new (Z) RelationalOpInstr(
-        call->token_pos(), Token::kLTE, new (Z) Value(load_cid),
-        new (Z) Value(cid_hi), kSmiCid, call->deopt_id());
-    *cursor = flow_graph->NewDiamond(*cursor, call,
-                                     FlowGraph::LogicalAnd(le_lo, le_hi),
-                                     block_external, block_internal);
-    LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr(
-        new (Z) Value(*array), ExternalTypedData::data_offset());
-    flow_graph->InsertAfter(*block_external, elements, NULL, FlowGraph::kValue);
-    *array = elements;  // return load untagged definition in array
-  } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
-    // External typed data: load untagged.
-    LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr(
-        new (Z) Value(*array), ExternalTypedData::data_offset());
-    *cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue);
-    *array = elements;
-  } else {
-    // Internal typed data: no action.
-  }
-}
-
 static LoadIndexedInstr* NewLoad(FlowGraph* flow_graph,
                                  Instruction* call,
                                  Definition* array,
@@ -2962,44 +2909,16 @@
                                        array, &index, &cursor);
   }
 
-  // Generates a template for the load, either a dynamic conditional
-  // that dispatches on external and internal storage, or a single
-  // case that deals with either external or internal storage.
-  TargetEntryInstr* block_external = nullptr;
-  TargetEntryInstr* block_internal = nullptr;
-  PrepareInlineByteArrayBaseOp(flow_graph, call, receiver, array_cid, &array,
-                               &cursor, &block_external, &block_internal);
+  ASSERT(TypedData::data_offset() == ExternalTypedData::data_offset());
+  LoadUntaggedInstr* elements =
+      new (Z) LoadUntaggedInstr(new (Z) Value(array), TypedData::data_offset());
+  cursor = flow_graph->AppendTo(cursor, elements, nullptr, FlowGraph::kValue);
 
-  // Fill out the generated template with loads.
-  if (array_cid == kDynamicCid) {
-    ASSERT(block_external != nullptr && block_internal != nullptr);
-    // Load from external in block_external and internal in block_internal
-    // (resolves (B)). The former loads from "array", which is the returned
-    // load untagged definition. The latter loads from the original "receiver".
-    LoadIndexedInstr* load1 = NewLoad(flow_graph, call, array, index, view_cid);
-    ASSERT(block_external->next() == array);
-    flow_graph->InsertAfter(
-        block_external->next(), load1,
-        call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
-        FlowGraph::kValue);
-    LoadIndexedInstr* load2 =
-        NewLoad(flow_graph, call, receiver, index, view_cid);
-    flow_graph->InsertAfter(
-        block_internal, load2,
-        call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
-        FlowGraph::kValue);
-    // Construct phi of external and internal load.
-    *last = flow_graph->AddPhi(cursor->AsJoinEntry(), load1, load2);
-  } else {
-    ASSERT(block_external == nullptr && block_internal == nullptr);
-    // Load from either external or internal.
-    LoadIndexedInstr* load = NewLoad(flow_graph, call, array, index, view_cid);
-    flow_graph->AppendTo(
-        cursor, load,
-        call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
-        FlowGraph::kValue);
-    cursor = *last = load;
-  }
+  LoadIndexedInstr* load = NewLoad(flow_graph, call, elements, index, view_cid);
+  flow_graph->AppendTo(
+      cursor, load, call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
+      FlowGraph::kValue);
+  cursor = *last = load;
 
   if (view_cid == kTypedDataFloat32ArrayCid) {
     *last = new (Z) FloatToDoubleInstr(new (Z) Value((*last)->AsDefinition()),
@@ -3178,43 +3097,17 @@
                                   FlowGraph::kValue);
   }
 
-  // Generates a template for the store, either a dynamic conditional
-  // that dispatches on external and internal storage, or a single
-  // case that deals with either external or internal storage.
-  TargetEntryInstr* block_external = nullptr;
-  TargetEntryInstr* block_internal = nullptr;
-  PrepareInlineByteArrayBaseOp(flow_graph, call, receiver, array_cid, &array,
-                               &cursor, &block_external, &block_internal);
+  ASSERT(TypedData::data_offset() == ExternalTypedData::data_offset());
+  LoadUntaggedInstr* elements =
+      new (Z) LoadUntaggedInstr(new (Z) Value(array), TypedData::data_offset());
+  cursor = flow_graph->AppendTo(cursor, elements, nullptr, FlowGraph::kValue);
 
-  // Fill out the generated template with stores.
-  if (array_cid == kDynamicCid) {
-    ASSERT(block_external != nullptr && block_internal != nullptr);
-    // Store to external in block_external and internal in block_internal
-    // (resolves (B)). The former stores to "array", which is the returned
-    // load untagged definition. The latter stores to the original "receiver".
-    ASSERT(block_external->next() == array);
-    flow_graph->InsertAfter(
-        block_external->next(),
-        NewStore(flow_graph, call, array, index, stored_value, view_cid),
-        call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
-        FlowGraph::kEffect);
-    flow_graph->InsertAfter(
-        block_internal,
-        NewStore(flow_graph, call, receiver, index, stored_value, view_cid),
-        call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
-        FlowGraph::kEffect);
-    *last = cursor;
-  } else {
-    ASSERT(block_external == nullptr && block_internal == nullptr);
-    // Store on either external or internal.
-    StoreIndexedInstr* store =
-        NewStore(flow_graph, call, array, index, stored_value, view_cid);
-    flow_graph->AppendTo(
-        cursor, store,
-        call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
-        FlowGraph::kEffect);
-    *last = store;
-  }
+  StoreIndexedInstr* store =
+      NewStore(flow_graph, call, elements, index, stored_value, view_cid);
+  flow_graph->AppendTo(
+      cursor, store, call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
+      FlowGraph::kEffect);
+  *last = store;
   // We need a return value to replace uses of the original definition. However,
   // the final instruction is a use of 'void operator[]=()', so we use null.
   *result = flow_graph->constant_null();
diff --git a/runtime/vm/compiler/backend/linearscan.cc b/runtime/vm/compiler/backend/linearscan.cc
index b09079d..23b5189 100644
--- a/runtime/vm/compiler/backend/linearscan.cc
+++ b/runtime/vm/compiler/backend/linearscan.cc
@@ -824,8 +824,9 @@
 static Location::Kind RegisterKindForResult(Instruction* instr) {
   const Representation rep = instr->representation();
 #if !defined(TARGET_ARCH_DBC)
-  if ((rep == kUnboxedDouble) || (rep == kUnboxedFloat32x4) ||
-      (rep == kUnboxedInt32x4) || (rep == kUnboxedFloat64x2)) {
+  if ((rep == kUnboxedFloat) || (rep == kUnboxedDouble) ||
+      (rep == kUnboxedFloat32x4) || (rep == kUnboxedInt32x4) ||
+      (rep == kUnboxedFloat64x2)) {
     return Location::kFpuRegister;
   } else {
     return Location::kRegister;
@@ -1454,7 +1455,7 @@
 #if defined(DEBUG)
     // Verify that temps, inputs and output were specified as fixed
     // locations.  Every register is blocked now so attempt to
-    // allocate will not succeed.
+    // allocate will go on the stack.
     for (intptr_t j = 0; j < locs->temp_count(); j++) {
       ASSERT(!locs->temp(j).IsPairLocation());
       ASSERT(!locs->temp(j).IsUnallocated());
@@ -1463,10 +1464,13 @@
     for (intptr_t j = 0; j < locs->input_count(); j++) {
       if (locs->in(j).IsPairLocation()) {
         PairLocation* pair = locs->in_slot(j)->AsPairLocation();
-        ASSERT(!pair->At(0).IsUnallocated());
-        ASSERT(!pair->At(1).IsUnallocated());
+        ASSERT(!pair->At(0).IsUnallocated() ||
+               locs->in(j).policy() == Location::kAny);
+        ASSERT(!pair->At(1).IsUnallocated() ||
+               locs->in(j).policy() == Location::kAny);
       } else {
-        ASSERT(!locs->in(j).IsUnallocated());
+        ASSERT(!locs->in(j).IsUnallocated() ||
+               locs->in(j).policy() == Location::kAny);
       }
     }
 
@@ -2059,7 +2063,8 @@
       ASSERT(need_quad);
       location = Location::QuadStackSlot(slot_idx);
     } else {
-      ASSERT((range->representation() == kUnboxedDouble));
+      ASSERT(range->representation() == kUnboxedFloat ||
+             range->representation() == kUnboxedDouble);
       location = Location::DoubleStackSlot(slot_idx);
     }
     range->set_spill_slot(location);
diff --git a/runtime/vm/compiler/backend/locations.h b/runtime/vm/compiler/backend/locations.h
index 9c76dd6..d1e6f00 100644
--- a/runtime/vm/compiler/backend/locations.h
+++ b/runtime/vm/compiler/backend/locations.h
@@ -23,6 +23,7 @@
   kTagged,
   kUntagged,
   kUnboxedDouble,
+  kUnboxedFloat,
   kUnboxedInt32,
   kUnboxedUint32,
   kUnboxedInt64,
@@ -33,6 +34,9 @@
   kNumRepresentations
 };
 
+static constexpr Representation kUnboxedIntPtr =
+    compiler::target::kWordSize == 4 ? kUnboxedInt32 : kUnboxedInt64;
+
 // Location objects are used to connect register allocator and code generator.
 // Instruction templates used by code generator have a corresponding
 // LocationSummary object which specifies expected location for every input
@@ -636,7 +640,10 @@
   void set_in(intptr_t index, Location loc) {
     ASSERT(index >= 0);
     ASSERT(index < num_inputs_);
-    ASSERT(!always_calls() || loc.IsMachineRegister());
+    // See FlowGraphAllocator::ProcessOneInstruction for explanation of this
+    // restriction.
+    ASSERT(!always_calls() || loc.IsMachineRegister() ||
+           (loc.IsUnallocated() && loc.policy() == Location::kAny));
     input_locations_[index] = loc;
   }
 
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index e0f096b..755ff5e 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -699,7 +699,6 @@
         last, instr, last->env(),
         instr->IsDefinition() ? FlowGraph::kValue : FlowGraph::kEffect);
     instr->CopyDeoptIdFrom(*last);
-    instr->env()->set_deopt_id(instr->deopt_id_);
 
     map_.Insert(instr);
     emitted_.Add(instr);
@@ -2606,6 +2605,8 @@
       break;
 
     case Slot::Kind::kTypedData_length:
+    case Slot::Kind::kTypedDataView_length:
+    case Slot::Kind::kTypedDataView_offset_in_bytes:
       *range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
       break;
 
@@ -2630,6 +2631,8 @@
     case Slot::Kind::kClosure_function:
     case Slot::Kind::kClosure_function_type_arguments:
     case Slot::Kind::kClosure_instantiator_type_arguments:
+    case Slot::Kind::kPointer_c_memory_address:
+    case Slot::Kind::kTypedDataView_data:
       // Not an integer valued field.
       UNREACHABLE();
       break;
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index f1c01f9..695760d 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -73,6 +73,9 @@
       RawObject::IsTypedDataClassId(array_cid)) {
     return GetNativeSlot(Kind::kTypedData_length);
   }
+  if (RawObject::IsTypedDataViewClassId(array_cid)) {
+    return GetNativeSlot(Kind::kTypedDataView_length);
+  }
 
   switch (array_cid) {
     case kGrowableObjectArrayCid:
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index d448e40..fc82584 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -59,6 +59,9 @@
   V(GrowableObjectArray, length, Smi, VAR)                                     \
   V(GrowableObjectArray, data, Array, VAR)                                     \
   V(TypedData, length, Smi, FINAL)                                             \
+  V(TypedDataView, length, Smi, FINAL)                                         \
+  V(TypedDataView, offset_in_bytes, Smi, FINAL)                                \
+  V(TypedDataView, data, Dynamic, FINAL)                                       \
   V(String, length, Smi, FINAL)                                                \
   V(LinkedHashMap, index, TypedDataUint32Array, VAR)                           \
   V(LinkedHashMap, data, Array, VAR)                                           \
@@ -67,7 +70,8 @@
   V(LinkedHashMap, deleted_keys, Smi, VAR)                                     \
   V(ArgumentsDescriptor, type_args_len, Smi, FINAL)                            \
   V(ArgumentsDescriptor, positional_count, Smi, FINAL)                         \
-  V(ArgumentsDescriptor, count, Smi, FINAL)
+  V(ArgumentsDescriptor, count, Smi, FINAL)                                    \
+  V(Pointer, c_memory_address, Integer, FINAL)
 
 // Slot is an abstraction that describes an readable (and possibly writeable)
 // location within an object.
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index ca5aadb..e3f4f7d 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -505,21 +505,19 @@
 
   Instruction* check_clone = NULL;
   if (check->IsCheckSmi()) {
-    check_clone =
-        new CheckSmiInstr(assert->value()->Copy(zone()),
-                          assert->env()->deopt_id(), check->token_pos());
+    check_clone = new CheckSmiInstr(assert->value()->Copy(zone()),
+                                    assert->deopt_id(), check->token_pos());
     check_clone->AsCheckSmi()->set_licm_hoisted(
         check->AsCheckSmi()->licm_hoisted());
   } else {
     ASSERT(check->IsCheckClass());
-    check_clone = new CheckClassInstr(
-        assert->value()->Copy(zone()), assert->env()->deopt_id(),
-        check->AsCheckClass()->cids(), check->token_pos());
+    check_clone =
+        new CheckClassInstr(assert->value()->Copy(zone()), assert->deopt_id(),
+                            check->AsCheckClass()->cids(), check->token_pos());
     check_clone->AsCheckClass()->set_licm_hoisted(
         check->AsCheckClass()->licm_hoisted());
   }
   ASSERT(check_clone != NULL);
-  ASSERT(assert->deopt_id() == assert->env()->deopt_id());
   check_clone->InsertBefore(assert);
   assert->env()->DeepCopyTo(zone(), check_clone);
 
@@ -987,8 +985,8 @@
   // Parameter is the receiver.
   if ((index() == 0) &&
       (function.IsDynamicFunction() || function.IsGenerativeConstructor())) {
-    LocalScope* scope = graph_entry->parsed_function().node_sequence()->scope();
-    const AbstractType& type = scope->VariableAt(index())->type();
+    const AbstractType& type =
+        graph_entry->parsed_function().ParameterVariable(index())->type();
     if (type.IsObjectType() || type.IsNullType()) {
       // Receiver can be null.
       return CompileType::FromAbstractType(type, CompileType::kNullable);
@@ -1508,6 +1506,7 @@
 
 CompileType UnboxInstr::ComputeType() const {
   switch (representation()) {
+    case kUnboxedFloat:
     case kUnboxedDouble:
       return CompileType::FromCid(kDoubleCid);
 
@@ -1531,6 +1530,7 @@
 
 CompileType BoxInstr::ComputeType() const {
   switch (from_representation()) {
+    case kUnboxedFloat:
     case kUnboxedDouble:
       return CompileType::FromCid(kDoubleCid);
 
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 42e2f9b..51ac37f 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -949,7 +949,7 @@
   }
   // Inline implicit instance setter.
   String& field_name = String::Handle(Z, instr->function_name().raw());
-  if (Function::IsDynamicInvocationForwaderName(field_name)) {
+  if (Function::IsDynamicInvocationForwarderName(field_name)) {
     field_name = Function::DemangleDynamicInvocationForwarderName(field_name);
   }
   field_name = Field::NameFromSetter(field_name);
@@ -1017,14 +1017,10 @@
     // not in strong mode or if at a dynamic invocation.
     bool needs_check = true;
     if (!instr->interface_target().IsNull() && (field.kernel_offset() >= 0)) {
-      bool is_covariant = false;
-      bool is_generic_covariant = false;
-      field.GetCovarianceAttributes(&is_covariant, &is_generic_covariant);
-
-      if (is_covariant) {
+      if (field.is_covariant()) {
         // Always type check covariant fields.
         needs_check = true;
-      } else if (is_generic_covariant) {
+      } else if (field.is_generic_covariant_impl()) {
         // If field is generic covariant then we don't need to check it
         // if the invocation was marked as unchecked (e.g. receiver of
         // the invocation is also the receiver of the surrounding method).
diff --git a/runtime/vm/compiler/ffi.cc b/runtime/vm/compiler/ffi.cc
index e343fc7..375dc5d 100644
--- a/runtime/vm/compiler/ffi.cc
+++ b/runtime/vm/compiler/ffi.cc
@@ -6,6 +6,8 @@
 
 namespace dart {
 
+namespace compiler {
+
 namespace ffi {
 
 #if defined(TARGET_ARCH_X64)
@@ -15,26 +17,22 @@
 static const intptr_t kNumElementSizes = kFfiVoidCid - kFfiPointerCid + 1;
 
 static const size_t element_size_table[kNumElementSizes] = {
-    sizeof(intptr_t),  // kFfiPointerCid
-    kSizeUnknown,      // kFfiNativeFunctionCid
-    1,                 // kFfiInt8Cid
-    2,                 // kFfiInt16Cid
-    4,                 // kFfiInt32Cid
-    8,                 // kFfiInt64Cid
-    1,                 // kFfiUint8Cid
-    2,                 // kFfiUint16Cid
-    4,                 // kFfiUint32Cid
-    8,                 // kFfiUint64Cid
-    sizeof(intptr_t),  // kFfiIntPtrCid
-    4,                 // kFfiFloatCid
-    8,                 // kFfiDoubleCid
-    kSizeUnknown,      // kFfiVoidCid
+    target::kWordSize,  // kFfiPointerCid
+    kSizeUnknown,       // kFfiNativeFunctionCid
+    1,                  // kFfiInt8Cid
+    2,                  // kFfiInt16Cid
+    4,                  // kFfiInt32Cid
+    8,                  // kFfiInt64Cid
+    1,                  // kFfiUint8Cid
+    2,                  // kFfiUint16Cid
+    4,                  // kFfiUint32Cid
+    8,                  // kFfiUint64Cid
+    target::kWordSize,  // kFfiIntPtrCid
+    4,                  // kFfiFloatCid
+    8,                  // kFfiDoubleCid
+    kSizeUnknown,       // kFfiVoidCid
 };
 
-Representation WordRep() {
-  return compiler::target::kWordSize > 4 ? kUnboxedInt64 : kUnboxedInt32;
-}
-
 size_t ElementSizeInBytes(intptr_t class_id) {
   ASSERT(class_id != kFfiNativeFunctionCid);
   ASSERT(class_id != kFfiVoidCid);
@@ -46,45 +44,52 @@
   return element_size_table[index];
 }
 
-bool ElementIsSigned(intptr_t class_id) {
-  switch (class_id) {
-    case kFfiFloatCid:
-    case kFfiDoubleCid:
-    case kFfiInt8Cid:
-    case kFfiInt16Cid:
-    case kFfiInt32Cid:
-    case kFfiInt64Cid:
-    case kFfiIntPtrCid:
-      return true;
-    case kFfiUint8Cid:
-    case kFfiUint16Cid:
-    case kFfiUint32Cid:
-    case kFfiUint64Cid:
-    case kFfiPointerCid:
-    default:  // Subtypes of Pointer.
-      return false;
-  }
-}
-
 Representation TypeRepresentation(const AbstractType& result_type) {
   switch (result_type.type_class_id()) {
     case kFfiFloatCid:
+      return kUnboxedFloat;
     case kFfiDoubleCid:
       return kUnboxedDouble;
     case kFfiInt8Cid:
     case kFfiInt16Cid:
     case kFfiInt32Cid:
+      return kUnboxedInt32;
     case kFfiUint8Cid:
     case kFfiUint16Cid:
     case kFfiUint32Cid:
-      return kUnboxedInt32;
+      return kUnboxedUint32;
     case kFfiInt64Cid:
     case kFfiUint64Cid:
       return kUnboxedInt64;
     case kFfiIntPtrCid:
     case kFfiPointerCid:
     default:  // Subtypes of Pointer.
-      return WordRep();
+      return kUnboxedIntPtr;
+  }
+}
+
+bool NativeTypeIsVoid(const AbstractType& result_type) {
+  return result_type.type_class_id() == kFfiVoidCid;
+}
+
+bool NativeTypeIsPointer(const AbstractType& result_type) {
+  switch (result_type.type_class_id()) {
+    case kFfiVoidCid:
+    case kFfiFloatCid:
+    case kFfiDoubleCid:
+    case kFfiInt8Cid:
+    case kFfiInt16Cid:
+    case kFfiInt32Cid:
+    case kFfiUint8Cid:
+    case kFfiUint16Cid:
+    case kFfiUint32Cid:
+    case kFfiInt64Cid:
+    case kFfiUint64Cid:
+    case kFfiIntPtrCid:
+      return false;
+    case kFfiPointerCid:
+    default:
+      return true;
   }
 }
 
@@ -120,6 +125,7 @@
     on_stack = true;
     switch (arg_reps.At(i)) {
       case kUnboxedInt32:
+      case kUnboxedUint32:
       case kUnboxedInt64:
         if (regs_used < CallingConventions::kNumArgRegs) {
           data[i] = Location::RegisterLocation(
@@ -131,6 +137,7 @@
           on_stack = false;
         }
         break;
+      case kUnboxedFloat:
       case kUnboxedDouble:
         if (xmm_regs_used < CallingConventions::kNumXmmArgRegs) {
           data[i] = Location::FpuRegisterLocation(
@@ -146,7 +153,6 @@
         UNREACHABLE();
     }
     if (on_stack) {
-      // SAMIR_TODO: Is this correct?
       data[i] = Location::StackSlot(nth_stack_argument, RSP);
       nth_stack_argument++;
     }
@@ -154,6 +160,36 @@
   return result;
 }
 
+Representation ResultRepresentation(const Function& signature) {
+  AbstractType& arg_type = AbstractType::Handle(signature.result_type());
+  return TypeRepresentation(arg_type);
+}
+
+Location ResultLocation(Representation result_rep) {
+  switch (result_rep) {
+    case kUnboxedInt32:
+    case kUnboxedUint32:
+    case kUnboxedInt64:
+      return Location::RegisterLocation(CallingConventions::kReturnReg);
+    case kUnboxedFloat:
+    case kUnboxedDouble:
+      return Location::FpuRegisterLocation(CallingConventions::kReturnFpuReg);
+    default:
+      UNREACHABLE();
+  }
+}
+
+intptr_t NumStackArguments(const ZoneGrowableArray<Location>& locations) {
+  intptr_t num_arguments = locations.length();
+  intptr_t num_stack_arguments = 0;
+  for (intptr_t i = 0; i < num_arguments; i++) {
+    if (locations.At(i).IsStackSlot()) {
+      num_stack_arguments++;
+    }
+  }
+  return num_stack_arguments;
+}
+
 #else
 
 size_t ElementSizeInBytes(intptr_t class_id) {
@@ -164,4 +200,6 @@
 
 }  // namespace ffi
 
+}  // namespace compiler
+
 }  // namespace dart
diff --git a/runtime/vm/compiler/ffi.h b/runtime/vm/compiler/ffi.h
index b66818b..e3eca6f 100644
--- a/runtime/vm/compiler/ffi.h
+++ b/runtime/vm/compiler/ffi.h
@@ -14,26 +14,43 @@
 
 namespace dart {
 
+namespace compiler {
+
 namespace ffi {
 
-// Native data types sizes in bytes
-
+// Storage size for an FFI type (extends 'ffi.NativeType').
 size_t ElementSizeInBytes(intptr_t class_id);
 
-bool ElementIsSigned(intptr_t class_id);
-
+// Unboxed representation of an FFI type (extends 'ffi.NativeType').
 Representation TypeRepresentation(const AbstractType& result_type);
 
-Representation WordRep();
+// Whether a type which extends 'ffi.NativeType' also extends 'ffi.Pointer'.
+bool NativeTypeIsPointer(const AbstractType& result_type);
 
+// Whether a type is 'ffi.Void'.
+bool NativeTypeIsVoid(const AbstractType& result_type);
+
+// Unboxed representation of the result of a C signature function.
+Representation ResultRepresentation(const Function& signature);
+
+// Location for the result of a C signature function.
+Location ResultLocation(Representation result_rep);
+
+// Unboxed representations of the arguments to a C signature function.
 ZoneGrowableArray<Representation>* ArgumentRepresentations(
     const Function& signature);
 
+// Location for the arguments of a C signature function.
 ZoneGrowableArray<Location>* ArgumentLocations(
     const ZoneGrowableArray<Representation>& arg_reps);
 
+// Number of stack slots used in 'locations'.
+intptr_t NumStackArguments(const ZoneGrowableArray<Location>& locations);
+
 }  // namespace ffi
 
+}  // namespace compiler
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_COMPILER_FFI_H_
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index 83fe857..d134dc1 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -284,8 +284,7 @@
 Fragment BaseFlowGraphBuilder::TestAnyTypeArgs(Fragment present,
                                                Fragment absent) {
   if (parsed_function_->function().IsClosureFunction()) {
-    LocalVariable* closure =
-        parsed_function_->node_sequence()->scope()->VariableAt(0);
+    LocalVariable* closure = parsed_function_->ParameterVariable(0);
 
     JoinEntryInstr* complete = BuildJoinEntry();
     JoinEntryInstr* present_entry = BuildJoinEntry();
@@ -703,6 +702,12 @@
   return Fragment(instr);
 }
 
+Fragment BaseFlowGraphBuilder::LoadClassId() {
+  LoadClassIdInstr* load = new (Z) LoadClassIdInstr(Pop());
+  Push(load);
+  return Fragment(load);
+}
+
 }  // namespace kernel
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
index 69ff503..fa4ff07 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
@@ -265,6 +265,7 @@
   Fragment CreateArray();
   Fragment InstantiateType(const AbstractType& type);
   Fragment InstantiateTypeArguments(const TypeArguments& type_arguments);
+  Fragment LoadClassId();
 
   // Returns true if we are building a graph for inlining of a call site that
   // enters the function through the unchecked entry.
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
index 3853076..f5f3c3a 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
@@ -809,8 +809,193 @@
     UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
   }
 
-  // Default flow graph builder is used to compile native methods.
-  UNREACHABLE();
+  ASSERT(function().is_native());
+
+  // TODO(alexmarkov): find a way to avoid code duplication with
+  // FlowGraphBuilder::NativeFunctionBody.
+  const MethodRecognizer::Kind kind =
+      MethodRecognizer::RecognizeKind(function());
+  switch (kind) {
+    case MethodRecognizer::kObjectEquals:
+      ASSERT((function().NumParameters() == 2) && !function().IsGeneric());
+      code_ += B->StrictCompare(Token::kEQ_STRICT);
+      break;
+    case MethodRecognizer::kStringBaseLength:
+    case MethodRecognizer::kStringBaseIsEmpty:
+      ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+      code_ += B->LoadNativeField(Slot::String_length());
+      if (kind == MethodRecognizer::kStringBaseIsEmpty) {
+        code_ += B->IntConstant(0);
+        code_ += B->StrictCompare(Token::kEQ_STRICT);
+      }
+      break;
+    case MethodRecognizer::kGrowableArrayLength:
+      ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+      code_ += B->LoadNativeField(Slot::GrowableObjectArray_length());
+      break;
+    case MethodRecognizer::kObjectArrayLength:
+    case MethodRecognizer::kImmutableArrayLength:
+      ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+      code_ += B->LoadNativeField(Slot::Array_length());
+      break;
+    case MethodRecognizer::kTypedDataLength:
+      ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+      code_ += B->LoadNativeField(Slot::TypedData_length());
+      break;
+    case MethodRecognizer::kClassIDgetID:
+      ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+      code_ += B->LoadClassId();
+      break;
+    case MethodRecognizer::kGrowableArrayCapacity:
+      ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+      code_ += B->LoadNativeField(Slot::GrowableObjectArray_data());
+      code_ += B->LoadNativeField(Slot::Array_length());
+      break;
+    case MethodRecognizer::kListFactory: {
+      ASSERT((function().NumParameters() == 2) && !function().IsGeneric() &&
+             function().HasOptionalParameters());
+      ASSERT(scratch_var_ != nullptr);
+      // Generate code that performs:
+      //
+      // factory List<E>([int length]) {
+      //   return (:arg_desc.positional_count == 2) ? new _List<E>(length)
+      //                                            : new _GrowableList<E>(0);
+      // }
+      const auto& core_lib = Library::Handle(Z, Library::CoreLibrary());
+
+      TargetEntryInstr *allocate_non_growable, *allocate_growable;
+
+      code_ += B->Drop();  // Drop 'length'.
+      code_ += B->Drop();  // Drop 'type arguments'.
+      code_ += B->LoadArgDescriptor();
+      code_ += B->LoadNativeField(Slot::ArgumentsDescriptor_positional_count());
+      code_ += B->IntConstant(2);
+      code_ +=
+          B->BranchIfStrictEqual(&allocate_non_growable, &allocate_growable);
+
+      JoinEntryInstr* join = B->BuildJoinEntry();
+
+      {
+        const auto& cls = Class::Handle(
+            Z, core_lib.LookupClass(
+                   Library::PrivateCoreLibName(Symbols::_List())));
+        ASSERT(!cls.IsNull());
+        const auto& func = Function::ZoneHandle(
+            Z, cls.LookupFactoryAllowPrivate(Symbols::_ListFactory()));
+        ASSERT(!func.IsNull());
+
+        code_ = Fragment(allocate_non_growable);
+        code_ += B->LoadLocal(LocalVariableAt(0));
+        code_ += B->LoadLocal(LocalVariableAt(1));
+        auto* call = new (Z) StaticCallInstr(
+            TokenPosition::kNoSource, func, 0, Array::null_array(),
+            GetArguments(2), *ic_data_array_, B->GetNextDeoptId(),
+            ICData::kStatic);
+        code_ <<= call;
+        B->Push(call);
+        code_ += B->StoreLocal(TokenPosition::kNoSource, scratch_var_);
+        code_ += B->Drop();
+        code_ += B->Goto(join);
+      }
+
+      {
+        const auto& cls = Class::Handle(
+            Z, core_lib.LookupClass(
+                   Library::PrivateCoreLibName(Symbols::_GrowableList())));
+        ASSERT(!cls.IsNull());
+        const auto& func = Function::ZoneHandle(
+            Z, cls.LookupFactoryAllowPrivate(Symbols::_GrowableListFactory()));
+        ASSERT(!func.IsNull());
+
+        code_ = Fragment(allocate_growable);
+        code_ += B->LoadLocal(LocalVariableAt(0));
+        code_ += B->IntConstant(0);
+        auto* call = new (Z) StaticCallInstr(
+            TokenPosition::kNoSource, func, 0, Array::null_array(),
+            GetArguments(2), *ic_data_array_, B->GetNextDeoptId(),
+            ICData::kStatic);
+        code_ <<= call;
+        B->Push(call);
+        code_ += B->StoreLocal(TokenPosition::kNoSource, scratch_var_);
+        code_ += B->Drop();
+        code_ += B->Goto(join);
+      }
+
+      code_ = Fragment(join);
+      code_ += B->LoadLocal(scratch_var_);
+      break;
+    }
+    case MethodRecognizer::kObjectArrayAllocate:
+      ASSERT((function().NumParameters() == 2) && !function().IsGeneric());
+      code_ += B->CreateArray();
+      break;
+    case MethodRecognizer::kLinkedHashMap_getIndex:
+      ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+      code_ += B->LoadNativeField(Slot::LinkedHashMap_index());
+      break;
+    case MethodRecognizer::kLinkedHashMap_setIndex:
+      ASSERT((function().NumParameters() == 2) && !function().IsGeneric());
+      code_ += B->StoreInstanceField(TokenPosition::kNoSource,
+                                     Slot::LinkedHashMap_index());
+      code_ += B->NullConstant();
+      break;
+    case MethodRecognizer::kLinkedHashMap_getData:
+      ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+      code_ += B->LoadNativeField(Slot::LinkedHashMap_data());
+      break;
+    case MethodRecognizer::kLinkedHashMap_setData:
+      ASSERT((function().NumParameters() == 2) && !function().IsGeneric());
+      code_ += B->StoreInstanceField(TokenPosition::kNoSource,
+                                     Slot::LinkedHashMap_data());
+      code_ += B->NullConstant();
+      break;
+    case MethodRecognizer::kLinkedHashMap_getHashMask:
+      ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+      code_ += B->LoadNativeField(Slot::LinkedHashMap_hash_mask());
+      break;
+    case MethodRecognizer::kLinkedHashMap_setHashMask:
+      ASSERT((function().NumParameters() == 2) && !function().IsGeneric());
+      code_ += B->StoreInstanceField(TokenPosition::kNoSource,
+                                     Slot::LinkedHashMap_hash_mask(),
+                                     kNoStoreBarrier);
+      code_ += B->NullConstant();
+      break;
+    case MethodRecognizer::kLinkedHashMap_getUsedData:
+      ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+      code_ += B->LoadNativeField(Slot::LinkedHashMap_used_data());
+      break;
+    case MethodRecognizer::kLinkedHashMap_setUsedData:
+      ASSERT((function().NumParameters() == 2) && !function().IsGeneric());
+      code_ += B->StoreInstanceField(TokenPosition::kNoSource,
+                                     Slot::LinkedHashMap_used_data(),
+                                     kNoStoreBarrier);
+      code_ += B->NullConstant();
+      break;
+    case MethodRecognizer::kLinkedHashMap_getDeletedKeys:
+      ASSERT((function().NumParameters() == 1) && !function().IsGeneric());
+      code_ += B->LoadNativeField(Slot::LinkedHashMap_deleted_keys());
+      break;
+    case MethodRecognizer::kLinkedHashMap_setDeletedKeys:
+      ASSERT((function().NumParameters() == 2) && !function().IsGeneric());
+      code_ += B->StoreInstanceField(TokenPosition::kNoSource,
+                                     Slot::LinkedHashMap_deleted_keys(),
+                                     kNoStoreBarrier);
+      code_ += B->NullConstant();
+      break;
+    default: {
+      B->InlineBailout("BytecodeFlowGraphBuilder::BuildNativeCall");
+      const auto& name = String::ZoneHandle(Z, function().native_name());
+      const intptr_t num_args =
+          function().NumParameters() + (function().IsGeneric() ? 1 : 0);
+      ArgumentArray arguments = GetArguments(num_args);
+      auto* call =
+          new (Z) NativeCallInstr(&name, &function(), FLAG_link_natives_lazily,
+                                  function().end_token_pos(), arguments);
+      code_ <<= call;
+      B->Push(call);
+      break;
+    }
+  }
 }
 
 void BytecodeFlowGraphBuilder::BuildAllocate() {
@@ -1471,6 +1656,9 @@
       return KernelBytecode::DecodeC(instr) > 0;
     case KernelBytecode::kEqualsNull:
       return true;
+    case KernelBytecode::kNativeCall:
+      return MethodRecognizer::RecognizeKind(function()) ==
+             MethodRecognizer::kListFactory;
     default:
       return false;
   }
@@ -1547,9 +1735,6 @@
 }
 
 FlowGraph* BytecodeFlowGraphBuilder::BuildGraph() {
-  // Use default flow graph builder for native methods.
-  ASSERT(!function().is_native());
-
   const Bytecode& bytecode = Bytecode::Handle(Z, function().bytecode());
 
   object_pool_ = bytecode.object_pool();
diff --git a/runtime/vm/compiler/frontend/constant_evaluator.cc b/runtime/vm/compiler/frontend/constant_evaluator.cc
index 6733249..861a19a 100644
--- a/runtime/vm/compiler/frontend/constant_evaluator.cc
+++ b/runtime/vm/compiler/frontend/constant_evaluator.cc
@@ -94,6 +94,14 @@
       case kStringConcatenation:
         EvaluateStringConcatenation();
         break;
+      case kListConcatenation:
+      case kSetConcatenation:
+      case kMapConcatenation:
+        // These only occur inside unevaluated constants, so if we decide to
+        // remove support for late evaluation of environment constants from
+        // dill files in the VM, an implementation here will not be necessary.
+        UNIMPLEMENTED();
+        break;
       case kSymbolLiteral:
         EvaluateSymbolLiteral();
         break;
@@ -466,11 +474,11 @@
   ASSERT(IsBuildingFlowGraph());
   TokenPosition position = helper_->ReadPosition();  // read position.
 
-  const LocalVariable* this_variable =
-      flow_graph_builder_->scopes_->this_variable;
-  ASSERT(this_variable->IsConst());
+  const LocalVariable* receiver_variable =
+      flow_graph_builder_->parsed_function_->receiver_var();
+  ASSERT(receiver_variable->IsConst());
   const Instance& receiver =
-      Instance::Handle(Z, this_variable->ConstValue()->raw());
+      Instance::Handle(Z, receiver_variable->ConstValue()->raw());
   ASSERT(!receiver.IsNull());
 
   Class& klass = Class::Handle(Z, active_class_->klass->SuperClass());
diff --git a/runtime/vm/compiler/frontend/flow_graph_builder.cc b/runtime/vm/compiler/frontend/flow_graph_builder.cc
index 00ff453..c1b1dea 100644
--- a/runtime/vm/compiler/frontend/flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/flow_graph_builder.cc
@@ -51,6 +51,8 @@
 
   // Attach the outer environment on each instruction in the callee graph.
   ASSERT(call_->env() != NULL);
+  ASSERT(call_->deopt_id() != DeoptId::kNone);
+  const intptr_t outer_deopt_id = call_->deopt_id();
   // Scale the edge weights by the call count for the inlined function.
   double scale_factor =
       static_cast<double>(call_->CallCount()) /
@@ -63,7 +65,8 @@
     }
     Instruction* instr = block;
     if (block->env() != NULL) {
-      call_->env()->DeepCopyToOuter(callee_graph->zone(), block);
+      call_->env()->DeepCopyToOuter(callee_graph->zone(), block,
+                                    outer_deopt_id);
     }
     for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
       instr = it.Current();
@@ -71,7 +74,8 @@
       // optimizations need deoptimization info for non-deoptable instructions,
       // eg, LICM on GOTOs.
       if (instr->env() != NULL) {
-        call_->env()->DeepCopyToOuter(callee_graph->zone(), instr);
+        call_->env()->DeepCopyToOuter(callee_graph->zone(), instr,
+                                      outer_deopt_id);
       }
     }
     if (instr->IsGoto()) {
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 7e77d3d..95b52d3 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -67,79 +67,18 @@
                            B->last_used_block_id_, prologue_info);
 }
 
-FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFieldAccessor(
-    LocalVariable* setter_value) {
+void StreamingFlowGraphBuilder::EvaluateConstFieldValue(const Field& field) {
+  ASSERT(field.is_const() && field.IsUninitialized());
+
   FieldHelper field_helper(this);
-  field_helper.ReadUntilIncluding(FieldHelper::kCanonicalName);
+  field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
+  Tag initializer_tag = ReadTag();  // read first part of initializer.
 
-  const Function& function = parsed_function()->function();
+  ASSERT(initializer_tag == kSomething);
 
-  // Instead of building a dynamic invocation forwarder that checks argument
-  // type and then invokes original setter we simply generate the type check
-  // and inlined field store. Scope builder takes care of setting correct
-  // type check mode in this case.
-  const bool is_setter = function.IsDynamicInvocationForwader() ||
-                         function.IsImplicitSetterFunction();
-  const bool is_method = !function.IsStaticFunction();
-  Field& field = Field::ZoneHandle(
-      Z, H.LookupFieldByKernelField(field_helper.canonical_name_));
-
-  B->graph_entry_ =
-      new (Z) GraphEntryInstr(*parsed_function(), Compiler::kNoOSRDeoptId);
-
-  auto normal_entry = B->BuildFunctionEntry(B->graph_entry_);
-  B->graph_entry_->set_normal_entry(normal_entry);
-
-  Fragment body(normal_entry);
-  if (is_setter) {
-    // We only expect to generate a dynamic invocation forwarder if
-    // the value needs type check.
-    ASSERT(!function.IsDynamicInvocationForwader() ||
-           setter_value->needs_type_check());
-    if (is_method) {
-      body += LoadLocal(scopes()->this_variable);
-    }
-    body += LoadLocal(setter_value);
-    if (I->argument_type_checks() && setter_value->needs_type_check()) {
-      body += CheckArgumentType(setter_value, setter_value->type());
-    }
-    if (is_method) {
-      body += flow_graph_builder_->StoreInstanceFieldGuarded(field, false);
-    } else {
-      body += StoreStaticField(TokenPosition::kNoSource, field);
-    }
-    body += NullConstant();
-  } else if (is_method) {
-    body += LoadLocal(scopes()->this_variable);
-    body += flow_graph_builder_->LoadField(field);
-  } else if (field.is_const()) {
-    field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
-    Tag initializer_tag = ReadTag();  // read first part of initializer.
-
-    // If the parser needs to know the value of an uninitialized constant field
-    // it will set the value to the transition sentinel (used to detect circular
-    // initialization) and then call the implicit getter.  Thus, the getter
-    // cannot contain the InitStaticField instruction that normal static getters
-    // contain because it would detect spurious circular initialization when it
-    // checks for the transition sentinel.
-    ASSERT(initializer_tag == kSomething);
-    body += Constant(Instance::ZoneHandle(
-        Z, constant_evaluator_.EvaluateExpression(ReaderOffset())));
-  } else {
-    // The field always has an initializer because static fields without
-    // initializers are initialized eagerly and do not have implicit getters.
-    ASSERT(field.has_initializer());
-    body += Constant(field);
-    body += flow_graph_builder_->InitStaticField(field);
-    body += Constant(field);
-    body += LoadStaticField();
-  }
-  body += Return(TokenPosition::kNoSource);
-
-  PrologueInfo prologue_info(-1, -1);
-  return new (Z)
-      FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
-                flow_graph_builder_->last_used_block_id_, prologue_info);
+  Instance& value = Instance::Handle(
+      Z, constant_evaluator_.EvaluateExpression(ReaderOffset()));
+  field.SetStaticValue(value);
 }
 
 void StreamingFlowGraphBuilder::SetupDefaultParameterValues() {
@@ -232,7 +171,7 @@
   }
 
   Fragment instructions;
-  instructions += LoadLocal(scopes()->this_variable);
+  instructions += LoadLocal(parsed_function()->receiver_var());
   instructions += BuildExpression();
   instructions += flow_graph_builder_->StoreInstanceFieldGuarded(field, true);
   return instructions;
@@ -328,7 +267,7 @@
           NameIndex canonical_target =
               ReadCanonicalNameReference();  // read target_reference.
 
-          instructions += LoadLocal(scopes()->this_variable);
+          instructions += LoadLocal(parsed_function()->receiver_var());
           instructions += PushArgument();
 
           // TODO(jensj): ASSERT(init->arguments()->types().length() == 0);
@@ -355,7 +294,7 @@
           NameIndex canonical_target =
               ReadCanonicalNameReference();  // read target_reference.
 
-          instructions += LoadLocal(scopes()->this_variable);
+          instructions += LoadLocal(parsed_function()->receiver_var());
           instructions += PushArgument();
 
           // TODO(jensj): ASSERT(init->arguments()->types().length() == 0);
@@ -448,162 +387,6 @@
   parsed_function()->SetDefaultFunctionTypeArguments(default_types);
 }
 
-Fragment StreamingFlowGraphBuilder::PushAllArguments(PushedArguments* pushed) {
-  FunctionNodeHelper function_node_helper(this);
-  function_node_helper.SetNext(FunctionNodeHelper::kTypeParameters);
-
-  Fragment body;
-
-  const intptr_t num_type_params = ReadListLength();
-  if (num_type_params > 0) {
-    // Skip type arguments.
-    for (intptr_t i = 0; i < num_type_params; ++i) {
-      TypeParameterHelper helper(this);
-      helper.Finish();
-    }
-
-    body += LoadLocal(parsed_function()->function_type_arguments());
-    body += PushArgument();
-    pushed->type_args_len = num_type_params;
-  }
-  function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters);
-  function_node_helper.ReadUntilExcluding(
-      FunctionNodeHelper::kPositionalParameters);
-
-  // Push receiver.
-  body += LoadLocal(scopes()->this_variable);
-  body += PushArgument();
-
-  // Push positional parameters.
-  const intptr_t num_positional_params = ReadListLength();
-  for (intptr_t i = 0; i < num_positional_params; ++i) {
-    // ith variable offset.
-    const intptr_t offset = ReaderOffset();
-    SkipVariableDeclaration();
-
-    LocalVariable* param = LookupVariable(offset + data_program_offset_);
-    body += LoadLocal(param);
-    body += PushArgument();
-  }
-
-  // Push named parameters.
-  const intptr_t num_named_params = ReadListLength();
-  pushed->argument_names = Array::New(num_named_params, Heap::kOld);
-  for (intptr_t i = 0; i < num_named_params; ++i) {
-    // ith variable offset.
-    const intptr_t offset = ReaderOffset();
-    SkipVariableDeclaration();
-
-    LocalVariable* param = LookupVariable(offset + data_program_offset_);
-    pushed->argument_names.SetAt(i, param->name());
-    body += LoadLocal(param);
-    body += PushArgument();
-  }
-
-  pushed->argument_count = num_positional_params + num_named_params + 1;
-
-  return body;
-}
-
-FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfDynamicInvocationForwarder() {
-  const Function& dart_function = parsed_function()->function();
-
-  // The prologue builder needs the default parameter values.
-  SetupDefaultParameterValues();
-  // BuildDefaultTypeHandling needs default function type arguments.
-  ReadDefaultFunctionTypeArguments(dart_function);
-
-  B->graph_entry_ = new (Z) GraphEntryInstr(*parsed_function(), B->osr_id_);
-
-  auto normal_entry = B->BuildFunctionEntry(B->graph_entry_);
-  B->graph_entry_->set_normal_entry(normal_entry);
-
-  PrologueInfo prologue_info(-1, -1);
-  auto instruction_cursor = B->BuildPrologue(normal_entry, &prologue_info);
-
-  Fragment body;
-  if (!dart_function.is_native()) {
-    body += B->CheckStackOverflowInPrologue(dart_function.token_pos());
-  }
-
-  ASSERT(parsed_function()->node_sequence()->scope()->num_context_variables() ==
-         0);
-
-  FunctionNodeHelper function_node_helper(this);
-  function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
-  const intptr_t type_parameters_offset = ReaderOffset();
-  function_node_helper.ReadUntilExcluding(
-      FunctionNodeHelper::kPositionalParameters);
-  intptr_t first_parameter_offset = -1;
-  {
-    AlternativeReadingScope alt(&reader_);
-    intptr_t list_length = ReadListLength();  // read number of positionals.
-    if (list_length > 0) {
-      first_parameter_offset = ReaderOffset() + data_program_offset_;
-    }
-  }
-  USE(first_parameter_offset);
-  // Current position: About to read list of positionals.
-
-  // Should never build a dynamic invocation forwarder for equality
-  // operator.
-  ASSERT(dart_function.name() != Symbols::EqualOperator().raw());
-
-  // Even if the caller did not pass argument vector we would still
-  // call the target with instantiate-to-bounds type arguments.
-  body += B->BuildDefaultTypeHandling(dart_function);
-
-  String& name = String::Handle(Z, dart_function.name());
-  name = Function::DemangleDynamicInvocationForwarderName(name);
-  const Class& owner = Class::Handle(Z, dart_function.Owner());
-  const Function& target =
-      Function::ZoneHandle(Z, owner.LookupDynamicFunction(name));
-  ASSERT(!target.IsNull());
-
-  // Build argument type checks that complement those that are emitted in the
-  // target.
-  {
-    AlternativeReadingScope alt(&reader_);
-    SetOffset(type_parameters_offset);
-    B->BuildArgumentTypeChecks(
-        TypeChecksToBuild::kCheckNonCovariantTypeParameterBounds, &body, &body,
-        nullptr);
-  }
-
-  // Push all arguments and invoke the original method.
-  PushedArguments pushed = {0, 0, Array::ZoneHandle(Z)};
-  {
-    AlternativeReadingScope alt(&reader_);
-    SetOffset(type_parameters_offset);
-    body += PushAllArguments(&pushed);
-  }
-  body += StaticCall(TokenPosition::kNoSource, target, pushed.argument_count,
-                     pushed.argument_names, ICData::kNoRebind, nullptr,
-                     pushed.type_args_len);
-
-  // Some IL optimization passes assume that result of operator []= invocation
-  // is never used, so we drop it and replace with an explicit null constant.
-  if (name.raw() == Symbols::AssignIndexToken().raw()) {
-    body += Drop();
-    body += NullConstant();
-  }
-
-  body += Return(TokenPosition::kNoSource);
-
-  instruction_cursor->LinkTo(body.entry);
-
-  GraphEntryInstr* graph_entry = B->graph_entry_;
-  // When compiling for OSR, use a depth first search to find the OSR
-  // entry and make graph entry jump to it instead of normal entry.
-  // Catch entries are always considered reachable, even if they
-  // become unreachable after OSR.
-  if (B->IsCompiledForOsr()) {
-    graph_entry->RelinkToOsrEntry(Z, B->last_used_block_id_ + 1);
-  }
-  return new (Z) FlowGraph(*parsed_function(), graph_entry,
-                           B->last_used_block_id_, prologue_info);
-}
-
 Fragment StreamingFlowGraphBuilder::DebugStepCheckInPrologue(
     const Function& dart_function,
     TokenPosition position) {
@@ -616,8 +399,8 @@
   const int parameter_count = dart_function.NumParameters();
   TokenPosition check_pos = TokenPosition::kNoSource;
   if (parameter_count > 0) {
-    LocalScope* scope = parsed_function()->node_sequence()->scope();
-    const LocalVariable& parameter = *scope->VariableAt(parameter_count - 1);
+    const LocalVariable& parameter =
+        *parsed_function()->ParameterVariable(parameter_count - 1);
     check_pos = parameter.token_pos();
   }
   if (!check_pos.IsDebugPause()) {
@@ -670,8 +453,7 @@
 
   if (dart_function.IsClosureFunction() &&
       dart_function.NumParentTypeParameters() > 0) {
-    LocalVariable* closure =
-        parsed_function()->node_sequence()->scope()->VariableAt(0);
+    LocalVariable* closure = parsed_function()->ParameterVariable(0);
 
     // Function with yield points can not be generic itself but the outer
     // function can be.
@@ -801,7 +583,7 @@
     const Function& function = pf.function();
 
     for (intptr_t i = 0; i < parameter_count; ++i) {
-      LocalVariable* variable = scope->VariableAt(i);
+      LocalVariable* variable = pf.ParameterVariable(i);
       if (variable->is_captured()) {
         LocalVariable& raw_parameter = *pf.RawParameterVariable(i);
         ASSERT((function.HasOptionalParameters() &&
@@ -1143,7 +925,7 @@
   SetOffset(kernel_offset);
 
   if ((FLAG_use_bytecode_compiler || FLAG_enable_interpreter) &&
-      function.IsBytecodeAllowed(Z) && !function.is_native()) {
+      function.IsBytecodeAllowed(Z)) {
     if (!function.HasBytecode()) {
       bytecode_metadata_helper_.ReadMetadata(function);
     }
@@ -1211,17 +993,22 @@
     case RawFunction::kImplicitGetter:
     case RawFunction::kImplicitStaticFinalGetter:
     case RawFunction::kImplicitSetter: {
-      return IsFieldInitializer(function, Z)
-                 ? BuildGraphOfFieldInitializer()
-                 : BuildGraphOfFieldAccessor(scopes()->setter_value);
+      if (IsFieldInitializer(function, Z)) {
+        return BuildGraphOfFieldInitializer();
+      }
+      const Field& field = Field::Handle(Z, function.accessor_field());
+      if (field.is_const() && field.IsUninitialized()) {
+        EvaluateConstFieldValue(field);
+      }
+      return B->BuildGraphOfFieldAccessor(function);
     }
     case RawFunction::kDynamicInvocationForwarder:
-      if (PeekTag() == kField) {
-        return BuildGraphOfFieldAccessor(scopes()->setter_value);
-      } else {
+      if (PeekTag() != kField) {
         ReadUntilFunctionNode();
-        return BuildGraphOfDynamicInvocationForwarder();
+        SetupDefaultParameterValues();
+        ReadDefaultFunctionTypeArguments(function);
       }
+      return B->BuildGraphOfDynamicInvocationForwarder(function);
     case RawFunction::kMethodExtractor:
       return flow_graph_builder_->BuildGraphOfMethodExtractor(function);
     case RawFunction::kNoSuchMethodDispatcher:
@@ -1233,9 +1020,10 @@
       SetupDefaultParameterValues();
       ReadDefaultFunctionTypeArguments(function);
       return flow_graph_builder_->BuildGraphOfImplicitClosureFunction(function);
+    case RawFunction::kFfiTrampoline:
+      return flow_graph_builder_->BuildGraphOfFfiTrampoline(function);
     case RawFunction::kSignatureFunction:
     case RawFunction::kIrregexpFunction:
-    case RawFunction::kFfiTrampoline:
       break;
   }
   UNREACHABLE();
@@ -1299,6 +1087,13 @@
       return BuildConditionalExpression(position);
     case kStringConcatenation:
       return BuildStringConcatenation(position);
+    case kListConcatenation:
+    case kSetConcatenation:
+    case kMapConcatenation:
+      // Collection concatenation operations are removed by the constant
+      // evaluator.
+      UNREACHABLE();
+      break;
     case kIsExpression:
       return BuildIsExpression(position);
     case kAsExpression:
@@ -1331,10 +1126,8 @@
       return BuildFunctionExpression();
     case kLet:
       return BuildLet(position);
-    case kBlockExpression: {
-      UNIMPLEMENTED();
-      break;
-    }
+    case kBlockExpression:
+      return BuildBlockExpression();
     case kBigIntLiteral:
       return BuildBigIntLiteral(position);
     case kStringLiteral:
@@ -1477,6 +1270,18 @@
   --flow_graph_builder_->try_depth_;
 }
 
+intptr_t StreamingFlowGraphBuilder::block_expression_depth() {
+  return flow_graph_builder_->block_expression_depth_;
+}
+
+void StreamingFlowGraphBuilder::block_expression_depth_inc() {
+  ++flow_graph_builder_->block_expression_depth_;
+}
+
+void StreamingFlowGraphBuilder::block_expression_depth_dec() {
+  --flow_graph_builder_->block_expression_depth_;
+}
+
 intptr_t StreamingFlowGraphBuilder::CurrentTryIndex() {
   return flow_graph_builder_->CurrentTryIndex();
 }
@@ -1831,7 +1636,7 @@
   const intptr_t saved_context_depth = B->context_depth_;
   const ProgramState state(B->breakable_block_, B->switch_block_,
                            B->loop_depth_, B->for_in_depth_, B->try_depth_,
-                           B->catch_depth_);
+                           B->catch_depth_, B->block_expression_depth_);
 
   Fragment instructions;
 
@@ -2368,12 +2173,12 @@
   // Populate array containing the actual arguments. Just add [this] here.
   instructions += LoadLocal(actuals_array);                      // array
   instructions += IntConstant(num_type_arguments == 0 ? 0 : 1);  // index
-  instructions += LoadLocal(scopes()->this_variable);            // receiver
+  instructions += LoadLocal(parsed_function()->receiver_var());  // receiver
   instructions += StoreIndexed(kArrayCid);
   instructions += build_rest_of_actuals;
 
   // First argument is receiver.
-  instructions += LoadLocal(scopes()->this_variable);
+  instructions += LoadLocal(parsed_function()->receiver_var());
   instructions += PushArgument();
 
   // Push the arguments for allocating the invocation mirror:
@@ -2473,7 +2278,7 @@
     ASSERT(!klass.IsNull());
     ASSERT(!function.IsNull());
 
-    instructions += LoadLocal(scopes()->this_variable);
+    instructions += LoadLocal(parsed_function()->receiver_var());
     instructions += PushArgument();
 
     instructions +=
@@ -2530,7 +2335,7 @@
     instructions += Drop();  // Drop array
   } else {
     // receiver
-    instructions += LoadLocal(scopes()->this_variable);
+    instructions += LoadLocal(parsed_function()->receiver_var());
     instructions += PushArgument();
 
     instructions += BuildExpression();  // read value.
@@ -3126,7 +2931,7 @@
     }
 
     // receiver
-    instructions += LoadLocal(scopes()->this_variable);
+    instructions += LoadLocal(parsed_function()->receiver_var());
     instructions += PushArgument();
 
     Array& argument_names = Array::ZoneHandle(Z);
@@ -3631,7 +3436,7 @@
     TokenPosition* position) {
   if (position != NULL) *position = TokenPosition::kNoSource;
 
-  return LoadLocal(scopes()->this_variable);
+  return LoadLocal(parsed_function()->receiver_var());
 }
 
 Fragment StreamingFlowGraphBuilder::BuildRethrow(TokenPosition* p) {
@@ -3791,6 +3596,24 @@
   return instructions;
 }
 
+Fragment StreamingFlowGraphBuilder::BuildBlockExpression() {
+  block_expression_depth_inc();
+  const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
+
+  Fragment instructions;
+
+  instructions += EnterScope(offset);
+  const intptr_t list_length = ReadListLength();  // read number of statements.
+  for (intptr_t i = 0; i < list_length; ++i) {
+    instructions += BuildStatement();  // read ith statement.
+  }
+  instructions += BuildExpression();  // read expression (inside scope).
+  instructions += ExitScope(offset);
+
+  block_expression_depth_dec();
+  return instructions;
+}
+
 Fragment StreamingFlowGraphBuilder::BuildBigIntLiteral(
     TokenPosition* position) {
   if (position != NULL) *position = TokenPosition::kNoSource;
@@ -4127,6 +3950,7 @@
 }
 
 Fragment StreamingFlowGraphBuilder::BuildWhileStatement() {
+  ASSERT(block_expression_depth() == 0);  // no while in block-expr
   loop_depth_inc();
   const TokenPosition position = ReadPosition();  // read position.
   TestFragment condition = TranslateConditionForControl();  // read condition.
@@ -4154,6 +3978,7 @@
 }
 
 Fragment StreamingFlowGraphBuilder::BuildDoStatement() {
+  ASSERT(block_expression_depth() == 0);  // no do-while in block-expr
   loop_depth_inc();
   const TokenPosition position = ReadPosition();  // read position.
   Fragment body = BuildStatement();               // read body.
@@ -4236,7 +4061,11 @@
     body += Goto(join);
 
     Fragment loop(join);
-    loop += CheckStackOverflow(position);
+
+    // Avoid OSR point inside block-expressions.
+    // TODO(ajcbik): make sure OSR works inside BE too
+    if (block_expression_depth() == 0) loop += CheckStackOverflow(position);
+
     if (condition.entry != nullptr) {
       loop <<= condition.entry;
     } else {
@@ -4309,7 +4138,11 @@
     body += Goto(join);
 
     Fragment loop(join);
-    loop += CheckStackOverflow(position);
+
+    // Avoid OSR point inside block-expressions.
+    // TODO(ajcbik): make sure OSR works inside BE too
+    if (block_expression_depth() == 0) loop += CheckStackOverflow(position);
+
     loop += condition;
   } else {
     instructions += condition;
@@ -4614,6 +4447,7 @@
 }
 
 Fragment StreamingFlowGraphBuilder::BuildTryCatch() {
+  ASSERT(block_expression_depth() == 0);  // no try-catch in block-expr
   InlineBailout("kernel::FlowgraphBuilder::VisitTryCatch");
 
   intptr_t try_handler_index = AllocateTryIndex();
@@ -4743,6 +4577,7 @@
 }
 
 Fragment StreamingFlowGraphBuilder::BuildTryFinally() {
+  ASSERT(block_expression_depth() == 0);  // no try-finally in block-expr
   // Note on streaming:
   // We only stream this TryFinally if we can stream everything inside it,
   // so creating a "TryFinallyBlock" with a kernel binary offset instead of an
@@ -4878,9 +4713,8 @@
     //     ...
     //   }
     //
-    LocalScope* scope = parsed_function()->node_sequence()->scope();
-    LocalVariable* exception_var = scope->VariableAt(2);
-    LocalVariable* stack_trace_var = scope->VariableAt(3);
+    LocalVariable* exception_var = parsed_function()->ParameterVariable(2);
+    LocalVariable* stack_trace_var = parsed_function()->ParameterVariable(3);
     ASSERT(exception_var->name().raw() == Symbols::ExceptionParameter().raw());
     ASSERT(stack_trace_var->name().raw() ==
            Symbols::StackTraceParameter().raw());
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index b12d4e3..bedc54e 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -57,13 +57,12 @@
   Thread* thread() const { return flow_graph_builder_->thread_; }
 
   FlowGraph* BuildGraphOfFieldInitializer();
-  FlowGraph* BuildGraphOfFieldAccessor(LocalVariable* setter_value);
+  void EvaluateConstFieldValue(const Field& field);
   void SetupDefaultParameterValues();
   void ReadDefaultFunctionTypeArguments(const Function& function);
   Fragment BuildFieldInitializer(NameIndex canonical_name);
   Fragment BuildInitializers(const Class& parent_class);
   FlowGraph* BuildGraphOfFunction(bool constructor);
-  FlowGraph* BuildGraphOfDynamicInvocationForwarder();
 
   Fragment BuildExpression(TokenPosition* position = NULL);
   Fragment BuildStatement();
@@ -112,6 +111,9 @@
   void catch_depth_dec();
   void try_depth_inc();
   void try_depth_dec();
+  intptr_t block_expression_depth();
+  void block_expression_depth_inc();
+  void block_expression_depth_dec();
   intptr_t CurrentTryIndex();
   intptr_t AllocateTryIndex();
   LocalVariable* CurrentException();
@@ -193,13 +195,6 @@
       bool use_unchecked_entry = false,
       const CallSiteAttributesMetadata* call_site_attrs = nullptr);
 
-  struct PushedArguments {
-    intptr_t type_args_len;
-    intptr_t argument_count;
-    Array& argument_names;
-  };
-  Fragment PushAllArguments(PushedArguments* pushed);
-
   Fragment ThrowException(TokenPosition position);
   Fragment BooleanNegate();
   Fragment TranslateInstantiatedTypeArguments(
@@ -314,6 +309,7 @@
   Fragment BuildMapLiteral(bool is_const, TokenPosition* position);
   Fragment BuildFunctionExpression();
   Fragment BuildLet(TokenPosition* position);
+  Fragment BuildBlockExpression();
   Fragment BuildBigIntLiteral(TokenPosition* position);
   Fragment BuildStringLiteral(TokenPosition* position);
   Fragment BuildIntLiteral(uint8_t payload, TokenPosition* position);
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index 58675d6..1a88f1ba 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -447,6 +447,13 @@
       ReadPosition();                           // read position.
       CalculateListOfExpressionsFingerprint();  // read list of expressions.
       return;
+    case kListConcatenation:
+    case kSetConcatenation:
+    case kMapConcatenation:
+      // Collection concatenation operations are removed by the constant
+      // evaluator.
+      UNREACHABLE();
+      break;
     case kIsExpression:
       ReadPosition();                    // read position.
       CalculateExpressionFingerprint();  // read operand.
@@ -505,10 +512,10 @@
       CalculateVariableDeclarationFingerprint();  // read variable declaration.
       CalculateExpressionFingerprint();           // read expression.
       return;
-    case kBlockExpression: {
-      UNIMPLEMENTED();
+    case kBlockExpression:
+      CalculateStatementListFingerprint();
+      CalculateExpressionFingerprint();  // read expression.
       return;
-    }
     case kInstantiation:
       CalculateExpressionFingerprint();       // read expression.
       CalculateListOfDartTypesFingerprint();  // read type arguments.
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 9da71ef..15b989b 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -2,11 +2,13 @@
 // 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 "vm/compiler/aot/precompiler.h"
 #include "vm/compiler/frontend/kernel_to_il.h"
+#include "vm/compiler/aot/precompiler.h"
+#include "vm/compiler/backend/locations.h"
 
 #include "vm/compiler/backend/il.h"
 #include "vm/compiler/backend/il_printer.h"
+#include "vm/compiler/ffi.h"
 #include "vm/compiler/frontend/kernel_binary_flowgraph.h"
 #include "vm/compiler/frontend/kernel_translation_helper.h"
 #include "vm/compiler/frontend/prologue_builder.h"
@@ -54,6 +56,7 @@
       try_depth_(0),
       catch_depth_(0),
       for_in_depth_(0),
+      block_expression_depth_(0),
       graph_entry_(NULL),
       scopes_(NULL),
       breakable_block_(NULL),
@@ -137,10 +140,10 @@
     ASSERT(function.IsFactory());
 #endif
     instructions += LoadLocal(scopes_->type_arguments_variable);
-  } else if (scopes_->this_variable != NULL &&
+  } else if (parsed_function_->has_receiver_var() &&
              active_class_.ClassNumTypeArguments() > 0) {
     ASSERT(!parsed_function_->function().IsFactory());
-    instructions += LoadLocal(scopes_->this_variable);
+    instructions += LoadLocal(parsed_function_->receiver_var());
     instructions += LoadNativeField(
         Slot::GetTypeArgumentsSlotFor(thread_, *active_class_.klass));
   } else {
@@ -258,9 +261,8 @@
   LocalVariable* context_variable = parsed_function_->current_context_var();
   if (should_restore_closure_context) {
     ASSERT(parsed_function_->function().IsClosureFunction());
-    LocalScope* scope = parsed_function_->node_sequence()->scope();
 
-    LocalVariable* closure_parameter = scope->VariableAt(0);
+    LocalVariable* closure_parameter = parsed_function_->ParameterVariable(0);
     ASSERT(!closure_parameter->is_captured());
     instructions += LoadLocal(closure_parameter);
     instructions += LoadNativeField(Slot::Closure_context());
@@ -393,6 +395,25 @@
   return Fragment(call);
 }
 
+Fragment FlowGraphBuilder::FfiCall(
+    const Function& signature,
+    const ZoneGrowableArray<Representation>& arg_reps,
+    const ZoneGrowableArray<Location>& arg_locs) {
+  Fragment body;
+
+  FfiCallInstr* call =
+      new (Z) FfiCallInstr(Z, GetNextDeoptId(), signature, arg_reps, arg_locs);
+
+  for (intptr_t i = call->InputCount() - 1; i >= 0; --i) {
+    call->SetInputAt(i, Pop());
+  }
+
+  Push(call);
+  body <<= call;
+
+  return body;
+}
+
 Fragment FlowGraphBuilder::RethrowException(TokenPosition position,
                                             int catch_try_index) {
   Fragment instructions;
@@ -410,12 +431,6 @@
   return instructions;
 }
 
-Fragment FlowGraphBuilder::LoadClassId() {
-  LoadClassIdInstr* load = new (Z) LoadClassIdInstr(Pop());
-  Push(load);
-  return Fragment(load);
-}
-
 Fragment FlowGraphBuilder::LoadLocal(LocalVariable* variable) {
   if (variable->is_captured()) {
     Fragment instructions;
@@ -733,14 +748,73 @@
   const MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
   bool omit_result_type_check = true;
   switch (kind) {
+    case MethodRecognizer::kTypedData_ByteDataView_factory:
+      body += BuildTypedDataViewFactoryConstructor(function, kByteDataViewCid);
+      break;
+    case MethodRecognizer::kTypedData_Int8ArrayView_factory:
+      body += BuildTypedDataViewFactoryConstructor(function,
+                                                   kTypedDataInt8ArrayViewCid);
+      break;
+    case MethodRecognizer::kTypedData_Uint8ArrayView_factory:
+      body += BuildTypedDataViewFactoryConstructor(function,
+                                                   kTypedDataUint8ArrayViewCid);
+      break;
+    case MethodRecognizer::kTypedData_Uint8ClampedArrayView_factory:
+      body += BuildTypedDataViewFactoryConstructor(
+          function, kTypedDataUint8ClampedArrayViewCid);
+      break;
+    case MethodRecognizer::kTypedData_Int16ArrayView_factory:
+      body += BuildTypedDataViewFactoryConstructor(function,
+                                                   kTypedDataInt16ArrayViewCid);
+      break;
+    case MethodRecognizer::kTypedData_Uint16ArrayView_factory:
+      body += BuildTypedDataViewFactoryConstructor(
+          function, kTypedDataUint16ArrayViewCid);
+      break;
+    case MethodRecognizer::kTypedData_Int32ArrayView_factory:
+      body += BuildTypedDataViewFactoryConstructor(function,
+                                                   kTypedDataInt32ArrayViewCid);
+      break;
+    case MethodRecognizer::kTypedData_Uint32ArrayView_factory:
+      body += BuildTypedDataViewFactoryConstructor(
+          function, kTypedDataUint32ArrayViewCid);
+      break;
+    case MethodRecognizer::kTypedData_Int64ArrayView_factory:
+      body += BuildTypedDataViewFactoryConstructor(function,
+                                                   kTypedDataInt64ArrayViewCid);
+      break;
+    case MethodRecognizer::kTypedData_Uint64ArrayView_factory:
+      body += BuildTypedDataViewFactoryConstructor(
+          function, kTypedDataUint64ArrayViewCid);
+      break;
+    case MethodRecognizer::kTypedData_Float32ArrayView_factory:
+      body += BuildTypedDataViewFactoryConstructor(
+          function, kTypedDataFloat32ArrayViewCid);
+      break;
+    case MethodRecognizer::kTypedData_Float64ArrayView_factory:
+      body += BuildTypedDataViewFactoryConstructor(
+          function, kTypedDataFloat64ArrayViewCid);
+      break;
+    case MethodRecognizer::kTypedData_Float32x4ArrayView_factory:
+      body += BuildTypedDataViewFactoryConstructor(
+          function, kTypedDataFloat32x4ArrayViewCid);
+      break;
+    case MethodRecognizer::kTypedData_Int32x4ArrayView_factory:
+      body += BuildTypedDataViewFactoryConstructor(
+          function, kTypedDataInt32x4ArrayViewCid);
+      break;
+    case MethodRecognizer::kTypedData_Float64x2ArrayView_factory:
+      body += BuildTypedDataViewFactoryConstructor(
+          function, kTypedDataFloat64x2ArrayViewCid);
+      break;
     case MethodRecognizer::kObjectEquals:
-      body += LoadLocal(scopes_->this_variable);
+      body += LoadLocal(parsed_function_->receiver_var());
       body += LoadLocal(first_parameter);
       body += StrictCompare(Token::kEQ_STRICT);
       break;
     case MethodRecognizer::kStringBaseLength:
     case MethodRecognizer::kStringBaseIsEmpty:
-      body += LoadLocal(scopes_->this_variable);
+      body += LoadLocal(parsed_function_->receiver_var());
       body += LoadNativeField(Slot::String_length());
       if (kind == MethodRecognizer::kStringBaseIsEmpty) {
         body += IntConstant(0);
@@ -748,24 +822,39 @@
       }
       break;
     case MethodRecognizer::kGrowableArrayLength:
-      body += LoadLocal(scopes_->this_variable);
+      body += LoadLocal(parsed_function_->receiver_var());
       body += LoadNativeField(Slot::GrowableObjectArray_length());
       break;
     case MethodRecognizer::kObjectArrayLength:
     case MethodRecognizer::kImmutableArrayLength:
-      body += LoadLocal(scopes_->this_variable);
+      body += LoadLocal(parsed_function_->receiver_var());
       body += LoadNativeField(Slot::Array_length());
       break;
     case MethodRecognizer::kTypedDataLength:
-      body += LoadLocal(scopes_->this_variable);
+      body += LoadLocal(parsed_function_->receiver_var());
       body += LoadNativeField(Slot::TypedData_length());
       break;
+    case MethodRecognizer::kByteDataViewLength:
+    case MethodRecognizer::kTypedDataViewLength:
+      body += LoadLocal(parsed_function_->receiver_var());
+      body += LoadNativeField(Slot::TypedDataView_length());
+      break;
+    case MethodRecognizer::kByteDataViewOffsetInBytes:
+    case MethodRecognizer::kTypedDataViewOffsetInBytes:
+      body += LoadLocal(parsed_function_->receiver_var());
+      body += LoadNativeField(Slot::TypedDataView_offset_in_bytes());
+      break;
+    case MethodRecognizer::kByteDataViewTypedData:
+    case MethodRecognizer::kTypedDataViewTypedData:
+      body += LoadLocal(parsed_function_->receiver_var());
+      body += LoadNativeField(Slot::TypedDataView_data());
+      break;
     case MethodRecognizer::kClassIDgetID:
       body += LoadLocal(first_parameter);
       body += LoadClassId();
       break;
     case MethodRecognizer::kGrowableArrayCapacity:
-      body += LoadLocal(scopes_->this_variable);
+      body += LoadLocal(parsed_function_->receiver_var());
       body += LoadNativeField(Slot::GrowableObjectArray_data());
       body += LoadNativeField(Slot::Array_length());
       break;
@@ -839,33 +928,33 @@
       body += CreateArray();
       break;
     case MethodRecognizer::kLinkedHashMap_getIndex:
-      body += LoadLocal(scopes_->this_variable);
+      body += LoadLocal(parsed_function_->receiver_var());
       body += LoadNativeField(Slot::LinkedHashMap_index());
       break;
     case MethodRecognizer::kLinkedHashMap_setIndex:
-      body += LoadLocal(scopes_->this_variable);
+      body += LoadLocal(parsed_function_->receiver_var());
       body += LoadLocal(first_parameter);
       body += StoreInstanceField(TokenPosition::kNoSource,
                                  Slot::LinkedHashMap_index());
       body += NullConstant();
       break;
     case MethodRecognizer::kLinkedHashMap_getData:
-      body += LoadLocal(scopes_->this_variable);
+      body += LoadLocal(parsed_function_->receiver_var());
       body += LoadNativeField(Slot::LinkedHashMap_data());
       break;
     case MethodRecognizer::kLinkedHashMap_setData:
-      body += LoadLocal(scopes_->this_variable);
+      body += LoadLocal(parsed_function_->receiver_var());
       body += LoadLocal(first_parameter);
       body += StoreInstanceField(TokenPosition::kNoSource,
                                  Slot::LinkedHashMap_data());
       body += NullConstant();
       break;
     case MethodRecognizer::kLinkedHashMap_getHashMask:
-      body += LoadLocal(scopes_->this_variable);
+      body += LoadLocal(parsed_function_->receiver_var());
       body += LoadNativeField(Slot::LinkedHashMap_hash_mask());
       break;
     case MethodRecognizer::kLinkedHashMap_setHashMask:
-      body += LoadLocal(scopes_->this_variable);
+      body += LoadLocal(parsed_function_->receiver_var());
       body += LoadLocal(first_parameter);
       body +=
           StoreInstanceField(TokenPosition::kNoSource,
@@ -873,11 +962,11 @@
       body += NullConstant();
       break;
     case MethodRecognizer::kLinkedHashMap_getUsedData:
-      body += LoadLocal(scopes_->this_variable);
+      body += LoadLocal(parsed_function_->receiver_var());
       body += LoadNativeField(Slot::LinkedHashMap_used_data());
       break;
     case MethodRecognizer::kLinkedHashMap_setUsedData:
-      body += LoadLocal(scopes_->this_variable);
+      body += LoadLocal(parsed_function_->receiver_var());
       body += LoadLocal(first_parameter);
       body +=
           StoreInstanceField(TokenPosition::kNoSource,
@@ -885,11 +974,11 @@
       body += NullConstant();
       break;
     case MethodRecognizer::kLinkedHashMap_getDeletedKeys:
-      body += LoadLocal(scopes_->this_variable);
+      body += LoadLocal(parsed_function_->receiver_var());
       body += LoadNativeField(Slot::LinkedHashMap_deleted_keys());
       break;
     case MethodRecognizer::kLinkedHashMap_setDeletedKeys:
-      body += LoadLocal(scopes_->this_variable);
+      body += LoadLocal(parsed_function_->receiver_var());
       body += LoadLocal(first_parameter);
       body += StoreInstanceField(TokenPosition::kNoSource,
                                  Slot::LinkedHashMap_deleted_keys(),
@@ -915,24 +1004,55 @@
   return body + Return(TokenPosition::kNoSource, omit_result_type_check);
 }
 
-static const LocalScope* MakeImplicitClosureScope(Zone* Z,
-                                                  const Function& function) {
-  Class& klass = Class::Handle(Z, function.Owner());
+Fragment FlowGraphBuilder::BuildTypedDataViewFactoryConstructor(
+    const Function& function,
+    classid_t cid) {
+  auto token_pos = function.token_pos();
+  auto class_table = Thread::Current()->isolate()->class_table();
+
+  ASSERT(class_table->HasValidClassAt(cid));
+  const auto& view_class = Class::ZoneHandle(H.zone(), class_table->At(cid));
+
+  LocalVariable* typed_data = parsed_function_->RawParameterVariable(1);
+  LocalVariable* offset_in_bytes = parsed_function_->RawParameterVariable(2);
+  LocalVariable* length = parsed_function_->RawParameterVariable(3);
+
+  Fragment body;
+
+  body += AllocateObject(token_pos, view_class, /*arg_count=*/0);
+  LocalVariable* view_object = MakeTemporary();
+
+  body += LoadLocal(view_object);
+  body += LoadLocal(typed_data);
+  body += StoreInstanceField(token_pos, Slot::TypedDataView_data());
+
+  body += LoadLocal(view_object);
+  body += LoadLocal(offset_in_bytes);
+  body += StoreInstanceField(token_pos, Slot::TypedDataView_offset_in_bytes());
+
+  body += LoadLocal(view_object);
+  body += LoadLocal(length);
+  body += StoreInstanceField(token_pos, Slot::TypedDataView_length());
+
+  return body;
+}
+
+static const LocalScope* MakeImplicitClosureScope(Zone* Z, const Class& klass) {
   ASSERT(!klass.IsNull());
   // Note that if klass is _Closure, DeclarationType will be _Closure,
   // and not the signature type.
   Type& klass_type = Type::ZoneHandle(Z, klass.DeclarationType());
 
-  LocalVariable* this_variable = new (Z)
+  LocalVariable* receiver_variable = new (Z)
       LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                     Symbols::This(), klass_type, /*param_type=*/nullptr);
 
-  this_variable->set_is_captured();
-  //  this_variable->set_is_final();
+  receiver_variable->set_is_captured();
+  //  receiver_variable->set_is_final();
   LocalScope* scope = new (Z) LocalScope(NULL, 0, 0);
   scope->set_context_level(0);
-  scope->AddVariable(this_variable);
-  scope->AddContextVariable(this_variable);
+  scope->AddVariable(receiver_variable);
+  scope->AddContextVariable(receiver_variable);
   return scope;
 }
 
@@ -959,7 +1079,7 @@
   // Allocate a context that closes over `this`.
   // Note: this must be kept in sync with ScopeBuilder::BuildScopes.
   const LocalScope* implicit_closure_scope =
-      MakeImplicitClosureScope(Z, target);
+      MakeImplicitClosureScope(Z, Class::Handle(Z, target.Owner()));
   fragment += AllocateContext(implicit_closure_scope->context_variables());
   LocalVariable* context = MakeTemporary();
 
@@ -982,7 +1102,7 @@
   // The context is on top of the operand stack.  Store `this`.  The context
   // doesn't need a parent pointer because it doesn't close over anything
   // else.
-  fragment += LoadLocal(scopes_->this_variable);
+  fragment += LoadLocal(parsed_function_->receiver_var());
   fragment += StoreInstanceField(
       TokenPosition::kNoSource,
       Slot::GetContextVariableSlotFor(
@@ -1181,8 +1301,7 @@
   // check them again at the call-site.
   if (dart_function.IsClosureFunction() && !check_bounds.is_empty() &&
       FLAG_eliminate_type_checks) {
-    LocalVariable* closure =
-        parsed_function_->node_sequence()->scope()->VariableAt(0);
+    LocalVariable* closure = parsed_function_->ParameterVariable(0);
     *implicit_checks += TestDelayedTypeArgs(closure, /*present=*/{},
                                             /*absent=*/check_bounds);
   } else {
@@ -1192,8 +1311,7 @@
   const intptr_t num_params = dart_function.NumParameters();
   for (intptr_t i = dart_function.NumImplicitParameters(); i < num_params;
        ++i) {
-    LocalVariable* param =
-        parsed_function_->node_sequence()->scope()->VariableAt(i);
+    LocalVariable* param = parsed_function_->ParameterVariable(i);
     if (!param->needs_type_check()) {
       continue;
     }
@@ -1242,6 +1360,34 @@
   return instruction_cursor;
 }
 
+RawArray* FlowGraphBuilder::GetOptionalParameterNames(
+    const Function& function) {
+  if (!function.HasOptionalNamedParameters()) {
+    return Array::null();
+  }
+
+  const intptr_t num_fixed_params = function.num_fixed_parameters();
+  const intptr_t num_opt_params = function.NumOptionalNamedParameters();
+  const auto& names = Array::Handle(Z, Array::New(num_opt_params, Heap::kOld));
+  auto& name = String::Handle(Z);
+  for (intptr_t i = 0; i < num_opt_params; ++i) {
+    name = function.ParameterNameAt(num_fixed_params + i);
+    names.SetAt(i, name);
+  }
+  return names.raw();
+}
+
+Fragment FlowGraphBuilder::PushExplicitParameters(const Function& function) {
+  Fragment instructions;
+  for (intptr_t i = function.NumImplicitParameters(),
+                n = function.NumParameters();
+       i < n; ++i) {
+    instructions += LoadLocal(parsed_function_->ParameterVariable(i));
+    instructions += PushArgument();
+  }
+  return instructions;
+}
+
 FlowGraph* FlowGraphBuilder::BuildGraphOfMethodExtractor(
     const Function& method) {
   // A method extractor is the implicit getter for a method.
@@ -1299,8 +1445,7 @@
 
   // The receiver is the first argument to noSuchMethod, and it is the first
   // argument passed to the dispatcher function.
-  LocalScope* scope = parsed_function_->node_sequence()->scope();
-  body += LoadLocal(scope->VariableAt(0));
+  body += LoadLocal(parsed_function_->ParameterVariable(0));
   body += PushArgument();
 
   // The second argument to noSuchMethod is an invocation mirror.  Push the
@@ -1330,7 +1475,7 @@
   for (intptr_t i = 0; i < descriptor.PositionalCount(); ++i) {
     body += LoadLocal(array);
     body += IntConstant(receiver_index + i);
-    body += LoadLocal(scope->VariableAt(i));
+    body += LoadLocal(parsed_function_->ParameterVariable(i));
     body += StoreIndexed(kArrayCid);
   }
   String& name = String::Handle(Z);
@@ -1340,7 +1485,7 @@
     name = Symbols::New(H.thread(), name);
     body += LoadLocal(array);
     body += IntConstant(receiver_index + descriptor.PositionAt(i));
-    body += LoadLocal(scope->VariableAt(parameter_index));
+    body += LoadLocal(parsed_function_->ParameterVariable(parameter_index));
     body += StoreIndexed(kArrayCid);
   }
   body += PushArgument();
@@ -1432,8 +1577,6 @@
   Fragment body(instruction_cursor);
   body += CheckStackOverflowInPrologue(function.token_pos());
 
-  LocalScope* scope = parsed_function_->node_sequence()->scope();
-
   if (descriptor.TypeArgsLen() > 0) {
     LocalVariable* type_args = parsed_function_->function_type_arguments();
     ASSERT(type_args != NULL);
@@ -1443,13 +1586,13 @@
 
   LocalVariable* closure = NULL;
   if (is_closure_call) {
-    closure = scope->VariableAt(0);
+    closure = parsed_function_->ParameterVariable(0);
 
     // The closure itself is the first argument.
     body += LoadLocal(closure);
   } else {
     // Invoke the getter to get the field value.
-    body += LoadLocal(scope->VariableAt(0));
+    body += LoadLocal(parsed_function_->ParameterVariable(0));
     body += PushArgument();
     const intptr_t kTypeArgsLen = 0;
     const intptr_t kNumArgsChecked = 1;
@@ -1463,7 +1606,7 @@
   // Push all arguments onto the stack.
   intptr_t pos = 1;
   for (; pos < descriptor.Count(); pos++) {
-    body += LoadLocal(scope->VariableAt(pos));
+    body += LoadLocal(parsed_function_->ParameterVariable(pos));
     body += PushArgument();
   }
 
@@ -1513,14 +1656,14 @@
       body += LoadArgDescriptor();
       body += LoadNativeField(Slot::ArgumentsDescriptor_count());
       body += LoadLocal(parsed_function_->current_context_var());
-      body += LoadNativeField(
-          Slot::GetContextVariableSlotFor(thread_, *scopes_->this_variable));
+      body += LoadNativeField(Slot::GetContextVariableSlotFor(
+          thread_, *parsed_function_->receiver_var()));
       body += StoreFpRelativeSlot(
           kWordSize * compiler::target::frame_layout.param_end_from_fp);
     } else {
       body += LoadLocal(parsed_function_->current_context_var());
-      body += LoadNativeField(
-          Slot::GetContextVariableSlotFor(thread_, *scopes_->this_variable));
+      body += LoadNativeField(Slot::GetContextVariableSlotFor(
+          thread_, *parsed_function_->receiver_var()));
       body += StoreFpRelativeSlot(
           kWordSize * (compiler::target::frame_layout.param_end_from_fp +
                        function.NumParameters()));
@@ -1655,12 +1798,11 @@
       body += Constant(type);
     } else {
       body += LoadLocal(parsed_function_->current_context_var());
-      body += LoadNativeField(
-          Slot::GetContextVariableSlotFor(thread_, *scopes_->this_variable));
+      body += LoadNativeField(Slot::GetContextVariableSlotFor(
+          thread_, *parsed_function_->receiver_var()));
     }
   } else {
-    LocalScope* scope = parsed_function_->node_sequence()->scope();
-    body += LoadLocal(scope->VariableAt(0));
+    body += LoadLocal(parsed_function_->ParameterVariable(0));
   }
   body += PushArgument();
 
@@ -1705,8 +1847,7 @@
 
   // Push the number of delayed type arguments.
   if (function.IsClosureFunction()) {
-    LocalVariable* closure =
-        parsed_function_->node_sequence()->scope()->VariableAt(0);
+    LocalVariable* closure = parsed_function_->ParameterVariable(0);
     Fragment then;
     then += IntConstant(function.NumTypeParameters());
     then += StoreLocal(TokenPosition::kNoSource, argument_count_var);
@@ -2000,50 +2141,28 @@
     body += PushArgument();
   }
 
-  // Load all the arguments.
-  auto scope = parsed_function_->node_sequence()->scope();
-
+  // Push receiver.
   if (!target.is_static()) {
     // The context has a fixed shape: a single variable which is the
     // closed-over receiver.
-    body += LoadLocal(scope->VariableAt(0));
+    body += LoadLocal(parsed_function_->ParameterVariable(0));
     body += LoadNativeField(Slot::Closure_context());
-    body += LoadNativeField(
-        Slot::GetContextVariableSlotFor(thread_, *scopes_->this_variable));
+    body += LoadNativeField(Slot::GetContextVariableSlotFor(
+        thread_, *parsed_function_->receiver_var()));
     body += PushArgument();
   }
 
-  // Positional.
-  intptr_t arg_index = function.NumImplicitParameters();
-  const intptr_t named_argument_count = function.NumOptionalNamedParameters();
-  const intptr_t positional_argument_count = function.NumParameters() -
-                                             function.NumImplicitParameters() -
-                                             named_argument_count;
-  for (intptr_t i = 0; i < positional_argument_count; ++i, ++arg_index) {
-    body += LoadLocal(scope->VariableAt(arg_index));  // ith variable offset.
-    body += PushArgument();
-  }
+  body += PushExplicitParameters(function);
 
-  // Named.
-  Array& argument_names = Array::ZoneHandle(Z);
-  if (named_argument_count > 0) {
-    argument_names = Array::New(named_argument_count, Heap::kOld);
-    String& name = String::Handle(Z);
-    for (intptr_t i = 0; i < named_argument_count; ++i, ++arg_index) {
-      body += LoadLocal(scope->VariableAt(arg_index));
-      body += PushArgument();
-
-      name = function.ParameterNameAt(arg_index);
-      argument_names.SetAt(i, name);
-    }
-  }
-
-  // Forward them to the parent.
-  intptr_t argument_count = positional_argument_count + named_argument_count;
-  if (!parent.is_static()) {
-    ++argument_count;
-  }
+  // Forward parameters to the target.
+  intptr_t argument_count = function.NumParameters() -
+                            function.NumImplicitParameters() +
+                            (target.is_static() ? 0 : 1);
   ASSERT(argument_count == target.NumParameters());
+
+  Array& argument_names =
+      Array::ZoneHandle(Z, GetOptionalParameterNames(function));
+
   body += StaticCall(TokenPosition::kNoSource, target, argument_count,
                      argument_names, ICData::kNoRebind,
                      /* result_type = */ NULL, type_args_len);
@@ -2055,7 +2174,7 @@
   FunctionEntryInstr* extra_entry = nullptr;
   if (function.MayHaveUncheckedEntryPoint(I)) {
     // The prologue for a closure will always have context handling (e.g.
-    // setting up the 'this_variable'), but we don't need it on the unchecked
+    // setting up the receiver variable), but we don't need it on the unchecked
     // entry because the only time we reference this is for loading the
     // receiver, which we fetch directly from the context.
     if (PrologueBuilder::PrologueSkippableOnUncheckedEntry(function)) {
@@ -2091,6 +2210,344 @@
                            prologue_info);
 }
 
+FlowGraph* FlowGraphBuilder::BuildGraphOfFieldAccessor(
+    const Function& function) {
+  ASSERT(function.IsImplicitGetterOrSetter() ||
+         function.IsDynamicInvocationForwarder());
+
+  // Instead of building a dynamic invocation forwarder that checks argument
+  // type and then invokes original setter we simply generate the type check
+  // and inlined field store. Scope builder takes care of setting correct
+  // type check mode in this case.
+  const bool is_setter = function.IsDynamicInvocationForwarder() ||
+                         function.IsImplicitSetterFunction();
+  const bool is_method = !function.IsStaticFunction();
+
+  Field& field = Field::ZoneHandle(Z, function.accessor_field());
+
+  graph_entry_ =
+      new (Z) GraphEntryInstr(*parsed_function_, Compiler::kNoOSRDeoptId);
+
+  auto normal_entry = BuildFunctionEntry(graph_entry_);
+  graph_entry_->set_normal_entry(normal_entry);
+
+  Fragment body(normal_entry);
+  if (is_setter) {
+    LocalVariable* setter_value =
+        parsed_function_->ParameterVariable(is_method ? 1 : 0);
+
+    // We only expect to generate a dynamic invocation forwarder if
+    // the value needs type check.
+    ASSERT(!function.IsDynamicInvocationForwarder() ||
+           setter_value->needs_type_check());
+    if (is_method) {
+      body += LoadLocal(parsed_function_->ParameterVariable(0));
+    }
+    body += LoadLocal(setter_value);
+    if (I->argument_type_checks() && setter_value->needs_type_check()) {
+      body += CheckAssignable(setter_value->type(), setter_value->name(),
+                              AssertAssignableInstr::kParameterCheck);
+    }
+    if (is_method) {
+      body += StoreInstanceFieldGuarded(field, false);
+    } else {
+      body += StoreStaticField(TokenPosition::kNoSource, field);
+    }
+    body += NullConstant();
+  } else if (is_method) {
+    body += LoadLocal(parsed_function_->ParameterVariable(0));
+    body += LoadField(field);
+  } else if (field.is_const()) {
+    // If the parser needs to know the value of an uninitialized constant field
+    // it will set the value to the transition sentinel (used to detect circular
+    // initialization) and then call the implicit getter.  Thus, the getter
+    // cannot contain the InitStaticField instruction that normal static getters
+    // contain because it would detect spurious circular initialization when it
+    // checks for the transition sentinel.
+    ASSERT(!field.IsUninitialized());
+    body += Constant(Instance::ZoneHandle(Z, field.StaticValue()));
+  } else {
+    // The field always has an initializer because static fields without
+    // initializers are initialized eagerly and do not have implicit getters.
+    ASSERT(field.has_initializer());
+    body += Constant(field);
+    body += InitStaticField(field);
+    body += Constant(field);
+    body += LoadStaticField();
+  }
+  body += Return(TokenPosition::kNoSource);
+
+  PrologueInfo prologue_info(-1, -1);
+  return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_,
+                           prologue_info);
+}
+
+FlowGraph* FlowGraphBuilder::BuildGraphOfDynamicInvocationForwarder(
+    const Function& function) {
+  auto& name = String::Handle(Z, function.name());
+  name = Function::DemangleDynamicInvocationForwarderName(name);
+  const auto& owner = Class::Handle(Z, function.Owner());
+  const auto& target =
+      Function::ZoneHandle(Z, owner.LookupDynamicFunction(name));
+  ASSERT(!target.IsNull());
+  ASSERT(!target.IsImplicitGetterFunction());
+
+  if (target.IsImplicitSetterFunction()) {
+    return BuildGraphOfFieldAccessor(function);
+  }
+
+  graph_entry_ = new (Z) GraphEntryInstr(*parsed_function_, osr_id_);
+
+  auto normal_entry = BuildFunctionEntry(graph_entry_);
+  graph_entry_->set_normal_entry(normal_entry);
+
+  PrologueInfo prologue_info(-1, -1);
+  auto instruction_cursor = BuildPrologue(normal_entry, &prologue_info);
+
+  Fragment body;
+  if (!function.is_native()) {
+    body += CheckStackOverflowInPrologue(function.token_pos());
+  }
+
+  ASSERT(parsed_function_->node_sequence()->scope()->num_context_variables() ==
+         0);
+
+  // Should never build a dynamic invocation forwarder for equality
+  // operator.
+  ASSERT(function.name() != Symbols::EqualOperator().raw());
+
+  // Even if the caller did not pass argument vector we would still
+  // call the target with instantiate-to-bounds type arguments.
+  body += BuildDefaultTypeHandling(function);
+
+  // Build argument type checks that complement those that are emitted in the
+  // target.
+  BuildArgumentTypeChecks(
+      TypeChecksToBuild::kCheckNonCovariantTypeParameterBounds, &body, &body,
+      nullptr);
+
+  // Push all arguments and invoke the original method.
+
+  intptr_t type_args_len = 0;
+  if (function.IsGeneric()) {
+    type_args_len = function.NumTypeParameters();
+    ASSERT(parsed_function_->function_type_arguments() != nullptr);
+    body += LoadLocal(parsed_function_->function_type_arguments());
+    body += PushArgument();
+  }
+
+  // Push receiver.
+  ASSERT(function.NumImplicitParameters() == 1);
+  body += LoadLocal(parsed_function_->receiver_var());
+  body += PushArgument();
+
+  body += PushExplicitParameters(function);
+
+  const intptr_t argument_count = function.NumParameters();
+  const auto& argument_names =
+      Array::ZoneHandle(Z, GetOptionalParameterNames(function));
+
+  body += StaticCall(TokenPosition::kNoSource, target, argument_count,
+                     argument_names, ICData::kNoRebind, nullptr, type_args_len);
+
+  // Later optimization passes assume that result of a x.[]=(...) call is not
+  // used. We must guarantee this invariant because violation will lead to an
+  // illegal IL once we replace x.[]=(...) with a sequence that does not
+  // actually produce any value. See http://dartbug.com/29135 for more details.
+  if (name.raw() == Symbols::AssignIndexToken().raw()) {
+    body += Drop();
+    body += NullConstant();
+  }
+
+  body += Return(TokenPosition::kNoSource);
+
+  instruction_cursor->LinkTo(body.entry);
+
+  // When compiling for OSR, use a depth first search to find the OSR
+  // entry and make graph entry jump to it instead of normal entry.
+  // Catch entries are always considered reachable, even if they
+  // become unreachable after OSR.
+  if (IsCompiledForOsr()) {
+    graph_entry_->RelinkToOsrEntry(Z, last_used_block_id_ + 1);
+  }
+  return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_,
+                           prologue_info);
+}
+
+Fragment FlowGraphBuilder::UnboxTruncate(Representation to) {
+  auto* unbox = UnboxInstr::Create(to, Pop(), DeoptId::kNone,
+                                   Instruction::kNotSpeculative);
+  Push(unbox);
+  return Fragment(unbox);
+}
+
+Fragment FlowGraphBuilder::LoadAddressFromFfiPointer() {
+  Fragment test;
+  TargetEntryInstr* null_entry;
+  TargetEntryInstr* not_null_entry;
+  JoinEntryInstr* join = BuildJoinEntry();
+
+  LocalVariable* result = parsed_function_->expression_temp_var();
+
+  LocalVariable* pointer = MakeTemporary();
+  test += LoadLocal(pointer);
+  test += BranchIfNull(&null_entry, &not_null_entry);
+
+  Fragment load_0(null_entry);
+  load_0 += IntConstant(0);
+  load_0 += StoreLocal(TokenPosition::kNoSource, result);
+  load_0 += Drop();
+  load_0 += Goto(join);
+
+  Fragment unbox(not_null_entry);
+  unbox += LoadLocal(pointer);
+  unbox += LoadNativeField(Slot::Pointer_c_memory_address());
+  unbox += StoreLocal(TokenPosition::kNoSource, result);
+  unbox += Drop();
+  unbox += Goto(join);
+
+  Fragment done{test.entry, join};
+  done += Drop();
+  done += LoadLocal(result);
+
+  return done;
+}
+
+Fragment FlowGraphBuilder::Box(Representation from) {
+  BoxInstr* box = BoxInstr::Create(from, Pop());
+  Push(box);
+  return Fragment(box);
+}
+
+Fragment FlowGraphBuilder::FfiPointerFromAddress(const Type& result_type) {
+  Fragment test;
+  TargetEntryInstr* null_entry;
+  TargetEntryInstr* not_null_entry;
+  JoinEntryInstr* join = BuildJoinEntry();
+
+  LocalVariable* address = MakeTemporary();
+  LocalVariable* result = parsed_function_->expression_temp_var();
+
+  test += LoadLocal(address);
+  test += IntConstant(0);
+  test += BranchIfEqual(&null_entry, &not_null_entry);
+
+  // If the result is 0, we return null because "0 means null".
+  Fragment load_null(null_entry);
+  {
+    load_null += NullConstant();
+    load_null += StoreLocal(TokenPosition::kNoSource, result);
+    load_null += Drop();
+    load_null += Goto(join);
+  }
+
+  Fragment box(not_null_entry);
+  {
+    Class& result_class = Class::ZoneHandle(Z, result_type.type_class());
+    TypeArguments& args = TypeArguments::ZoneHandle(Z, result_type.arguments());
+
+    // A kernel transform for FFI in the front-end ensures that type parameters
+    // do not appear in the type arguments to a any Pointer classes in an FFI
+    // signature.
+    ASSERT(args.IsNull() || args.IsInstantiated());
+
+    box += Constant(args);
+    box += PushArgument();
+    box += AllocateObject(TokenPosition::kNoSource, result_class, 1);
+    LocalVariable* pointer = MakeTemporary();
+    box += LoadLocal(pointer);
+    box += LoadLocal(address);
+    box += StoreInstanceField(TokenPosition::kNoSource,
+                              Slot::Pointer_c_memory_address());
+    box += StoreLocal(TokenPosition::kNoSource, result);
+    box += Drop();
+    box += Goto(join);
+  }
+
+  Fragment rest(test.entry, join);
+  rest += Drop();
+  rest += LoadLocal(result);
+
+  return rest;
+}
+
+FlowGraph* FlowGraphBuilder::BuildGraphOfFfiTrampoline(
+    const Function& function) {
+#if !defined(TARGET_ARCH_X64)
+  UNREACHABLE();
+#else
+  graph_entry_ =
+      new (Z) GraphEntryInstr(*parsed_function_, Compiler::kNoOSRDeoptId);
+
+  auto normal_entry = BuildFunctionEntry(graph_entry_);
+  graph_entry_->set_normal_entry(normal_entry);
+
+  PrologueInfo prologue_info(-1, -1);
+
+  BlockEntryInstr* instruction_cursor =
+      BuildPrologue(normal_entry, &prologue_info);
+
+  Fragment body(instruction_cursor);
+  body += CheckStackOverflowInPrologue(function.token_pos());
+
+  const Function& signature = Function::ZoneHandle(Z, function.FfiCSignature());
+  const auto& arg_reps = *compiler::ffi::ArgumentRepresentations(signature);
+  const auto& arg_locs = *compiler::ffi::ArgumentLocations(arg_reps);
+
+  BuildArgumentTypeChecks(TypeChecksToBuild::kCheckAllTypeParameterBounds,
+                          &body, &body, &body);
+
+  // Unbox and push the arguments.
+  AbstractType& ffi_type = AbstractType::Handle(Z);
+  for (intptr_t pos = 1; pos < function.num_fixed_parameters(); pos++) {
+    body += LoadLocal(parsed_function_->ParameterVariable(pos));
+    ffi_type = signature.ParameterTypeAt(pos);
+
+    // Check for 'null'. Only ffi.Pointers are allowed to be null.
+    if (!compiler::ffi::NativeTypeIsPointer(ffi_type)) {
+      body += LoadLocal(parsed_function_->ParameterVariable(pos));
+      body <<=
+          new (Z) CheckNullInstr(Pop(), String::ZoneHandle(Z, function.name()),
+                                 GetNextDeoptId(), TokenPosition::kNoSource);
+    }
+
+    if (compiler::ffi::NativeTypeIsPointer(ffi_type)) {
+      body += LoadAddressFromFfiPointer();
+      body += UnboxTruncate(kUnboxedIntPtr);
+    } else {
+      body += UnboxTruncate(arg_reps[pos - 1]);
+    }
+  }
+
+  // Push the function pointer, which is stored (boxed) in the first slot of the
+  // context.
+  body += LoadLocal(parsed_function_->ParameterVariable(0));
+  body += LoadNativeField(Slot::Closure_context());
+  body += LoadNativeField(Slot::GetContextVariableSlotFor(
+      thread_, *MakeImplicitClosureScope(
+                    Z, Class::Handle(I->object_store()->ffi_pointer_class()))
+                    ->context_variables()[0]));
+  body += UnboxTruncate(kUnboxedIntPtr);
+  body += FfiCall(signature, arg_reps, arg_locs);
+
+  ffi_type = signature.result_type();
+  if (compiler::ffi::NativeTypeIsPointer(ffi_type)) {
+    body += Box(kUnboxedIntPtr);
+    body += FfiPointerFromAddress(Type::Cast(ffi_type));
+  } else if (compiler::ffi::NativeTypeIsVoid(ffi_type)) {
+    body += Drop();
+    body += NullConstant();
+  } else {
+    body += Box(compiler::ffi::ResultRepresentation(signature));
+  }
+
+  body += Return(TokenPosition::kNoSource);
+
+  return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_,
+                           prologue_info);
+#endif
+}
+
 void FlowGraphBuilder::SetCurrentTryCatchBlock(TryCatchBlock* try_catch_block) {
   try_catch_block_ = try_catch_block;
   SetCurrentTryIndex(try_catch_block == nullptr ? kInvalidTryIndex
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index a2cb7ca..1e76f9a 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -91,13 +91,23 @@
   BlockEntryInstr* BuildPrologue(BlockEntryInstr* normal_entry,
                                  PrologueInfo* prologue_info);
 
+  // Return names of optional named parameters of [function].
+  RawArray* GetOptionalParameterNames(const Function& function);
+
+  // Generate fragment which pushes all explicit parameters of [function].
+  Fragment PushExplicitParameters(const Function& function);
+
   FlowGraph* BuildGraphOfMethodExtractor(const Function& method);
   FlowGraph* BuildGraphOfNoSuchMethodDispatcher(const Function& function);
   FlowGraph* BuildGraphOfInvokeFieldDispatcher(const Function& function);
+  FlowGraph* BuildGraphOfFfiTrampoline(const Function& function);
 
   Fragment NativeFunctionBody(const Function& function,
                               LocalVariable* first_parameter);
 
+  Fragment BuildTypedDataViewFactoryConstructor(const Function& function,
+                                                classid_t cid);
+
   Fragment EnterScope(intptr_t kernel_offset,
                       const LocalScope** scope = nullptr);
   Fragment ExitScope(intptr_t kernel_offset);
@@ -142,9 +152,11 @@
                        intptr_t argument_count,
                        const Array& argument_names,
                        bool use_unchecked_entry = false);
+  Fragment FfiCall(const Function& signature,
+                   const ZoneGrowableArray<Representation>& arg_reps,
+                   const ZoneGrowableArray<Location>& arg_locs);
 
   Fragment RethrowException(TokenPosition position, int catch_try_index);
-  Fragment LoadClassId();
   Fragment LoadLocal(LocalVariable* variable);
   Fragment InitStaticField(const Field& field);
   Fragment NativeCall(const String* name, const Function* function);
@@ -198,6 +210,25 @@
   bool NeedsDebugStepCheck(Value* value, TokenPosition position);
   Fragment DebugStepCheck(TokenPosition position);
 
+  // Truncates (instead of deoptimizing) if the origin does not fit into the
+  // target representation.
+  Fragment UnboxTruncate(Representation to);
+
+  // Sign-extends kUnboxedInt32 and zero-extends kUnboxedUint32.
+  Fragment Box(Representation from);
+
+  // Pops an 'ffi.Pointer' off the stack.
+  // If it's null, pushes 0.
+  // Otherwise pushes the address (in boxed representation).
+  Fragment LoadAddressFromFfiPointer();
+
+  // Reverse of 'LoadPointerFromFfiPointer':
+  // Pops an integer off the the stack.
+  // If it's zero, pushes null.
+  // If it's nonzero, creates an 'ffi.Pointer' holding the address and pushes
+  // the pointer.
+  Fragment FfiPointerFromAddress(const Type& result_type);
+
   LocalVariable* LookupVariable(intptr_t kernel_offset);
 
   // Build argument type checks for the current function.
@@ -258,6 +289,8 @@
   // Builds flow graph for implicit closure function (tear-off).
   //
   // ParsedFunction should have the following information:
+  //  - DefaultFunctionTypeArguments()
+  //  - function_type_arguments()
   //  - default_parameter_values()
   //  - is_forwarding_stub()
   //  - forwarding_stub_super_target()
@@ -268,6 +301,32 @@
   //
   FlowGraph* BuildGraphOfImplicitClosureFunction(const Function& function);
 
+  // Builds flow graph of implicit field getter, setter, or a
+  // dynamic invocation forwarder to a field setter.
+  //
+  // If field is const, its value should be evaluated and stored in
+  //  - StaticValue()
+  //
+  // Scope should be populated with parameter variables including
+  //  - needs_type_check()
+  //
+  FlowGraph* BuildGraphOfFieldAccessor(const Function& function);
+
+  // Builds flow graph of dynamic invocation forwarder.
+  //
+  // ParsedFunction should have the following information:
+  //  - DefaultFunctionTypeArguments()
+  //  - function_type_arguments()
+  //  - default_parameter_values()
+  //  - is_forwarding_stub()
+  //  - forwarding_stub_super_target()
+  //
+  // Scope should be populated with parameter variables including
+  //  - needs_type_check()
+  //  - is_explicit_covariant_parameter()
+  //
+  FlowGraph* BuildGraphOfDynamicInvocationForwarder(const Function& function);
+
   TranslationHelper translation_helper_;
   Thread* thread_;
   Zone* zone_;
@@ -283,6 +342,7 @@
   intptr_t try_depth_;
   intptr_t catch_depth_;
   intptr_t for_in_depth_;
+  intptr_t block_expression_depth_;
 
   GraphEntryInstr* graph_entry_;
 
@@ -355,13 +415,15 @@
                intptr_t loop_depth,
                intptr_t for_in_depth,
                intptr_t try_depth,
-               intptr_t catch_depth)
+               intptr_t catch_depth,
+               intptr_t block_expression_depth)
       : breakable_block_(breakable_block),
         switch_block_(switch_block),
         loop_depth_(loop_depth),
         for_in_depth_(for_in_depth),
         try_depth_(try_depth),
-        catch_depth_(catch_depth) {}
+        catch_depth_(catch_depth),
+        block_expression_depth_(block_expression_depth) {}
 
   void assignTo(FlowGraphBuilder* builder) const {
     builder->breakable_block_ = breakable_block_;
@@ -370,6 +432,7 @@
     builder->for_in_depth_ = for_in_depth_;
     builder->try_depth_ = try_depth_;
     builder->catch_depth_ = catch_depth_;
+    builder->block_expression_depth_ = block_expression_depth_;
   }
 
  private:
@@ -379,6 +442,7 @@
   const intptr_t for_in_depth_;
   const intptr_t try_depth_;
   const intptr_t catch_depth_;
+  const intptr_t block_expression_depth_;
 };
 
 class SwitchBlock {
@@ -505,7 +569,8 @@
                builder_->loop_depth_,
                builder_->for_in_depth_,
                builder_->try_depth_ - 1,
-               builder_->catch_depth_) {
+               builder_->catch_depth_,
+               builder_->block_expression_depth_) {
     builder_->try_finally_block_ = this;
   }
   ~TryFinallyBlock() { builder_->try_finally_block_ = outer_; }
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 6194c70..ebd4ed7 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -2197,6 +2197,13 @@
       ReadPosition();           // read position.
       SkipListOfExpressions();  // read list of expressions.
       return;
+    case kListConcatenation:
+    case kSetConcatenation:
+    case kMapConcatenation:
+      // Collection concatenation operations are removed by the constant
+      // evaluator.
+      UNREACHABLE();
+      break;
     case kIsExpression:
       ReadPosition();    // read position.
       SkipExpression();  // read operand.
@@ -2255,10 +2262,10 @@
       SkipVariableDeclaration();  // read variable declaration.
       SkipExpression();           // read expression.
       return;
-    case kBlockExpression: {
-      UNIMPLEMENTED();
+    case kBlockExpression:
+      SkipStatementList();
+      SkipExpression();  // read expression.
       return;
-    }
     case kInstantiation:
       SkipExpression();       // read expression.
       SkipListOfDartTypes();  // read type arguments.
diff --git a/runtime/vm/compiler/frontend/prologue_builder.cc b/runtime/vm/compiler/frontend/prologue_builder.cc
index 1149d15..3c5103c 100644
--- a/runtime/vm/compiler/frontend/prologue_builder.cc
+++ b/runtime/vm/compiler/frontend/prologue_builder.cc
@@ -29,7 +29,7 @@
 
 bool PrologueBuilder::HasEmptyPrologue(const Function& function) {
   return !function.HasOptionalParameters() && !function.IsGeneric() &&
-         !function.IsClosureFunction();
+         !function.CanReceiveDynamicInvocation();
 }
 
 BlockEntryInstr* PrologueBuilder::BuildPrologue(BlockEntryInstr* entry,
@@ -41,7 +41,7 @@
 
   const bool load_optional_arguments = function_.HasOptionalParameters();
   const bool expect_type_args = function_.IsGeneric();
-  const bool check_arguments = function_.IsClosureFunction();
+  const bool check_arguments = function_.CanReceiveDynamicInvocation();
 
   Fragment prologue = Fragment(entry);
   JoinEntryInstr* nsm = NULL;
@@ -383,9 +383,7 @@
 }
 
 Fragment PrologueBuilder::BuildClosureContextHandling() {
-  LocalScope* scope = parsed_function_->node_sequence()->scope();
-  LocalVariable* closure_parameter = scope->VariableAt(0);
-
+  LocalVariable* closure_parameter = parsed_function_->ParameterVariable(0);
   LocalVariable* context = parsed_function_->current_context_var();
 
   // Load closure.context & store it into the context variable.
@@ -419,8 +417,7 @@
   handling += TestTypeArgsLen(store_null, store_type_args, 0);
 
   if (parsed_function_->function().IsClosureFunction()) {
-    LocalVariable* closure =
-        parsed_function_->node_sequence()->scope()->VariableAt(0);
+    LocalVariable* closure = parsed_function_->ParameterVariable(0);
 
     // Currently, delayed type arguments can only be introduced through type
     // inference in the FE. So if they are present, we can assume they are
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index 71c2e61..e23bf10 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -96,14 +96,15 @@
     // load instantiator type arguments if they are needed.
     Class& klass = Class::Handle(Z, function.Owner());
     Type& klass_type = H.GetDeclarationType(klass);
-    result_->this_variable =
+    LocalVariable* receiver_variable =
         MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                      Symbols::This(), klass_type);
-    result_->this_variable->set_is_captured();
+    parsed_function_->set_receiver_var(receiver_variable);
+    receiver_variable->set_is_captured();
     enclosing_scope = new (Z) LocalScope(NULL, 0, 0);
     enclosing_scope->set_context_level(0);
-    enclosing_scope->AddVariable(result_->this_variable);
-    enclosing_scope->AddContextVariable(result_->this_variable);
+    enclosing_scope->AddVariable(receiver_variable);
+    enclosing_scope->AddContextVariable(receiver_variable);
   } else if (function.IsLocalFunction()) {
     enclosing_scope = LocalScope::RestoreOuterScope(
         ContextScope::Handle(Z, function.context_scope()));
@@ -126,6 +127,10 @@
     scope_->AddVariable(parsed_function_->arg_desc_var());
   }
 
+  if (parsed_function_->function().IsFfiTrampoline()) {
+    needs_expr_temp_ = true;
+  }
+
   LocalVariable* context_var = parsed_function_->current_context_var();
   context_var->set_is_forced_stack();
   scope_->AddVariable(context_var);
@@ -170,7 +175,7 @@
             MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                          Symbols::This(), klass_type);
         scope_->InsertParameterAt(pos++, variable);
-        result_->this_variable = variable;
+        parsed_function_->set_receiver_var(variable);
 
         // We visit instance field initializers because they might contain
         // [Let] expressions and we need to have a mapping.
@@ -279,7 +284,7 @@
             MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                          Symbols::This(), klass_type);
         scope_->InsertParameterAt(pos++, variable);
-        result_->this_variable = variable;
+        parsed_function_->set_receiver_var(variable);
       }
       if (is_setter) {
         result_->setter_value = MakeVariable(
@@ -290,12 +295,10 @@
 
         if (is_method &&
             MethodCanSkipTypeChecksForNonCovariantArguments(function, attrs)) {
-          FieldHelper field_helper(&helper_);
-          field_helper.ReadUntilIncluding(FieldHelper::kFlags);
-
-          if (field_helper.IsCovariant()) {
+          const auto& field = Field::Handle(Z, function.accessor_field());
+          if (field.is_covariant()) {
             result_->setter_value->set_is_explicit_covariant_parameter();
-          } else if (!field_helper.IsGenericCovariantImpl() ||
+          } else if (!field.is_generic_covariant_impl() ||
                      (!attrs.has_non_this_uses && !attrs.has_tearoff_uses)) {
             result_->setter_value->set_type_check_mode(
                 LocalVariable::kTypeCheckedByCaller);
@@ -320,16 +323,16 @@
       if (helper_.PeekTag() == kField) {
 #ifdef DEBUG
         String& name = String::Handle(Z, function.name());
-        ASSERT(Function::IsDynamicInvocationForwaderName(name));
+        ASSERT(Function::IsDynamicInvocationForwarderName(name));
         name = Function::DemangleDynamicInvocationForwarderName(name);
         ASSERT(Field::IsSetterName(name));
 #endif
         // Create [this] variable.
         const Class& klass = Class::Handle(Z, function.Owner());
-        result_->this_variable =
+        parsed_function_->set_receiver_var(
             MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
-                         Symbols::This(), H.GetDeclarationType(klass));
-        scope_->InsertParameterAt(0, result_->this_variable);
+                         Symbols::This(), H.GetDeclarationType(klass)));
+        scope_->InsertParameterAt(0, parsed_function_->receiver_var());
 
         // Create setter value variable.
         result_->setter_value = MakeVariable(
@@ -345,10 +348,10 @@
         // Create [this] variable.
         intptr_t pos = 0;
         Class& klass = Class::Handle(Z, function.Owner());
-        result_->this_variable =
+        parsed_function_->set_receiver_var(
             MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
-                         Symbols::This(), H.GetDeclarationType(klass));
-        scope_->InsertParameterAt(pos++, result_->this_variable);
+                         Symbols::This(), H.GetDeclarationType(klass)));
+        scope_->InsertParameterAt(pos++, parsed_function_->receiver_var());
 
         // Create all positional and named parameters.
         AddPositionalAndNamedParameters(
@@ -368,22 +371,24 @@
           MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                        Symbols::This(), klass_type);
       scope_->InsertParameterAt(0, variable);
-      result_->this_variable = variable;
+      parsed_function_->set_receiver_var(variable);
       break;
     }
     case RawFunction::kNoSuchMethodDispatcher:
     case RawFunction::kInvokeFieldDispatcher:
+    case RawFunction::kFfiTrampoline:
       for (intptr_t i = 0; i < function.NumParameters(); ++i) {
-        LocalVariable* variable =
-            MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
-                         String::ZoneHandle(Z, function.ParameterNameAt(i)),
-                         AbstractType::dynamic_type());
+        LocalVariable* variable = MakeVariable(
+            TokenPosition::kNoSource, TokenPosition::kNoSource,
+            String::ZoneHandle(Z, function.ParameterNameAt(i)),
+            AbstractType::ZoneHandle(Z, function.IsFfiTrampoline()
+                                            ? function.ParameterTypeAt(i)
+                                            : Object::dynamic_type().raw()));
         scope_->InsertParameterAt(i, variable);
       }
       break;
     case RawFunction::kSignatureFunction:
     case RawFunction::kIrregexpFunction:
-    case RawFunction::kFfiTrampoline:
       UNREACHABLE();
   }
   if (needs_expr_temp_) {
@@ -513,12 +518,11 @@
   }
 
   if (function_node_helper.async_marker_ == FunctionNodeHelper::kSyncYielding) {
-    LocalScope* scope = parsed_function_->node_sequence()->scope();
     intptr_t offset = parsed_function_->function().num_fixed_parameters();
     for (intptr_t i = 0;
          i < parsed_function_->function().NumOptionalPositionalParameters();
          i++) {
-      scope->VariableAt(offset + i)->set_is_forced_stack();
+      parsed_function_->ParameterVariable(offset + i)->set_is_forced_stack();
     }
   }
 
@@ -678,13 +682,13 @@
       VisitExpression();                     // read value·
       return;
     case kSuperPropertyGet:
-      HandleSpecialLoad(&result_->this_variable, Symbols::This());
+      HandleLoadReceiver();
       helper_.ReadPosition();                // read position.
       helper_.SkipName();                    // read name.
       helper_.SkipCanonicalNameReference();  // read target_reference.
       return;
     case kSuperPropertySet:
-      HandleSpecialLoad(&result_->this_variable, Symbols::This());
+      HandleLoadReceiver();
       helper_.ReadPosition();                // read position.
       helper_.SkipName();                    // read name.
       VisitExpression();                     // read value.
@@ -714,7 +718,7 @@
       VisitArguments();                      // read arguments.
       return;
     case kSuperMethodInvocation:
-      HandleSpecialLoad(&result_->this_variable, Symbols::This());
+      HandleLoadReceiver();
       helper_.ReadPosition();  // read position.
       helper_.SkipName();      // read name.
       VisitArguments();        // read arguments.
@@ -758,6 +762,13 @@
       }
       return;
     }
+    case kListConcatenation:
+    case kSetConcatenation:
+    case kMapConcatenation:
+      // Collection concatenation operations are removed by the constant
+      // evaluator.
+      UNREACHABLE();
+      break;
     case kIsExpression:
       helper_.ReadPosition();  // read position.
       VisitExpression();       // read operand.
@@ -776,7 +787,7 @@
       VisitDartType();  // read type.
       return;
     case kThisExpression:
-      HandleSpecialLoad(&result_->this_variable, Symbols::This());
+      HandleLoadReceiver();
       return;
     case kRethrow:
       helper_.ReadPosition();  // read position.
@@ -833,7 +844,19 @@
       return;
     }
     case kBlockExpression: {
-      UNIMPLEMENTED();
+      PositionScope scope(&helper_.reader_);
+      intptr_t offset = helper_.ReaderOffset() - 1;  // -1 to include tag byte.
+
+      EnterScope(offset);
+
+      intptr_t list_length =
+          helper_.ReadListLength();  // read number of statements.
+      for (intptr_t i = 0; i < list_length; ++i) {
+        VisitStatement();  // read ith statement.
+      }
+      VisitExpression();  // read expression.
+
+      ExitScope(helper_.reader_.min_position(), helper_.reader_.max_position());
       return;
     }
     case kBigIntLiteral:
@@ -1342,7 +1365,7 @@
     // object, so we need to capture 'this'.
     Class& parent_class = Class::Handle(Z, function.Owner());
     if (index < parent_class.NumTypeParameters()) {
-      HandleSpecialLoad(&result_->this_variable, Symbols::This());
+      HandleLoadReceiver();
     }
   }
 
@@ -1689,6 +1712,24 @@
   return H.DartSymbolObfuscate(name);
 }
 
+void ScopeBuilder::HandleLoadReceiver() {
+  if (!parsed_function_->has_receiver_var() &&
+      current_function_scope_->parent() != nullptr) {
+    // Lazily populate receiver variable using the parent function scope.
+    parsed_function_->set_receiver_var(
+        current_function_scope_->parent()->LookupVariable(Symbols::This(),
+                                                          true));
+  }
+
+  if ((current_function_scope_->parent() != nullptr) ||
+      (scope_->function_level() > 0)) {
+    // Every scope we use the [receiver] from needs to be notified of the usage
+    // in order to ensure that preserving the context scope on that particular
+    // use-site also includes the [receiver].
+    scope_->CaptureVariable(parsed_function_->receiver_var());
+  }
+}
+
 void ScopeBuilder::HandleSpecialLoad(LocalVariable** variable,
                                      const String& symbol) {
   if (current_function_scope_->parent() != NULL) {
diff --git a/runtime/vm/compiler/frontend/scope_builder.h b/runtime/vm/compiler/frontend/scope_builder.h
index 12521be..b2227aa 100644
--- a/runtime/vm/compiler/frontend/scope_builder.h
+++ b/runtime/vm/compiler/frontend/scope_builder.h
@@ -116,6 +116,7 @@
 
   const String& GenerateName(const char* prefix, intptr_t suffix);
 
+  void HandleLoadReceiver();
   void HandleSpecialLoad(LocalVariable** variable, const String& symbol);
   void LookupCapturedVariableByName(LocalVariable** variable,
                                     const String& name);
@@ -171,8 +172,7 @@
 class ScopeBuildingResult : public ZoneAllocated {
  public:
   ScopeBuildingResult()
-      : this_variable(NULL),
-        type_arguments_variable(NULL),
+      : type_arguments_variable(NULL),
         switch_variable(NULL),
         finally_return_variable(NULL),
         setter_value(NULL),
@@ -184,9 +184,6 @@
   IntMap<LocalScope*> scopes;
   GrowableArray<FunctionScope> function_scopes;
 
-  // Only non-NULL for instance functions.
-  LocalVariable* this_variable;
-
   // Only non-NULL for factory constructor functions.
   LocalVariable* type_arguments_variable;
 
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
index bac9f7e..85c5e6c 100644
--- a/runtime/vm/compiler/graph_intrinsifier.cc
+++ b/runtime/vm/compiler/graph_intrinsifier.cc
@@ -162,7 +162,6 @@
         current_(entry),
         fall_through_env_(new Environment(0,
                                           0,
-                                          DeoptId::kNone,
                                           flow_graph->parsed_function(),
                                           NULL)) {}
 
@@ -276,7 +275,9 @@
   index = PrepareIndexedOp(flow_graph, &builder, array, index,
                            Slot::GetLengthFieldForArrayCid(array_cid));
 
-  if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+  if (RawObject::IsTypedDataClassId(array_cid) ||
+      RawObject::IsExternalTypedDataClassId(array_cid)) {
+    ASSERT(TypedData::data_offset() == ExternalTypedData::data_offset());
     array = builder.AddDefinition(new LoadUntaggedInstr(
         new Value(array), ExternalTypedData::data_offset()));
   }
@@ -422,7 +423,9 @@
       UNREACHABLE();
   }
 
-  if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+  if (RawObject::IsTypedDataClassId(array_cid) ||
+      RawObject::IsExternalTypedDataClassId(array_cid)) {
+    ASSERT(TypedData::data_offset() == ExternalTypedData::data_offset());
     array = builder.AddDefinition(new LoadUntaggedInstr(
         new Value(array), ExternalTypedData::data_offset()));
   }
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index b8e2fdb..db4a507 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -381,8 +381,11 @@
 
   // CreateDeoptInfo uses the object pool and needs to be done before
   // FinalizeCode.
-  const Array& deopt_info_array =
-      Array::Handle(zone, graph_compiler->CreateDeoptInfo(assembler));
+  Array& deopt_info_array = Array::Handle(zone, Object::empty_array().raw());
+  if (!function.ForceOptimize()) {
+    deopt_info_array = graph_compiler->CreateDeoptInfo(assembler);
+  }
+
   // Allocates instruction object. Since this occurs only at safepoint,
   // there can be no concurrent access to the instruction page.
   Code& code = Code::Handle(Code::FinalizeCode(
@@ -431,7 +434,13 @@
   graph_compiler->FinalizeStaticCallTargetsTable(code);
   graph_compiler->FinalizeCodeSourceMap(code);
 
-  if (optimized()) {
+  if (function.ForceOptimize()) {
+    ASSERT(optimized() && thread()->IsMutatorThread());
+    code.set_is_optimized(false);
+    function.AttachCode(code);
+    function.set_unoptimized_code(code);
+    function.SetWasCompiled(true);
+  } else if (optimized()) {
     // Installs code while at safepoint.
     if (thread()->IsMutatorThread()) {
       const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
@@ -764,6 +773,7 @@
                                         intptr_t osr_id) {
   ASSERT(!FLAG_precompiled_mode);
   ASSERT(!optimized || function.WasCompiled());
+  if (function.ForceOptimize()) optimized = true;
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
     Thread* const thread = Thread::Current();
@@ -1058,13 +1068,6 @@
 
   ASSERT(function.ShouldCompilerOptimize());
 
-  // If we are in the optimizing in the mutator/Dart thread, then
-  // this is either an OSR compilation or background compilation is
-  // not currently allowed.
-  ASSERT(!thread->IsMutatorThread() || (osr_id != kNoOSRDeoptId) ||
-         !FLAG_background_compilation ||
-         BackgroundCompiler::IsDisabled(Isolate::Current()) ||
-         !function.is_background_optimizable());
   CompilationPipeline* pipeline =
       CompilationPipeline::New(thread->zone(), function);
   return CompileFunctionHelper(pipeline, function, /* optimized = */ true,
diff --git a/runtime/vm/compiler/method_recognizer.cc b/runtime/vm/compiler/method_recognizer.cc
index be12f08..0973fed 100644
--- a/runtime/vm/compiler/method_recognizer.cc
+++ b/runtime/vm/compiler/method_recognizer.cc
@@ -304,7 +304,7 @@
   String& name = thread->StringHandle();
   name = name_.raw();
   ASSERT(name.IsSymbol());
-  if (Function::IsDynamicInvocationForwaderName(name)) {
+  if (Function::IsDynamicInvocationForwarderName(name)) {
     name = Function::DemangleDynamicInvocationForwarderName(name);
   }
   if (name.raw() == Symbols::Plus().raw()) {
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index fa35d7c..a0baa73 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -8,7 +8,7 @@
 namespace dart {
 
 // clang-format off
-// (class-name, function-name, recognized enum, result type, fingerprint).
+// (class-name, function-name, recognized enum, fingerprint).
 // When adding a new function add a 0 as fingerprint, build and run to get the
 // correct fingerprint from the mismatch error (or use Library::GetFunction()
 // and print func.SourceFingerprint()).
@@ -42,6 +42,27 @@
   V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 0x38a80b0d)              \
   V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 0x40052c4e)          \
   V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, 0x07b89f54)              \
+  V(_ByteDataView, get:length, ByteDataViewLength, 0x0)                        \
+  V(_ByteDataView, get:offsetInBytes, ByteDataViewOffsetInBytes, 0x0)          \
+  V(_ByteDataView, get:_typedData, ByteDataViewTypedData, 0x0)                 \
+  V(_TypedListView, get:length, TypedDataViewLength, 0x0)                      \
+  V(_TypedListView, get:offsetInBytes, TypedDataViewOffsetInBytes, 0x0)        \
+  V(_TypedListView, get:_typedData, TypedDataViewTypedData, 0x0)               \
+  V(_ByteDataView, ., TypedData_ByteDataView_factory, 0x0)                     \
+  V(_Int8ArrayView, ., TypedData_Int8ArrayView_factory, 0x0)                   \
+  V(_Uint8ArrayView, ., TypedData_Uint8ArrayView_factory, 0x0)                 \
+  V(_Uint8ClampedArrayView, ., TypedData_Uint8ClampedArrayView_factory, 0x0)   \
+  V(_Int16ArrayView, ., TypedData_Int16ArrayView_factory, 0x0)                 \
+  V(_Uint16ArrayView, ., TypedData_Uint16ArrayView_factory, 0x0)               \
+  V(_Int32ArrayView, ., TypedData_Int32ArrayView_factory, 0x0)                 \
+  V(_Uint32ArrayView, ., TypedData_Uint32ArrayView_factory, 0x0)               \
+  V(_Int64ArrayView, ., TypedData_Int64ArrayView_factory, 0x0)                 \
+  V(_Uint64ArrayView, ., TypedData_Uint64ArrayView_factory, 0x0)               \
+  V(_Float32ArrayView, ., TypedData_Float32ArrayView_factory, 0x0)             \
+  V(_Float64ArrayView, ., TypedData_Float64ArrayView_factory, 0x0)             \
+  V(_Float32x4ArrayView, ., TypedData_Float32x4ArrayView_factory, 0x0)         \
+  V(_Int32x4ArrayView, ., TypedData_Int32x4ArrayView_factory, 0x0)             \
+  V(_Float64x2ArrayView, ., TypedData_Float64x2ArrayView_factory, 0x0)         \
   V(::, _toClampedUint8, ConvertIntToClampedUint8, 0x564b0435)                 \
   V(_StringBase, _interpolate, StringBaseInterpolate, 0x01ecb15a)              \
   V(_IntegerImplementation, toDouble, IntegerToDouble, 0x05da96ed)             \
@@ -352,6 +373,9 @@
   V(_List, get:length, ObjectArrayLength, 0x25952390)                          \
   V(_ImmutableList, get:length, ImmutableArrayLength, 0x25952390)              \
   V(_TypedList, get:length, TypedDataLength, 0x2091c4d8)                       \
+  V(_TypedListView, get:length, TypedDataViewLength, 0x0)                      \
+  V(_TypedListView, get:offsetInBytes, TypedDataViewOffsetInBytes, 0x0)        \
+  V(_TypedListView, get:_typedData, TypedDataViewTypedData, 0x0)               \
   V(_GrowableList, get:length, GrowableArrayLength, 0x18dd86b4)                \
   V(_GrowableList, get:_capacity, GrowableArrayCapacity, 0x2e04be60)           \
   V(_GrowableList, add, GrowableListAdd, 0x40b490b8)                           \
@@ -390,6 +414,9 @@
   V(_Float32ArrayView, []=, Float32ArrayViewSetIndexed, 0xc9b691bd)            \
   V(_Float64ArrayView, [], Float64ArrayViewGetIndexed, 0x9d83f585)             \
   V(_Float64ArrayView, []=, Float64ArrayViewSetIndexed, 0x3c1adabd)            \
+  V(_ByteDataView, get:length, ByteDataViewLength, 0x0)                        \
+  V(_ByteDataView, get:offsetInBytes, ByteDataViewOffsetInBytes, 0x0)          \
+  V(_ByteDataView, get:_typedData, ByteDataViewTypedData, 0x0)                 \
   V(_ByteDataView, setInt8, ByteDataViewSetInt8, 0x6395293e)                   \
   V(_ByteDataView, setUint8, ByteDataViewSetUint8, 0x79979d1f)                 \
   V(_ByteDataView, setInt16, ByteDataViewSetInt16, 0x525ec534)                 \
diff --git a/runtime/vm/compiler/relocation.cc b/runtime/vm/compiler/relocation.cc
index 467aa78..5d4d35f 100644
--- a/runtime/vm/compiler/relocation.cc
+++ b/runtime/vm/compiler/relocation.cc
@@ -5,6 +5,7 @@
 #include "vm/compiler/relocation.h"
 
 #include "vm/code_patcher.h"
+#include "vm/heap/pages.h"
 #include "vm/instructions.h"
 #include "vm/object_store.h"
 #include "vm/stub_code.h"
@@ -362,8 +363,11 @@
   auto caller = Code::InstructionsOf(unresolved_call->caller);
   const int32_t distance = destination_text - call_text_offset;
   {
-    PcRelativeCallPattern call(Instructions::PayloadStart(caller) +
-                               call_offset);
+    uword addr = Instructions::PayloadStart(caller) + call_offset;
+    if (FLAG_write_protect_code) {
+      addr -= HeapPage::Of(caller)->AliasOffset();
+    }
+    PcRelativeCallPattern call(addr);
     ASSERT(call.IsValid());
     call.set_distance(static_cast<int32_t>(distance));
     ASSERT(call.distance() == distance);
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index ce66591..ba72cc1 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -254,6 +254,10 @@
 const word RawObject::kBarrierOverlapShift =
     dart::RawObject::kBarrierOverlapShift;
 
+bool RawObject::IsTypedDataClassId(intptr_t cid) {
+  return dart::RawObject::IsTypedDataClassId(cid);
+}
+
 intptr_t ObjectPool::element_offset(intptr_t index) {
   return dart::ObjectPool::element_offset(index);
 }
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 8df8767..652c1b3 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -335,6 +335,8 @@
   static const word kSizeTagMaxSizeTag;
   static const word kTagBitsSizeTagPos;
   static const word kBarrierOverlapShift;
+
+  static bool IsTypedDataClassId(intptr_t cid);
 };
 
 class RawAbstractType : public AllStatic {
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 5de7ddc..00affe4 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -145,9 +145,9 @@
 
 #define R(reg) (1 << (reg))
 
-#if defined(_WIN64)
 class CallingConventions {
  public:
+#if defined(_WIN64)
   static const Register kArg1Reg = RCX;
   static const Register kArg2Reg = RDX;
   static const Register kArg3Reg = R8;
@@ -186,10 +186,10 @@
   // Windows x64 ABI specifies that small objects are passed in registers.
   // Otherwise they are passed by reference.
   static const size_t kRegisterTransferLimit = 16;
-};
+
+  static constexpr Register kReturnReg = RAX;
+  static constexpr FpuRegister kReturnFpuReg = XMM0;
 #else
-class CallingConventions {
- public:
   static const Register kArg1Reg = RDI;
   static const Register kArg2Reg = RSI;
   static const Register kArg3Reg = RDX;
@@ -229,9 +229,24 @@
   static const intptr_t kCalleeSaveXmmRegisters = 0;
 
   static const XmmRegister xmmFirstNonParameterReg = XMM8;
-};
+
+  static constexpr Register kReturnReg = RAX;
+  static constexpr FpuRegister kReturnFpuReg = XMM0;
 #endif
 
+  COMPILE_ASSERT((kArgumentRegisters & kReservedCpuRegisters) == 0);
+
+  static constexpr Register kFirstCalleeSavedCpuReg = RBX;
+  static constexpr Register kFirstNonArgumentRegister = RAX;
+  static constexpr Register kSecondNonArgumentRegister = RBX;
+
+  COMPILE_ASSERT(((R(kFirstCalleeSavedCpuReg)) & kCalleeSaveCpuRegisters) != 0);
+
+  COMPILE_ASSERT(((R(kFirstNonArgumentRegister) |
+                   R(kSecondNonArgumentRegister)) &
+                  kArgumentRegisters) == 0);
+};
+
 #undef R
 
 class Instr {
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 3e81020..0c51e1a 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -3087,19 +3087,19 @@
     }
   }
   if (RawObject::IsTypedDataViewClassId(obj.GetClassId())) {
-    const Instance& view = Instance::Cast(obj);
+    const auto& view = TypedDataView::Cast(obj);
     if (TypedDataView::ElementSizeInBytes(view) == 1) {
-      intptr_t view_length = Smi::Value(TypedDataView::Length(view));
+      const intptr_t view_length = Smi::Value(view.length());
       if (!Utils::RangeCheck(offset, length, view_length)) {
         return Api::NewError(
             "Invalid length passed in to access list elements");
       }
-      const Instance& data = Instance::Handle(TypedDataView::Data(view));
+      const auto& data = Instance::Handle(view.typed_data());
       if (data.IsTypedData()) {
         const TypedData& array = TypedData::Cast(data);
         if (array.ElementSizeInBytes() == 1) {
-          intptr_t data_offset =
-              Smi::Value(TypedDataView::OffsetInBytes(view)) + offset;
+          const intptr_t data_offset =
+              Smi::Value(view.offset_in_bytes()) + offset;
           // Range check already performed on the view object.
           ASSERT(Utils::RangeCheck(data_offset, length, array.Length()));
           return CopyBytes(array, data_offset, native_array, length);
@@ -3389,10 +3389,9 @@
   if (RawObject::IsTypedDataViewClassId(class_id)) {
     // Check if data object of the view is external.
     Zone* zone = thread->zone();
-    const Instance& view_obj = Api::UnwrapInstanceHandle(zone, object);
+    const auto& view_obj = Api::UnwrapTypedDataViewHandle(zone, object);
     ASSERT(!view_obj.IsNull());
-    const Instance& data_obj =
-        Instance::Handle(zone, TypedDataView::Data(view_obj));
+    const auto& data_obj = Instance::Handle(zone, view_obj.typed_data());
     if (ExternalTypedData::IsExternalTypedData(data_obj)) {
       return GetType(class_id);
     }
@@ -3744,15 +3743,15 @@
     data_tmp = obj.DataAddr(0);
   } else {
     ASSERT(RawObject::IsTypedDataViewClassId(class_id));
-    const Instance& view_obj = Api::UnwrapInstanceHandle(Z, object);
+    const auto& view_obj = Api::UnwrapTypedDataViewHandle(Z, object);
     ASSERT(!view_obj.IsNull());
     Smi& val = Smi::Handle();
-    val ^= TypedDataView::Length(view_obj);
+    val ^= view_obj.length();
     length = val.Value();
     size_in_bytes = length * TypedDataView::ElementSizeInBytes(class_id);
-    val ^= TypedDataView::OffsetInBytes(view_obj);
+    val ^= view_obj.offset_in_bytes();
     intptr_t offset_in_bytes = val.Value();
-    const Instance& obj = Instance::Handle(TypedDataView::Data(view_obj));
+    const auto& obj = Instance::Handle(view_obj.typed_data());
     T->IncrementNoSafepointScopeDepth();
     START_NO_CALLBACK_SCOPE(T);
     if (TypedData::IsTypedData(obj)) {
@@ -4900,7 +4899,7 @@
       return Symbols::False().raw();
     }
 
-    if (!Api::ffiEnabled() && name.Equals(Symbols::DartLibraryFfi())) {
+    if (!Api::IsFfiEnabled() && name.Equals(Symbols::DartLibraryFfi())) {
       return Symbols::False().raw();
     }
 
@@ -5839,7 +5838,6 @@
   if (event == NULL) {
     return;
   }
-  label = strdup(label);
   switch (type) {
     case Dart_Timeline_Event_Begin:
       event->Begin(label, timestamp0);
@@ -5877,7 +5875,6 @@
     default:
       FATAL("Unknown Dart_Timeline_Event_Type");
   }
-  event->set_owns_label(true);
   event->SetNumArguments(argument_count);
   for (intptr_t i = 0; i < argument_count; i++) {
     event->CopyArgument(i, argument_names[i], argument_values[i]);
@@ -5945,6 +5942,10 @@
   API_TIMELINE_DURATION(thread);
   DARTSCOPE(thread);
   CHECK_NULL(buffer);
+  Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
+  if (Api::IsError(state)) {
+    return state;
+  }
   CompilationTraceLoader loader(thread);
   const Object& error =
       Object::Handle(loader.CompileTrace(buffer, buffer_length));
@@ -5964,6 +5965,10 @@
   API_TIMELINE_DURATION(thread);
   DARTSCOPE(thread);
   CHECK_NULL(buffer);
+  Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
+  if (Api::IsError(state)) {
+    return state;
+  }
   ReadStream stream(buffer, buffer_length);
   TypeFeedbackLoader loader(thread);
   const Object& error = Object::Handle(loader.LoadFeedback(&stream));
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index 76a6b0d..41f7383 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -295,14 +295,14 @@
 
   static RawString* GetEnvironmentValue(Thread* thread, const String& name);
 
-  static bool ffiEnabled() {
+  static bool IsFfiEnabled() {
     // dart:ffi is not implemented for the following configurations
 #if !defined(TARGET_ARCH_X64)
-    // https://github.com/dart-lang/sdk/issues/35774
+    // https://github.com/dart-lang/sdk/issues/35774 IA32
     return false;
-#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
+#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS) &&                \
+    !defined(TARGET_OS_WINDOWS)
     // https://github.com/dart-lang/sdk/issues/35760 Arm32 && Android
-    // https://github.com/dart-lang/sdk/issues/35771 Windows
     // https://github.com/dart-lang/sdk/issues/35772 Arm64
     // https://github.com/dart-lang/sdk/issues/35773 DBC
     return false;
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
index 6b4b612..88c6c92 100644
--- a/runtime/vm/dart_api_message.cc
+++ b/runtime/vm/dart_api_message.cc
@@ -243,39 +243,6 @@
   return value;
 }
 
-static Dart_TypedData_Type GetTypedDataTypeFromView(
-    Dart_CObject_Internal* object,
-    char* class_name) {
-  struct {
-    const char* name;
-    Dart_TypedData_Type type;
-  } view_class_names[] = {
-      {"_Int8ArrayView", Dart_TypedData_kInt8},
-      {"_Uint8ArrayView", Dart_TypedData_kUint8},
-      {"_Uint8ClampedArrayView", Dart_TypedData_kUint8Clamped},
-      {"_Int16ArrayView", Dart_TypedData_kInt16},
-      {"_Uint16ArrayView", Dart_TypedData_kUint16},
-      {"_Int32ArrayView", Dart_TypedData_kInt32},
-      {"_Uint32ArrayView", Dart_TypedData_kUint32},
-      {"_Int64ArrayView", Dart_TypedData_kInt64},
-      {"_Uint64ArrayView", Dart_TypedData_kUint64},
-      {"_ByteDataView", Dart_TypedData_kUint8},
-      {"_Float32ArrayView", Dart_TypedData_kFloat32},
-      {"_Float64ArrayView", Dart_TypedData_kFloat64},
-      {NULL, Dart_TypedData_kInvalid},
-  };
-
-  int i = 0;
-  while (view_class_names[i].name != NULL) {
-    if (strncmp(view_class_names[i].name, class_name,
-                strlen(view_class_names[i].name)) == 0) {
-      return view_class_names[i].type;
-    }
-    i++;
-  }
-  return Dart_TypedData_kInvalid;
-}
-
 Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) {
   // Read the class header information and lookup the class.
   intptr_t class_header = Read<int32_t>();
@@ -299,46 +266,6 @@
     }
     ASSERT(object->type == static_cast<Dart_CObject_Type>(
                                Dart_CObject_Internal::kUninitialized));
-
-    char* library_uri =
-        object->cls->internal.as_class.library_url->value.as_string;
-    char* class_name =
-        object->cls->internal.as_class.class_name->value.as_string;
-
-    // Handle typed data views.
-    if (strcmp("dart:typed_data", library_uri) == 0) {
-      Dart_TypedData_Type type = GetTypedDataTypeFromView(object, class_name);
-      if (type != Dart_TypedData_kInvalid) {
-        object->type =
-            static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kView);
-        Dart_CObject_Internal* cls =
-            reinterpret_cast<Dart_CObject_Internal*>(ReadObjectImpl());
-        ASSERT(cls == object->cls);
-        object->internal.as_view.buffer = ReadObjectImpl();
-        object->internal.as_view.offset_in_bytes = ReadSmiValue();
-        object->internal.as_view.length = ReadSmiValue();
-
-        // The buffer is fully read now as typed data objects are
-        // serialized in-line.
-        Dart_CObject* buffer = object->internal.as_view.buffer;
-        ASSERT(buffer->type == Dart_CObject_kTypedData);
-
-        // Now turn the view into a byte array.
-        object->type = Dart_CObject_kTypedData;
-        object->value.as_typed_data.type = type;
-        object->value.as_typed_data.length =
-            object->internal.as_view.length * GetTypedDataSizeInBytes(type);
-        object->value.as_typed_data.values =
-            buffer->value.as_typed_data.values +
-            object->internal.as_view.offset_in_bytes;
-      } else {
-        // TODO(sgjesse): Handle other instances. Currently this will
-        // skew the reading as the fields of the instance is not read.
-      }
-    } else {
-      // TODO(sgjesse): Handle other instances. Currently this will
-      // skew the reading as the fields of the instance is not read.
-    }
     return object;
   }
 
@@ -531,7 +458,6 @@
       return value;
     }
     case kTypeParameterCid: {
-      // TODO(sgjesse): Fix this workaround ignoring the type parameter.
       Dart_CObject* value = &dynamic_type_marker;
       AddBackRef(object_id, value, kIsDeserialized);
       intptr_t index = Read<int32_t>();
@@ -657,60 +583,59 @@
     return object;                                                             \
   }
 
-    case kTypedDataInt8ArrayCid:
-      READ_TYPED_DATA(Int8, int8_t);
-    case kExternalTypedDataInt8ArrayCid:
-      READ_EXTERNAL_TYPED_DATA(Int8, int8_t);
+#define READ_TYPED_DATA_VIEW(tname, ctype)                                     \
+  {                                                                            \
+    Dart_CObject_Internal* object =                                            \
+        AllocateDartCObjectInternal(Dart_CObject_Internal::kUninitialized);    \
+    AddBackRef(object_id, object, kIsDeserialized);                            \
+    object->type =                                                             \
+        static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kView);          \
+    object->internal.as_view.offset_in_bytes = ReadSmiValue();                 \
+    object->internal.as_view.length = ReadSmiValue();                          \
+    object->internal.as_view.buffer = ReadObjectImpl();                        \
+    Dart_CObject* buffer = object->internal.as_view.buffer;                    \
+    RELEASE_ASSERT(buffer->type == Dart_CObject_kTypedData);                   \
+                                                                               \
+    /* Now turn the view into a byte array.*/                                  \
+    const Dart_TypedData_Type type = Dart_TypedData_k##tname;                  \
+    object->type = Dart_CObject_kTypedData;                                    \
+    object->value.as_typed_data.type = type;                                   \
+    object->value.as_typed_data.length =                                       \
+        object->internal.as_view.length * GetTypedDataSizeInBytes(type);       \
+    object->value.as_typed_data.values =                                       \
+        buffer->value.as_typed_data.values +                                   \
+        object->internal.as_view.offset_in_bytes;                              \
+    return object;                                                             \
+  }
 
-    case kTypedDataUint8ArrayCid:
-      READ_TYPED_DATA(Uint8, uint8_t);
-    case kExternalTypedDataUint8ArrayCid:
-      READ_EXTERNAL_TYPED_DATA(Uint8, uint8_t);
+#define TYPED_DATA_LIST(V)                                                     \
+  V(Int8, int8_t)                                                              \
+  V(Uint8, uint8_t)                                                            \
+  V(Uint8Clamped, uint8_t)                                                     \
+  V(Int16, int16_t)                                                            \
+  V(Uint16, uint16_t)                                                          \
+  V(Int32, int32_t)                                                            \
+  V(Uint32, uint32_t)                                                          \
+  V(Int64, int64_t)                                                            \
+  V(Uint64, uint64_t)                                                          \
+  V(Float32, float)                                                            \
+  V(Float64, double)
 
-    case kTypedDataUint8ClampedArrayCid:
-      READ_TYPED_DATA(Uint8Clamped, uint8_t);
-    case kExternalTypedDataUint8ClampedArrayCid:
-      READ_EXTERNAL_TYPED_DATA(Uint8Clamped, uint8_t);
+#define EMIT_TYPED_DATA_CASES(type, c_type)                                    \
+  case kTypedData##type##ArrayCid:                                             \
+    READ_TYPED_DATA(type, c_type);                                             \
+  case kExternalTypedData##type##ArrayCid:                                     \
+    READ_EXTERNAL_TYPED_DATA(type, c_type);                                    \
+  case kTypedData##type##ArrayViewCid:                                         \
+    READ_TYPED_DATA_VIEW(type, c_type);
 
-    case kTypedDataInt16ArrayCid:
-      READ_TYPED_DATA(Int16, int16_t);
-    case kExternalTypedDataInt16ArrayCid:
-      READ_EXTERNAL_TYPED_DATA(Int16, int16_t);
-
-    case kTypedDataUint16ArrayCid:
-      READ_TYPED_DATA(Uint16, uint16_t);
-    case kExternalTypedDataUint16ArrayCid:
-      READ_EXTERNAL_TYPED_DATA(Uint16, uint16_t);
-
-    case kTypedDataInt32ArrayCid:
-      READ_TYPED_DATA(Int32, int32_t);
-    case kExternalTypedDataInt32ArrayCid:
-      READ_EXTERNAL_TYPED_DATA(Int32, int32_t);
-
-    case kTypedDataUint32ArrayCid:
-      READ_TYPED_DATA(Uint32, uint32_t);
-    case kExternalTypedDataUint32ArrayCid:
-      READ_EXTERNAL_TYPED_DATA(Uint32, uint32_t);
-
-    case kTypedDataInt64ArrayCid:
-      READ_TYPED_DATA(Int64, int64_t);
-    case kExternalTypedDataInt64ArrayCid:
-      READ_EXTERNAL_TYPED_DATA(Int64, int64_t);
-
-    case kTypedDataUint64ArrayCid:
-      READ_TYPED_DATA(Uint64, uint64_t);
-    case kExternalTypedDataUint64ArrayCid:
-      READ_EXTERNAL_TYPED_DATA(Uint64, uint64_t);
-
-    case kTypedDataFloat32ArrayCid:
-      READ_TYPED_DATA(Float32, float);
-    case kExternalTypedDataFloat32ArrayCid:
-      READ_EXTERNAL_TYPED_DATA(Float32, float);
-
-    case kTypedDataFloat64ArrayCid:
-      READ_TYPED_DATA(Float64, double);
-    case kExternalTypedDataFloat64ArrayCid:
-      READ_EXTERNAL_TYPED_DATA(Float64, double);
+      TYPED_DATA_LIST(EMIT_TYPED_DATA_CASES)
+#undef EMIT_TYPED_DATA_CASES
+#undef TYPED_DATA_LIST
+#undef READ_TYPED_DATA
+#undef READ_EXTERNAL_TYPED_DATA
+#undef READ_TYPED_DATA_VIEW
+#undef READ_TYPED_DATA_HEADER
 
     case kGrowableObjectArrayCid: {
       // A GrowableObjectArray is serialized as its type arguments and
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index 759a180..011dcca 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -522,6 +522,11 @@
 
   bool IsPaused() const { return pause_event_ != NULL; }
 
+  bool ignore_breakpoints() const { return ignore_breakpoints_; }
+  void set_ignore_breakpoints(bool ignore_breakpoints) {
+    ignore_breakpoints_ = ignore_breakpoints;
+  }
+
   // Put the isolate into single stepping mode when Dart code next runs.
   //
   // This is used by the vm service to allow the user to step while
@@ -780,6 +785,26 @@
   DISALLOW_COPY_AND_ASSIGN(Debugger);
 };
 
+class DisableBreakpointsScope : public ValueObject {
+ public:
+  DisableBreakpointsScope(Debugger* debugger, bool disable)
+      : debugger_(debugger) {
+    ASSERT(debugger_ != NULL);
+    initial_state_ = debugger_->ignore_breakpoints();
+    debugger_->set_ignore_breakpoints(disable);
+  }
+
+  ~DisableBreakpointsScope() {
+    debugger_->set_ignore_breakpoints(initial_state_);
+  }
+
+ private:
+  Debugger* debugger_;
+  bool initial_state_;
+
+  DISALLOW_COPY_AND_ASSIGN(DisableBreakpointsScope);
+};
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_DEBUGGER_H_
diff --git a/runtime/vm/deferred_objects.cc b/runtime/vm/deferred_objects.cc
index 9529569..76ca7b7 100644
--- a/runtime/vm/deferred_objects.cc
+++ b/runtime/vm/deferred_objects.cc
@@ -105,16 +105,13 @@
     Exceptions::PropagateError(error);
   }
   const Code& code = Code::Handle(zone, function.unoptimized_code());
-// Check that deopt_id exists.
-// TODO(vegorov): verify after deoptimization targets as well.
-#ifdef DEBUG
-  ASSERT(DeoptId::IsDeoptAfter(deopt_id_) ||
-         (code.GetPcForDeoptId(deopt_id_, RawPcDescriptors::kDeopt) != 0));
-#endif
 
   uword continue_at_pc =
       code.GetPcForDeoptId(deopt_id_, RawPcDescriptors::kDeopt);
-  ASSERT(continue_at_pc != 0);
+  if (continue_at_pc == 0) {
+    FATAL2("Can't locate continuation PC for deoptid %" Pd " within %s\n",
+           deopt_id_, function.ToFullyQualifiedCString());
+  }
   uword* dest_addr = reinterpret_cast<uword*>(slot());
   *dest_addr = continue_at_pc;
 
@@ -306,7 +303,11 @@
                        value.ToCString());
         }
       } else {
-        ASSERT(offset.Value() == cls.type_arguments_field_offset());
+        // In addition to the type arguments vector we can also have lazy
+        // materialization of e.g. _ByteDataView objects which don't have
+        // explicit fields in Dart (all accesses to the fields are done via
+        // recognized native methods).
+        ASSERT(offset.Value() < cls.instance_size());
         obj.SetFieldAtOffset(offset.Value(), value);
         if (FLAG_trace_deoptimization_verbose) {
           OS::PrintErr("    null Field @ offset(%" Pd ") <- %s\n",
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 487b22a..058d9c7 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -239,12 +239,15 @@
   }
 
   void ExecuteCatchEntryMoves(const CatchEntryMoves& moves) {
+    Zone* zone = Thread::Current()->zone();
+    auto& value = Object::Handle(zone);
+    auto& dst_values = Array::Handle(zone, Array::New(moves.count()));
+
     uword fp = handler_fp;
     ObjectPool* pool = nullptr;
     for (int j = 0; j < moves.count(); j++) {
       const CatchEntryMove& move = moves.At(j);
 
-      RawObject* value;
       switch (move.source_kind()) {
         case CatchEntryMove::SourceKind::kConstant:
           if (pool == nullptr) {
@@ -295,64 +298,28 @@
           UNREACHABLE();
       }
 
-      *TaggedSlotAt(fp, move.dest_slot()) = value;
+      dst_values.SetAt(j, value);
+    }
+
+    {
+      NoSafepointScope no_safepoint_scope;
+
+      for (int j = 0; j < moves.count(); j++) {
+        const CatchEntryMove& move = moves.At(j);
+        value = dst_values.At(j);
+        *TaggedSlotAt(fp, move.dest_slot()) = value.raw();
+      }
     }
   }
 
 #if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
   void ReadCompressedCatchEntryMoves() {
-    intptr_t pc_offset = pc_ - code_->PayloadStart();
-    const TypedData& td = TypedData::Handle(code_->catch_entry_moves_maps());
-    NoSafepointScope no_safepoint;
-    ReadStream stream(static_cast<uint8_t*>(td.DataAddr(0)), td.Length());
+    const intptr_t pc_offset = pc_ - code_->PayloadStart();
+    const auto& td = TypedData::Handle(code_->catch_entry_moves_maps());
 
-    intptr_t prefix_length = 0, suffix_length = 0, suffix_offset = 0;
-    while (stream.PendingBytes() > 0) {
-      intptr_t target_pc_offset = Reader::Read(&stream);
-      prefix_length = Reader::Read(&stream);
-      suffix_length = Reader::Read(&stream);
-      suffix_offset = Reader::Read(&stream);
-      if (pc_offset == target_pc_offset) {
-        break;
-      }
-
-      // Skip the moves.
-      for (intptr_t j = 0; j < prefix_length; j++) {
-        CatchEntryMove::ReadFrom(&stream);
-      }
-    }
-    ASSERT((stream.PendingBytes() > 0) || (prefix_length == 0));
-
-    CatchEntryMoves* moves =
-        CatchEntryMoves::Allocate(prefix_length + suffix_length);
-    for (int j = 0; j < prefix_length; j++) {
-      moves->At(j) = CatchEntryMove::ReadFrom(&stream);
-    }
-    ReadCompressedCatchEntryMovesSuffix(&stream, suffix_offset, suffix_length,
-                                        moves, prefix_length);
-    catch_entry_moves_ = moves;
+    CatchEntryMovesMapReader reader(td);
+    catch_entry_moves_ = reader.ReadMovesForPcOffset(pc_offset);
   }
-
-  void ReadCompressedCatchEntryMovesSuffix(ReadStream* stream,
-                                           intptr_t offset,
-                                           intptr_t length,
-                                           CatchEntryMoves* moves,
-                                           intptr_t moves_offset) {
-    stream->SetPosition(offset);
-    Reader::Read(stream);  // skip pc_offset
-    Reader::Read(stream);  // skip variables
-    intptr_t suffix_length = Reader::Read(stream);
-    intptr_t suffix_offset = Reader::Read(stream);
-    intptr_t to_read = length - suffix_length;
-    for (int j = 0; j < to_read; j++) {
-      moves->At(moves_offset + j) = CatchEntryMove::ReadFrom(stream);
-    }
-    if (suffix_length > 0) {
-      ReadCompressedCatchEntryMovesSuffix(stream, suffix_offset, suffix_length,
-                                          moves, moves_offset + to_read);
-    }
-  }
-
 #else
   void GetCatchEntryMovesFromDeopt(intptr_t num_vars, StackFrame* frame) {
     Isolate* isolate = thread_->isolate();
@@ -415,6 +382,79 @@
 }
 #endif
 
+CatchEntryMoves* CatchEntryMovesMapReader::ReadMovesForPcOffset(
+    intptr_t pc_offset) {
+  NoSafepointScope no_safepoint;
+
+  ReadStream stream(static_cast<uint8_t*>(bytes_.DataAddr(0)), bytes_.Length());
+
+  intptr_t position = 0;
+  intptr_t length = 0;
+  FindEntryForPc(&stream, pc_offset, &position, &length);
+
+  return ReadCompressedCatchEntryMovesSuffix(&stream, position, length);
+}
+
+void CatchEntryMovesMapReader::FindEntryForPc(ReadStream* stream,
+                                              intptr_t pc_offset,
+                                              intptr_t* position,
+                                              intptr_t* length) {
+  using Reader = ReadStream::Raw<sizeof(intptr_t), intptr_t>;
+
+  while (stream->PendingBytes() > 0) {
+    const intptr_t stream_position = stream->Position();
+    const intptr_t target_pc_offset = Reader::Read(stream);
+    const intptr_t prefix_length = Reader::Read(stream);
+    const intptr_t suffix_length = Reader::Read(stream);
+    Reader::Read(stream);  // Skip suffix_offset
+    if (pc_offset == target_pc_offset) {
+      *position = stream_position;
+      *length = prefix_length + suffix_length;
+      return;
+    }
+
+    // Skip the prefix moves.
+    for (intptr_t j = 0; j < prefix_length; j++) {
+      CatchEntryMove::ReadFrom(stream);
+    }
+  }
+
+  UNREACHABLE();
+}
+
+CatchEntryMoves* CatchEntryMovesMapReader::ReadCompressedCatchEntryMovesSuffix(
+    ReadStream* stream,
+    intptr_t offset,
+    intptr_t length) {
+  using Reader = ReadStream::Raw<sizeof(intptr_t), intptr_t>;
+
+  CatchEntryMoves* moves = CatchEntryMoves::Allocate(length);
+
+  intptr_t remaining_length = length;
+
+  intptr_t moves_offset = 0;
+  while (remaining_length > 0) {
+    stream->SetPosition(offset);
+    Reader::Read(stream);  // skip pc_offset
+    Reader::Read(stream);  // skip prefix length
+    const intptr_t suffix_length = Reader::Read(stream);
+    const intptr_t suffix_offset = Reader::Read(stream);
+    const intptr_t to_read = remaining_length - suffix_length;
+    if (to_read > 0) {
+      for (int j = 0; j < to_read; j++) {
+        // The prefix is written from the back.
+        moves->At(moves_offset + to_read - j - 1) =
+            CatchEntryMove::ReadFrom(stream);
+      }
+      remaining_length -= to_read;
+      moves_offset += to_read;
+    }
+    offset = suffix_offset;
+  }
+
+  return moves;
+}
+
 static void FindErrorHandler(uword* handler_pc,
                              uword* handler_sp,
                              uword* handler_fp) {
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index d43201f..894f374 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -27,6 +27,7 @@
 class WriteStream;
 class String;
 class Thread;
+class TypedData;
 
 class Exceptions : AllStatic {
  public:
@@ -190,7 +191,7 @@
            (dest_slot() == src_slot());
   }
 
-  bool operator==(const CatchEntryMove& rhs) {
+  bool operator==(const CatchEntryMove& rhs) const {
     return src_ == rhs.src_ && dest_and_kind_ == rhs.dest_and_kind_;
   }
 
@@ -253,6 +254,30 @@
   // Followed by CatchEntryMove[count_]
 };
 
+// Used for reading the [CatchEntryMoves] from the compressed form.
+class CatchEntryMovesMapReader : public ValueObject {
+ public:
+  explicit CatchEntryMovesMapReader(const TypedData& bytes) : bytes_(bytes) {}
+
+  // The returned [CatchEntryMoves] must be freed by the caller via [free].
+  CatchEntryMoves* ReadMovesForPcOffset(intptr_t pc_offset);
+
+ private:
+  // Given the [pc_offset] this function will find the [position] at which to
+  // read the catch entries and the [length] of the catch entry moves array.
+  void FindEntryForPc(ReadStream* stream,
+                      intptr_t pc_offset,
+                      intptr_t* position,
+                      intptr_t* length);
+
+  // Reads the [length] catch entry moves from [offset] in the [stream].
+  CatchEntryMoves* ReadCompressedCatchEntryMovesSuffix(ReadStream* stream,
+                                                       intptr_t offset,
+                                                       intptr_t length);
+
+  const TypedData& bytes_;
+};
+
 // A simple reference counting wrapper for CatchEntryMoves.
 //
 // TODO(vegorov) switch this to intrusive reference counting.
diff --git a/runtime/vm/ffi_trampoline_stubs_x64.cc b/runtime/vm/ffi_trampoline_stubs_x64.cc
index 1afc9b5..a98236d 100644
--- a/runtime/vm/ffi_trampoline_stubs_x64.cc
+++ b/runtime/vm/ffi_trampoline_stubs_x64.cc
@@ -31,432 +31,13 @@
 
 namespace dart {
 
-static intptr_t NumStackArguments(
-    const ZoneGrowableArray<Location>& locations) {
-  intptr_t num_arguments = locations.length();
-  intptr_t num_stack_arguments = 0;
-  for (intptr_t i = 0; i < num_arguments; i++) {
-    if (locations.At(i).IsStackSlot()) {
-      num_stack_arguments++;
-    }
-  }
-  return num_stack_arguments;
-}
-
-// Input parameters:
-//   Register reg : a Null, or something else
-static void GenerateNotNullCheck(Assembler* assembler, Register reg) {
-  Label not_null;
-  Address throw_null_pointer_address =
-      Address(THR, Thread::OffsetFromThread(&kArgumentNullErrorRuntimeEntry));
-
-  __ CompareObject(reg, Object::null_object());
-  __ j(NOT_EQUAL, &not_null, Assembler::kNearJump);
-
-  // TODO(dacoharkes): Create the message here and use
-  // kArgumentErrorRuntimeEntry to report which argument was null.
-  __ movq(CODE_REG, Address(THR, Thread::call_to_runtime_stub_offset()));
-  __ movq(RBX, throw_null_pointer_address);
-  __ movq(R10, Immediate(0));
-  __ call(Address(THR, Thread::call_to_runtime_entry_point_offset()));
-
-  __ Bind(&not_null);
-}
-
-// Saves an int64 in the thread so GC does not trip.
-//
-// Input parameters:
-//   Register src : a C int64
-static void GenerateSaveInt64GCSafe(Assembler* assembler, Register src) {
-  __ movq(Address(THR, Thread::unboxed_int64_runtime_arg_offset()), src);
-}
-
-// Loads an int64 from the thread.
-static void GenerateLoadInt64GCSafe(Assembler* assembler, Register dst) {
-  __ movq(dst, Address(THR, Thread::unboxed_int64_runtime_arg_offset()));
-}
-
-// Takes a Dart int and converts it to a C int64.
-//
-// Input parameters:
-//   Register reg : a Dart Null, Smi, or Mint
-// Output parameters:
-//   Register reg : a C int64
-// Invariant: keeps ArgumentRegisters and XmmArgumentRegisters intact
-void GenerateMarshalInt64(Assembler* assembler, Register reg) {
-  ASSERT(reg != TMP);
-  ASSERT((1 << TMP & CallingConventions::kArgumentRegisters) == 0);
-  Label done, not_smi;
-
-  // Exception on Null
-  GenerateNotNullCheck(assembler, reg);
-
-  // Smi or Mint?
-  __ movq(TMP, reg);
-  __ testq(TMP, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
-
-  // Smi
-  __ SmiUntag(reg);
-  __ jmp(&done, Assembler::kNearJump);
-
-  // Mint
-  __ Bind(&not_smi);
-  __ movq(reg, FieldAddress(reg, Mint::value_offset()));
-  __ Bind(&done);
-}
-
-// Takes a C int64 and converts it to a Dart int.
-//
-// Input parameters:
-//   RAX : a C int64
-// Output paramaters:
-//   RAX : a Dart Smi or Mint
-static void GenerateUnmarshalInt64(Assembler* assembler) {
-  const Class& mint_class =
-      Class::ZoneHandle(Isolate::Current()->object_store()->mint_class());
-  ASSERT(!mint_class.IsNull());
-  const auto& mint_allocation_stub =
-      Code::ZoneHandle(StubCode::GetAllocationStubForClass(mint_class));
-  ASSERT(!mint_allocation_stub.IsNull());
-  Label done;
-
-  // Try whether it fits in a Smi.
-  __ movq(TMP, RAX);
-  __ SmiTag(RAX);
-  __ j(NO_OVERFLOW, &done, Assembler::kNearJump);
-
-  // Mint
-  // Backup result value (to avoid GC).
-  GenerateSaveInt64GCSafe(assembler, TMP);
-
-  // Allocate object (can call into runtime).
-  __ Call(mint_allocation_stub);
-
-  // Store result value.
-  GenerateLoadInt64GCSafe(assembler, TMP);
-  __ movq(FieldAddress(RAX, Mint::value_offset()), TMP);
-
-  __ Bind(&done);
-}
-
-// Takes a Dart double and converts it into a C double.
-//
-// Input parameters:
-//   Register reg : a Dart Null or Double
-// Output parameters:
-//   XmmRegister xmm_reg : a C double
-// Invariant: keeps ArgumentRegisters and other XmmArgumentRegisters intact
-static void GenerateMarshalDouble(Assembler* assembler,
-                                  Register reg,
-                                  XmmRegister xmm_reg) {
-  ASSERT((1 << reg & CallingConventions::kArgumentRegisters) == 0);
-
-  // Throw a Dart Exception on Null.
-  GenerateNotNullCheck(assembler, reg);
-
-  __ movq(reg, FieldAddress(reg, Double::value_offset()));
-  __ movq(xmm_reg, reg);
-}
-
-// Takes a C double and converts it into a Dart double.
-//
-// Input parameters:
-//   XMM0 : a C double
-// Output parameters:
-//   RAX : a Dart Double
-static void GenerateUnmarshalDouble(Assembler* assembler) {
-  const auto& double_class =
-      Class::ZoneHandle(Isolate::Current()->object_store()->double_class());
-  ASSERT(!double_class.IsNull());
-  const auto& double_allocation_stub =
-      Code::ZoneHandle(StubCode::GetAllocationStubForClass(double_class));
-  ASSERT(!double_allocation_stub.IsNull());
-
-  // Backup result value (to avoid GC).
-  __ movq(RAX, XMM0);
-  GenerateSaveInt64GCSafe(assembler, RAX);
-
-  // Allocate object (can call into runtime).
-  __ Call(double_allocation_stub);
-
-  // Store the result value.
-  GenerateLoadInt64GCSafe(assembler, TMP);
-  __ movq(FieldAddress(RAX, Double::value_offset()), TMP);
-}
-
-// Takes a Dart double and converts into a C float.
-//
-// Input parameters:
-//   Register reg : a Dart double
-// Output parameters:
-//   XmmRegister xxmReg : a C float
-// Invariant: keeps ArgumentRegisters and other XmmArgumentRegisters intact
-static void GenerateMarshalFloat(Assembler* assembler,
-                                 Register reg,
-                                 XmmRegister xmm_reg) {
-  ASSERT((1 << reg & CallingConventions::kArgumentRegisters) == 0);
-
-  GenerateMarshalDouble(assembler, reg, xmm_reg);
-
-  __ cvtsd2ss(xmm_reg, xmm_reg);
-}
-
-// Takes a C float and converts it into a Dart double.
-//
-// Input parameters:
-//   XMM0 : a C float
-// Output paramaters:
-//   RAX : a Dart Double
-static void GenerateUnmarshalFloat(Assembler* assembler) {
-  __ cvtss2sd(XMM0, XMM0);
-  GenerateUnmarshalDouble(assembler);
-}
-
-// Takes a Dart ffi.Pointer and converts it into a C pointer.
-//
-// Input parameters:
-//   Register reg : a Dart ffi.Pointer or Null
-// Output parameters:
-//   Register reg : a C pointer
-static void GenerateMarshalPointer(Assembler* assembler, Register reg) {
-  Label done, not_null;
-
-  __ CompareObject(reg, Object::null_object());
-  __ j(NOT_EQUAL, &not_null, Assembler::kNearJump);
-
-  // If null, the address is 0.
-  __ movq(reg, Immediate(0));
-  __ jmp(&done);
-
-  // If not null but a Pointer, load the address.
-  __ Bind(&not_null);
-  __ movq(reg, FieldAddress(reg, Pointer::c_memory_address_offset()));
-  GenerateMarshalInt64(assembler, reg);
-  __ Bind(&done);
-}
-
-// Takes a C pointer and converts it into a Dart ffi.Pointer or Null.
-//
-// Input parameters:
-//   RAX : a C pointer
-// Outpot paramaters:
-//   RAX : a Dart ffi.Pointer or Null
-static void GenerateUnmarshalPointer(Assembler* assembler,
-                                     Address closure_dart,
-                                     const Class& pointer_class) {
-  Label done, not_null;
-  ASSERT(!pointer_class.IsNull());
-  const auto& pointer_allocation_stub =
-      Code::ZoneHandle(StubCode::GetAllocationStubForClass(pointer_class));
-  ASSERT(!pointer_allocation_stub.IsNull());
-
-  // If the address is 0, return a Dart Null.
-  __ cmpq(RAX, Immediate(0));
-  __ j(NOT_EQUAL, &not_null, Assembler::kNearJump);
-  __ LoadObject(RAX, Object::null_object());
-  __ jmp(&done);
-
-  __ Bind(&not_null);
-  GenerateUnmarshalInt64(assembler);
-  __ pushq(RAX);
-
-  // Allocate object (can call into runtime).
-  __ movq(TMP, closure_dart);
-  __ movq(TMP, FieldAddress(TMP, Closure::function_offset()));
-  __ movq(TMP, FieldAddress(TMP, Function::result_type_offset()));
-  __ pushq(FieldAddress(TMP, Type::arguments_offset()));
-  __ Call(pointer_allocation_stub);
-  __ popq(TMP);  // Pop type arguments.
-
-  // Store the result value.
-  __ popq(RDX);
-  __ movq(FieldAddress(RAX, Pointer::c_memory_address_offset()), RDX);
-  __ Bind(&done);
-}
-
-static void GenerateMarshalArgument(Assembler* assembler,
-                                    const AbstractType& arg_type,
-                                    Register reg,
-                                    XmmRegister xmm_reg) {
-  switch (arg_type.type_class_id()) {
-    case kFfiInt8Cid:
-    case kFfiInt16Cid:
-    case kFfiInt32Cid:
-    case kFfiInt64Cid:
-    case kFfiUint8Cid:
-    case kFfiUint16Cid:
-    case kFfiUint32Cid:
-    case kFfiUint64Cid:
-    case kFfiIntPtrCid:
-      // TODO(dacoharkes): Truncate and sign extend 8 bit and 16 bit, and write
-      // tests. https://github.com/dart-lang/sdk/issues/35787
-      GenerateMarshalInt64(assembler, reg);
-      return;
-    case kFfiFloatCid:
-      GenerateMarshalFloat(assembler, reg, xmm_reg);
-      return;
-    case kFfiDoubleCid:
-      GenerateMarshalDouble(assembler, reg, xmm_reg);
-      return;
-    case kFfiPointerCid:
-    default:  // Subtypes of Pointer.
-      GenerateMarshalPointer(assembler, reg);
-      return;
-  }
-}
-
-static void GenerateUnmarshalResult(Assembler* assembler,
-                                    const AbstractType& result_type,
-                                    Address closure_dart) {
-  switch (result_type.type_class_id()) {
-    case kFfiVoidCid:
-      __ LoadObject(RAX, Object::null_object());
-      return;
-    case kFfiInt8Cid:
-    case kFfiInt16Cid:
-    case kFfiInt32Cid:
-    case kFfiInt64Cid:
-    case kFfiUint8Cid:
-    case kFfiUint16Cid:
-    case kFfiUint32Cid:
-    case kFfiUint64Cid:
-    case kFfiIntPtrCid:
-      GenerateUnmarshalInt64(assembler);
-      return;
-    case kFfiFloatCid:
-      GenerateUnmarshalFloat(assembler);
-      return;
-    case kFfiDoubleCid:
-      GenerateUnmarshalDouble(assembler);
-      return;
-    case kFfiPointerCid:
-    default:  // subtypes of Pointer
-      break;
-  }
-  Class& cls = Class::ZoneHandle(Thread::Current()->zone(),
-                                 Type::Cast(result_type).type_class());
-
-  GenerateUnmarshalPointer(assembler, closure_dart, cls);
-}
-
-// Generates a assembly for dart:ffi trampolines:
-// - marshal arguments
-// - put the arguments in registers and on the c stack
-// - invoke the c function
-// - (c result register is the same as dart, so keep in place)
-// - unmarshal c result
-// - return
-//
-// Input parameters:
-//   RSP + kWordSize *  num_arguments      : closure.
-//   RSP + kWordSize * (num_arguments - 1) : arg 1.
-//   RSP + kWordSize * (num_arguments - 2) : arg 2.
-//   RSP + kWordSize                       : arg n.
-// After entering stub:
-//   RBP = RSP (before stub) - kWordSize
-//   RBP + kWordSize * (num_arguments + 1) : closure.
-//   RBP + kWordSize *  num_arguments      : arg 1.
-//   RBP + kWordSize * (num_arguments - 1) : arg 2.
-//   RBP + kWordSize *  2                  : arg n.
-//
-// TODO(dacoharkes): Test truncation on non 64 bits ints and floats.
-void GenerateFfiTrampoline(Assembler* assembler, const Function& signature) {
-  ZoneGrowableArray<Representation>* arg_representations =
-      ffi::ArgumentRepresentations(signature);
-  ZoneGrowableArray<Location>* arg_locations =
-      ffi::ArgumentLocations(*arg_representations);
-
-  intptr_t num_dart_arguments = signature.num_fixed_parameters();
-  intptr_t num_arguments = num_dart_arguments - 1;  // ignore closure
-
-  __ EnterStubFrame();
-
-  // Save exit frame information to enable stack walking as we are about
-  // to transition to Dart VM C++ code.
-  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP);
-
-#if defined(DEBUG)
-  {
-    Label ok;
-    // Check that we are always entering from Dart code.
-    __ movq(TMP, Immediate(VMTag::kDartCompiledTagId));
-    __ cmpq(TMP, Assembler::VMTagAddress());
-    __ j(EQUAL, &ok, Assembler::kNearJump);
-    __ Stop("Not coming from Dart code.");
-    __ Bind(&ok);
-  }
-#endif
-
-  // Reserve space for arguments and align frame before entering C++ world.
-  __ subq(RSP, Immediate(NumStackArguments(*arg_locations) * kWordSize));
-  if (OS::ActivationFrameAlignment() > 1) {
-    __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
-  }
-
-  // Prepare address for calling the C function.
-  Address closure_dart = Address(RBP, (num_dart_arguments + 1) * kWordSize);
-  __ movq(RBX, closure_dart);
-  __ movq(RBX, FieldAddress(RBX, Closure::context_offset()));
-  __ movq(RBX, FieldAddress(RBX, Context::variable_offset(0)));
-  GenerateMarshalInt64(assembler, RBX);  // Address is a Smi or Mint.
-
-  // Marshal arguments and store in the right register.
-  for (intptr_t i = 0; i < num_arguments; i++) {
-    Representation rep = arg_representations->At(i);
-    Location loc = arg_locations->At(i);
-
-    // We do marshalling in the the target register or in RAX.
-    Register reg = loc.IsRegister() ? loc.reg() : RAX;
-    // For doubles and floats we use target xmm register or first non param reg.
-    FpuRegister xmm_reg = loc.IsFpuRegister()
-                              ? loc.fpu_reg()
-                              : CallingConventions::xmmFirstNonParameterReg;
-
-    // Load parameter from Dart stack.
-    __ movq(reg, Address(RBP, (num_arguments + 1 - i) * kWordSize));
-
-    // Marshal argument.
-    AbstractType& arg_type =
-        AbstractType::Handle(signature.ParameterTypeAt(i + 1));
-    GenerateMarshalArgument(assembler, arg_type, reg, xmm_reg);
-
-    // Store marshalled argument where c expects value.
-    if (loc.IsStackSlot()) {
-      if (rep == kUnboxedDouble) {
-        __ movq(reg, xmm_reg);
-      }
-      __ movq(loc.ToStackSlotAddress(), reg);
-    }
-  }
-
-  // Mark that the thread is executing VM code.
-  __ movq(Assembler::VMTagAddress(), RBX);
-
-  __ CallCFunction(RBX);
-
-  // Mark that the thread is executing Dart code.
-  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
-
-  // Unmarshal result.
-  AbstractType& return_type = AbstractType::Handle(signature.result_type());
-  GenerateUnmarshalResult(assembler, return_type, closure_dart);
-
-  // Reset exit frame information in Isolate structure.
-  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
-
-  __ LeaveStubFrame();
-
-  __ ret();
-}
-
 void GenerateFfiInverseTrampoline(Assembler* assembler,
                                   const Function& signature,
                                   void* dart_entry_point) {
   ZoneGrowableArray<Representation>* arg_representations =
-      ffi::ArgumentRepresentations(signature);
+      compiler::ffi::ArgumentRepresentations(signature);
   ZoneGrowableArray<Location>* arg_locations =
-      ffi::ArgumentLocations(*arg_representations);
+      compiler::ffi::ArgumentLocations(*arg_representations);
 
   intptr_t num_dart_arguments = signature.num_fixed_parameters();
   intptr_t num_arguments = num_dart_arguments - 1;  // Ignore closure.
diff --git a/runtime/vm/heap/compactor.cc b/runtime/vm/heap/compactor.cc
index e3073a0..91e2058 100644
--- a/runtime/vm/heap/compactor.cc
+++ b/runtime/vm/heap/compactor.cc
@@ -483,6 +483,10 @@
         // Slide the object down.
         memmove(reinterpret_cast<void*>(new_addr),
                 reinterpret_cast<void*>(old_addr), size);
+
+        if (RawObject::IsTypedDataClassId(new_obj->GetClassId())) {
+          reinterpret_cast<RawTypedData*>(new_obj)->ResetData();
+        }
       }
       new_obj->ClearMarkBit();
       new_obj->VisitPointers(compactor_);
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index 35675f4..a7220d1 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -727,6 +727,18 @@
                        : old_space_.ExternalInWords();
 }
 
+int64_t Heap::TotalUsedInWords() const {
+  return UsedInWords(kNew) + UsedInWords(kOld);
+}
+
+int64_t Heap::TotalCapacityInWords() const {
+  return CapacityInWords(kNew) + CapacityInWords(kOld);
+}
+
+int64_t Heap::TotalExternalInWords() const {
+  return ExternalInWords(kNew) + ExternalInWords(kOld);
+}
+
 int64_t Heap::GCTimeInMicros(Space space) const {
   if (space == kNew) {
     return new_space_.gc_time_micros();
@@ -851,6 +863,14 @@
     old_space_.PrintToJSONObject(object);
   }
 }
+
+void Heap::PrintMemoryUsageJSON(JSONStream* stream) const {
+  JSONObject jsobj(stream);
+  jsobj.AddProperty("type", "MemoryUsage");
+  jsobj.AddProperty64("heapUsage", TotalUsedInWords() * kWordSize);
+  jsobj.AddProperty64("heapCapacity", TotalCapacityInWords() * kWordSize);
+  jsobj.AddProperty64("externalUsage", TotalExternalInWords() * kWordSize);
+}
 #endif  // PRODUCT
 
 void Heap::RecordBeforeGC(GCType type, GCReason reason) {
diff --git a/runtime/vm/heap/heap.h b/runtime/vm/heap/heap.h
index 5ae4083..628ab15 100644
--- a/runtime/vm/heap/heap.h
+++ b/runtime/vm/heap/heap.h
@@ -180,6 +180,10 @@
   int64_t UsedInWords(Space space) const;
   int64_t CapacityInWords(Space space) const;
   int64_t ExternalInWords(Space space) const;
+
+  int64_t TotalUsedInWords() const;
+  int64_t TotalCapacityInWords() const;
+  int64_t TotalExternalInWords() const;
   // Return the amount of GCing in microseconds.
   int64_t GCTimeInMicros(Space space) const;
 
@@ -268,6 +272,10 @@
 #ifndef PRODUCT
   void PrintToJSONObject(Space space, JSONObject* object) const;
 
+  // Returns a JSON object with total memory usage statistics for both new and
+  // old space combined.
+  void PrintMemoryUsageJSON(JSONStream* stream) const;
+
   // The heap map contains the sizes and class ids for the objects in each page.
   void PrintHeapMapToJSONStream(Isolate* isolate, JSONStream* stream) {
     old_space_.PrintHeapMapToJSONStream(isolate, stream);
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index 03c9683..6f4a183 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -368,6 +368,10 @@
   }
 
   static bool TryAcquireMarkBit(RawObject* raw_obj) {
+    if (FLAG_write_protect_code && raw_obj->IsInstructions()) {
+      // A non-writable alias mapping may exist for instruction pages.
+      raw_obj = HeapPage::ToWritable(raw_obj);
+    }
     if (!sync) {
       raw_obj->SetMarkBitUnsynchronized();
       return true;
@@ -487,8 +491,9 @@
   isolate_->ReleaseStoreBuffers();
 
 #ifndef DART_PRECOMPILED_RUNTIME
-  if (isolate_->IsMutatorThreadScheduled()) {
-    Interpreter* interpreter = isolate_->mutator_thread()->interpreter();
+  Thread* mutator_thread = isolate_->mutator_thread();
+  if (mutator_thread != NULL) {
+    Interpreter* interpreter = mutator_thread->interpreter();
     if (interpreter != NULL) {
       interpreter->MajorGC();
     }
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index e1ac801..19d8f04 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -57,11 +57,8 @@
 HeapPage* HeapPage::Allocate(intptr_t size_in_words,
                              PageType type,
                              const char* name) {
-  bool is_executable = (type == kExecutable);
-  // Create the new page executable (RWX) only if we're not in W^X mode
-  bool create_executable = !FLAG_write_protect_code && is_executable;
   VirtualMemory* memory = VirtualMemory::AllocateAligned(
-      size_in_words << kWordSizeLog2, kPageSize, create_executable, name);
+      size_in_words << kWordSizeLog2, kPageSize, type == kExecutable, name);
   if (memory == NULL) {
     return NULL;
   }
@@ -214,7 +211,7 @@
 
   VirtualMemory::Protection prot;
   if (read_only) {
-    if (type_ == kExecutable) {
+    if ((type_ == kExecutable) && (memory_->AliasOffset() == 0)) {
       prot = VirtualMemory::kReadExecute;
     } else {
       prot = VirtualMemory::kReadOnly;
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index 98d480f..d7381d7 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -40,7 +40,8 @@
   HeapPage* next() const { return next_; }
   void set_next(HeapPage* next) { next_ = next; }
 
-  bool Contains(uword addr) { return memory_->Contains(addr); }
+  bool Contains(uword addr) const { return memory_->Contains(addr); }
+  intptr_t AliasOffset() const { return memory_->AliasOffset(); }
 
   uword object_start() const { return memory_->start() + ObjectStartOffset(); }
   uword object_end() const { return object_end_; }
@@ -70,7 +71,8 @@
   }
 
   // Warning: This does not work for objects on image pages because image pages
-  // are not aligned.
+  // are not aligned. However, it works for objects on large pages, because
+  // only one object is allocated per large page.
   static HeapPage* Of(RawObject* obj) {
     ASSERT(obj->IsHeapObject());
     ASSERT(obj->IsOldObject());
@@ -78,10 +80,45 @@
                                        kPageMask);
   }
 
-  static HeapPage* Of(uintptr_t addr) {
+  // Warning: This does not work for addresses on image pages or on large pages.
+  static HeapPage* Of(uword addr) {
     return reinterpret_cast<HeapPage*>(addr & kPageMask);
   }
 
+  // Warning: This does not work for objects on image pages.
+  static RawObject* ToExecutable(RawObject* obj) {
+    HeapPage* page = Of(obj);
+    VirtualMemory* memory = page->memory_;
+    const intptr_t alias_offset = memory->AliasOffset();
+    if (alias_offset == 0) {
+      return obj;  // Not aliased.
+    }
+    uword addr = RawObject::ToAddr(obj);
+    if (memory->Contains(addr)) {
+      return RawObject::FromAddr(addr + alias_offset);
+    }
+    // obj is executable.
+    ASSERT(memory->ContainsAlias(addr));
+    return obj;
+  }
+
+  // Warning: This does not work for objects on image pages.
+  static RawObject* ToWritable(RawObject* obj) {
+    HeapPage* page = Of(obj);
+    VirtualMemory* memory = page->memory_;
+    const intptr_t alias_offset = memory->AliasOffset();
+    if (alias_offset == 0) {
+      return obj;  // Not aliased.
+    }
+    uword addr = RawObject::ToAddr(obj);
+    if (memory->ContainsAlias(addr)) {
+      return RawObject::FromAddr(addr - alias_offset);
+    }
+    // obj is writable.
+    ASSERT(memory->Contains(addr));
+    return obj;
+  }
+
   // 1 card = 128 slots.
   static const intptr_t kSlotsPerCardLog2 = 7;
   static const intptr_t kBytesPerCardLog2 = kWordSizeLog2 + kSlotsPerCardLog2;
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index 7abe066..0242715 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -60,6 +60,31 @@
   *reinterpret_cast<uword*>(original) = target | kForwarded;
 }
 
+static inline void objcpy(void* dst, const void* src, size_t size) {
+  // A memcopy specialized for objects. We can assume:
+  //  - dst and src do not overlap
+  ASSERT(
+      (reinterpret_cast<uword>(dst) + size <= reinterpret_cast<uword>(src)) ||
+      (reinterpret_cast<uword>(src) + size <= reinterpret_cast<uword>(dst)));
+  //  - dst and src are word aligned
+  ASSERT(Utils::IsAligned(reinterpret_cast<uword>(dst), sizeof(uword)));
+  ASSERT(Utils::IsAligned(reinterpret_cast<uword>(src), sizeof(uword)));
+  //  - size is strictly positive
+  ASSERT(size > 0);
+  //  - size is a multiple of double words
+  ASSERT(Utils::IsAligned(size, 2 * sizeof(uword)));
+
+  uword* __restrict dst_cursor = reinterpret_cast<uword*>(dst);
+  const uword* __restrict src_cursor = reinterpret_cast<const uword*>(src);
+  do {
+    uword a = *src_cursor++;
+    uword b = *src_cursor++;
+    *dst_cursor++ = a;
+    *dst_cursor++ = b;
+    size -= (2 * sizeof(uword));
+  } while (size > 0);
+}
+
 class ScavengerVisitor : public ObjectPointerVisitor {
  public:
   explicit ScavengerVisitor(Isolate* isolate,
@@ -163,8 +188,8 @@
       // current objects to the to space.
       ASSERT(new_addr != 0);
       // Copy the object to the new location.
-      memmove(reinterpret_cast<void*>(new_addr),
-              reinterpret_cast<void*>(raw_addr), size);
+      objcpy(reinterpret_cast<void*>(new_addr),
+             reinterpret_cast<void*>(raw_addr), size);
 
       RawObject* new_obj = RawObject::FromAddr(new_addr);
       if (new_obj->IsOldObject()) {
@@ -183,6 +208,10 @@
         new_obj->ptr()->tags_ = tags;
       }
 
+      if (RawObject::IsTypedDataClassId(new_obj->GetClassId())) {
+        reinterpret_cast<RawTypedData*>(new_obj)->ResetData();
+      }
+
       // Remember forwarding address.
       ForwardTo(raw_addr, new_addr);
     }
@@ -422,6 +451,7 @@
   NOT_IN_PRODUCT(isolate->class_table()->ResetCountersNew());
 
   isolate->ReleaseStoreBuffers();
+  AbandonTLABs(isolate);
 
   // Flip the two semi-spaces so that to_ is always the space for allocating
   // objects.
@@ -833,11 +863,12 @@
   }
 }
 
-void Scavenger::MakeAllTLABsIterable(Isolate* isolate) const {
-  MonitorLocker ml(isolate->threads_lock(), false);
+void Scavenger::MakeNewSpaceIterable() const {
   ASSERT(Thread::Current()->IsAtSafepoint() ||
          (Thread::Current()->task_kind() == Thread::kMarkerTask) ||
          (Thread::Current()->task_kind() == Thread::kCompactorTask));
+  Isolate* isolate = heap_->isolate();
+  MonitorLocker ml(isolate->threads_lock(), false);
   Thread* current = heap_->isolate()->thread_registry()->active_list();
   while (current != NULL) {
     if (current->HasActiveTLAB()) {
@@ -846,22 +877,12 @@
     current = current->next();
   }
   Thread* mutator_thread = isolate->mutator_thread();
-  if ((mutator_thread != NULL) && (!isolate->IsMutatorThreadScheduled())) {
+  if (mutator_thread != NULL) {
     heap_->MakeTLABIterable(mutator_thread);
   }
 }
 
-void Scavenger::MakeNewSpaceIterable() const {
-  ASSERT(heap_ != NULL);
-  ASSERT(Thread::Current()->IsAtSafepoint() ||
-         (Thread::Current()->task_kind() == Thread::kMarkerTask) ||
-         (Thread::Current()->task_kind() == Thread::kCompactorTask));
-  if (!scavenging_) {
-    MakeAllTLABsIterable(heap_->isolate());
-  }
-}
-
-void Scavenger::AbandonAllTLABs(Isolate* isolate) {
+void Scavenger::AbandonTLABs(Isolate* isolate) {
   ASSERT(Thread::Current()->IsAtSafepoint());
   MonitorLocker ml(isolate->threads_lock(), false);
   Thread* current = isolate->thread_registry()->active_list();
@@ -870,7 +891,7 @@
     current = current->next();
   }
   Thread* mutator_thread = isolate->mutator_thread();
-  if ((mutator_thread != NULL) && (!isolate->IsMutatorThreadScheduled())) {
+  if (mutator_thread != NULL) {
     heap_->AbandonRemainingTLAB(mutator_thread);
   }
 }
@@ -975,13 +996,6 @@
   int64_t safe_point = OS::GetCurrentMonotonicMicros();
   heap_->RecordTime(kSafePoint, safe_point - start);
 
-  AbandonAllTLABs(isolate);
-
-  Thread* mutator_thread = isolate->mutator_thread();
-  if ((mutator_thread != NULL) && (mutator_thread->HasActiveTLAB())) {
-    heap_->AbandonRemainingTLAB(mutator_thread);
-  }
-
   // TODO(koda): Make verification more compatible with concurrent sweep.
   if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) {
     OS::PrintErr("Verifying before Scavenge...");
@@ -990,7 +1004,6 @@
   }
 
   // Prepare for a scavenge.
-  MakeNewSpaceIterable();
   SpaceUsage usage_before = GetCurrentUsage();
   intptr_t promo_candidate_words =
       (survivor_end_ - FirstObjectStart()) / kWordSize;
diff --git a/runtime/vm/heap/scavenger.h b/runtime/vm/heap/scavenger.h
index 1a6fe0a..7e5f623 100644
--- a/runtime/vm/heap/scavenger.h
+++ b/runtime/vm/heap/scavenger.h
@@ -218,8 +218,7 @@
 
   void MakeNewSpaceIterable() const;
   int64_t FreeSpaceInWords(Isolate* isolate) const;
-  void MakeAllTLABsIterable(Isolate* isolate) const;
-  void AbandonAllTLABs(Isolate* isolate);
+  void AbandonTLABs(Isolate* isolate);
 
  private:
   // Ids for time and data records in Heap::GCStats.
diff --git a/runtime/vm/heap/verifier.cc b/runtime/vm/heap/verifier.cc
index 8ea2fdb..237777e 100644
--- a/runtime/vm/heap/verifier.cc
+++ b/runtime/vm/heap/verifier.cc
@@ -49,6 +49,10 @@
     RawObject* raw_obj = *current;
     if (raw_obj->IsHeapObject()) {
       if (!allocated_set_->Contains(raw_obj)) {
+        if (raw_obj->IsInstructions() &&
+            allocated_set_->Contains(HeapPage::ToWritable(raw_obj))) {
+          continue;
+        }
         uword raw_addr = RawObject::ToAddr(raw_obj);
         FATAL1("Invalid object pointer encountered %#" Px "\n", raw_addr);
       }
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index 88e6bb9..4ca767d 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -157,8 +157,9 @@
     ObjectOffsetPair* pair = reuse_instructions_.Lookup(instructions);
     if (pair == NULL) {
       // Code should have been removed by DropCodeWithoutReusableInstructions.
-      FATAL("Expected instructions to reuse\n");
+      return 0;
     }
+    ASSERT(pair->offset != 0);
     return pair->offset;
   }
 
@@ -167,6 +168,7 @@
     // Negative offsets tell the reader the offset is w/r/t the shared
     // instructions image instead of the app-specific instructions image.
     // Compare ImageReader::GetInstructionsAt.
+    ASSERT(pair->offset != 0);
     return -pair->offset;
   }
 
@@ -175,6 +177,7 @@
   next_text_offset_ += instructions->HeapSize();
   instructions_.Add(InstructionsData(instructions, code, offset));
 
+  ASSERT(offset != 0);
   return offset;
 }
 
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index 49a8ddc..3e897e7 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -584,8 +584,40 @@
       RawInstance* instance = reinterpret_cast<RawInstance*>(*call_base);
       RawField* field = reinterpret_cast<RawField*>(function->ptr()->data_);
       intptr_t offset_in_words = Smi::Value(field->ptr()->value_.offset_);
+      RawObject* value =
+          reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
+
+      const bool unboxing =
+          (field->ptr()->is_nullable_ != kNullCid) &&
+          Field::UnboxingCandidateBit::decode(field->ptr()->kind_bits_);
+      classid_t guarded_cid = field->ptr()->guarded_cid_;
+      if (unboxing && (guarded_cid == kDoubleCid)) {
+        double raw_value = Double::RawCast(value)->ptr()->value_;
+        if (!AllocateDoubleBox(thread, raw_value, *pc, *FP, *SP)) {
+          *invoked = true;
+          return false;
+        }
+        value = Double::RawCast(*SP[0]);
+      } else if (unboxing && (guarded_cid == kFloat32x4Cid)) {
+        simd128_value_t raw_value;
+        raw_value.readFrom(Float32x4::RawCast(value)->ptr()->value_);
+        if (!AllocateFloat32x4Box(thread, raw_value, *pc, *FP, *SP)) {
+          *invoked = true;
+          return false;
+        }
+        value = Float32x4::RawCast(*SP[0]);
+      } else if (unboxing && (guarded_cid == kFloat64x2Cid)) {
+        simd128_value_t raw_value;
+        raw_value.readFrom(Float64x2::RawCast(value)->ptr()->value_);
+        if (!AllocateFloat64x2Box(thread, raw_value, *pc, *FP, *SP)) {
+          *invoked = true;
+          return false;
+        }
+        value = Float64x2::RawCast(*SP[0]);
+      }
+
       *SP = call_base;
-      **SP = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
+      **SP = value;
       *invoked = true;
       return true;
     }
@@ -669,9 +701,39 @@
         instance = reinterpret_cast<RawInstance*>(call_base[0]);
         value = call_base[1];
       }
-      instance->StorePointer(
-          reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words,
-          value, thread);
+
+      const bool unboxing =
+          (field->ptr()->is_nullable_ != kNullCid) &&
+          Field::UnboxingCandidateBit::decode(field->ptr()->kind_bits_);
+      classid_t guarded_cid = field->ptr()->guarded_cid_;
+      if (unboxing && (guarded_cid == kDoubleCid)) {
+        double raw_value = Double::RawCast(value)->ptr()->value_;
+        RawDouble* box =
+            *(reinterpret_cast<RawDouble**>(instance->ptr()) + offset_in_words);
+        ASSERT(box != null_value);  // Non-initializing store.
+        box->ptr()->value_ = raw_value;
+      } else if (unboxing && (guarded_cid == kFloat32x4Cid)) {
+        simd128_value_t raw_value;
+        raw_value.readFrom(Float32x4::RawCast(value)->ptr()->value_);
+        RawFloat32x4* box =
+            *(reinterpret_cast<RawFloat32x4**>(instance->ptr()) +
+              offset_in_words);
+        ASSERT(box != null_value);  // Non-initializing store.
+        raw_value.writeTo(box->ptr()->value_);
+      } else if (unboxing && (guarded_cid == kFloat64x2Cid)) {
+        simd128_value_t raw_value;
+        raw_value.readFrom(Float64x2::RawCast(value)->ptr()->value_);
+        RawFloat64x2* box =
+            *(reinterpret_cast<RawFloat64x2**>(instance->ptr()) +
+              offset_in_words);
+        ASSERT(box != null_value);  // Non-initializing store.
+        raw_value.writeTo(box->ptr()->value_);
+      } else {
+        instance->StorePointer(
+            reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words,
+            value, thread);
+      }
+
       *SP = call_base;
       **SP = null_value;
       *invoked = true;
@@ -1350,8 +1412,111 @@
     if (!InvokeRuntime(thread, this, DRT_AllocateObject, args)) {
       return false;
     }
-    *reinterpret_cast<int64_t*>(reinterpret_cast<uword>(SP[0]) -
-                                kHeapObjectTag + Mint::value_offset()) = value;
+    reinterpret_cast<RawMint*>(SP[0])->ptr()->value_ = value;
+    return true;
+  }
+}
+
+// Allocate _Double box for the given double value and puts it into SP[0].
+// Returns false on exception.
+DART_NOINLINE bool Interpreter::AllocateDoubleBox(Thread* thread,
+                                                  double value,
+                                                  uint32_t* pc,
+                                                  RawObject** FP,
+                                                  RawObject** SP) {
+  const intptr_t instance_size = Double::InstanceSize();
+  const uword start =
+      thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size);
+  if (LIKELY(start != 0)) {
+    uword tags = 0;
+    tags = RawObject::ClassIdTag::update(kDoubleCid, tags);
+    tags = RawObject::SizeTag::update(instance_size, tags);
+    tags = RawObject::NewBit::update(true, tags);
+    // Also writes zero in the hash_ field.
+    *reinterpret_cast<uword*>(start + Double::tags_offset()) = tags;
+    *reinterpret_cast<double*>(start + Double::value_offset()) = value;
+    SP[0] = reinterpret_cast<RawObject*>(start + kHeapObjectTag);
+    return true;
+  } else {
+    SP[0] = 0;  // Space for the result.
+    SP[1] = thread->isolate()->object_store()->double_class();  // Class object.
+    SP[2] = Object::null();  // Type arguments.
+    Exit(thread, FP, SP + 3, pc);
+    NativeArguments args(thread, 2, SP + 1, SP);
+    if (!InvokeRuntime(thread, this, DRT_AllocateObject, args)) {
+      return false;
+    }
+    reinterpret_cast<RawDouble*>(SP[0])->ptr()->value_ = value;
+    return true;
+  }
+}
+
+// Allocate _Float32x4 box for the given simd value and puts it into SP[0].
+// Returns false on exception.
+DART_NOINLINE bool Interpreter::AllocateFloat32x4Box(Thread* thread,
+                                                     simd128_value_t value,
+                                                     uint32_t* pc,
+                                                     RawObject** FP,
+                                                     RawObject** SP) {
+  const intptr_t instance_size = Float32x4::InstanceSize();
+  const uword start =
+      thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size);
+  if (LIKELY(start != 0)) {
+    uword tags = 0;
+    tags = RawObject::ClassIdTag::update(kFloat32x4Cid, tags);
+    tags = RawObject::SizeTag::update(instance_size, tags);
+    tags = RawObject::NewBit::update(true, tags);
+    // Also writes zero in the hash_ field.
+    *reinterpret_cast<uword*>(start + Float32x4::tags_offset()) = tags;
+    SP[0] = reinterpret_cast<RawObject*>(start + kHeapObjectTag);
+    value.writeTo(reinterpret_cast<RawFloat32x4*>(SP[0])->ptr()->value_);
+    return true;
+  } else {
+    SP[0] = 0;  // Space for the result.
+    SP[1] =
+        thread->isolate()->object_store()->float32x4_class();  // Class object.
+    SP[2] = Object::null();  // Type arguments.
+    Exit(thread, FP, SP + 3, pc);
+    NativeArguments args(thread, 2, SP + 1, SP);
+    if (!InvokeRuntime(thread, this, DRT_AllocateObject, args)) {
+      return false;
+    }
+    value.writeTo(reinterpret_cast<RawFloat32x4*>(SP[0])->ptr()->value_);
+    return true;
+  }
+}
+
+// Allocate _Float64x2 box for the given simd value and puts it into SP[0].
+// Returns false on exception.
+DART_NOINLINE bool Interpreter::AllocateFloat64x2Box(Thread* thread,
+                                                     simd128_value_t value,
+                                                     uint32_t* pc,
+                                                     RawObject** FP,
+                                                     RawObject** SP) {
+  const intptr_t instance_size = Float64x2::InstanceSize();
+  const uword start =
+      thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size);
+  if (LIKELY(start != 0)) {
+    uword tags = 0;
+    tags = RawObject::ClassIdTag::update(kFloat64x2Cid, tags);
+    tags = RawObject::SizeTag::update(instance_size, tags);
+    tags = RawObject::NewBit::update(true, tags);
+    // Also writes zero in the hash_ field.
+    *reinterpret_cast<uword*>(start + Float64x2::tags_offset()) = tags;
+    SP[0] = reinterpret_cast<RawObject*>(start + kHeapObjectTag);
+    value.writeTo(reinterpret_cast<RawFloat64x2*>(SP[0])->ptr()->value_);
+    return true;
+  } else {
+    SP[0] = 0;  // Space for the result.
+    SP[1] =
+        thread->isolate()->object_store()->float64x2_class();  // Class object.
+    SP[2] = Object::null();  // Type arguments.
+    Exit(thread, FP, SP + 3, pc);
+    NativeArguments args(thread, 2, SP + 1, SP);
+    if (!InvokeRuntime(thread, this, DRT_AllocateObject, args)) {
+      return false;
+    }
+    value.writeTo(reinterpret_cast<RawFloat32x4*>(SP[0])->ptr()->value_);
     return true;
   }
 }
@@ -2230,30 +2395,74 @@
     RawField* field = RAW_CAST(Field, LOAD_CONSTANT(rD + 1));
     RawInstance* instance = reinterpret_cast<RawInstance*>(SP[-1]);
     RawObject* value = reinterpret_cast<RawObject*>(SP[0]);
-    SP -= 2;  // Drop instance and value.
     intptr_t offset_in_words = Smi::Value(field->ptr()->value_.offset_);
 
     if (thread->isolate()->use_field_guards() &&
         InterpreterHelpers::FieldNeedsGuardUpdate(field, value)) {
-      SP[1] = instance;  // Preserve.
-      SP[2] = 0;         // Unused result of runtime call.
-      SP[3] = field;
-      SP[4] = value;
-      Exit(thread, FP, SP + 5, pc);
-      NativeArguments args(thread, 2, /* argv */ SP + 3, /* retval */ SP + 2);
+      SP[1] = 0;  // Unused result of runtime call.
+      SP[2] = field;
+      SP[3] = value;
+      Exit(thread, FP, SP + 4, pc);
+      NativeArguments args(thread, 2, /* argv */ SP + 2, /* retval */ SP + 1);
       if (!InvokeRuntime(thread, this, DRT_UpdateFieldCid, args)) {
         HANDLE_EXCEPTION;
       }
 
       // Reload objects after the call which may trigger GC.
-      instance = reinterpret_cast<RawInstance*>(SP[1]);
-      value = SP[4];
+      field = RAW_CAST(Field, LOAD_CONSTANT(rD + 1));
+      instance = reinterpret_cast<RawInstance*>(SP[-1]);
+      value = SP[0];
     }
 
-    instance->StorePointer(
-        reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words, value,
-        thread);
+    const bool unboxing =
+        (field->ptr()->is_nullable_ != kNullCid) &&
+        Field::UnboxingCandidateBit::decode(field->ptr()->kind_bits_);
+    classid_t guarded_cid = field->ptr()->guarded_cid_;
+    if (unboxing && (guarded_cid == kDoubleCid)) {
+      double raw_value = Double::RawCast(value)->ptr()->value_;
+      ASSERT(*(reinterpret_cast<RawDouble**>(instance->ptr()) +
+               offset_in_words) == null_value);  // Initializing store.
+      if (!AllocateDoubleBox(thread, raw_value, pc, FP, SP)) {
+        HANDLE_EXCEPTION;
+      }
+      RawDouble* box = Double::RawCast(SP[0]);
+      instance = reinterpret_cast<RawInstance*>(SP[-1]);
+      instance->StorePointer(
+          reinterpret_cast<RawDouble**>(instance->ptr()) + offset_in_words, box,
+          thread);
+    } else if (unboxing && (guarded_cid == kFloat32x4Cid)) {
+      simd128_value_t raw_value;
+      raw_value.readFrom(Float32x4::RawCast(value)->ptr()->value_);
+      ASSERT(*(reinterpret_cast<RawFloat32x4**>(instance->ptr()) +
+               offset_in_words) == null_value);  // Initializing store.
+      if (!AllocateFloat32x4Box(thread, raw_value, pc, FP, SP)) {
+        HANDLE_EXCEPTION;
+      }
+      RawFloat32x4* box = Float32x4::RawCast(SP[0]);
+      instance = reinterpret_cast<RawInstance*>(SP[-1]);
+      instance->StorePointer(
+          reinterpret_cast<RawFloat32x4**>(instance->ptr()) + offset_in_words,
+          box, thread);
+    } else if (unboxing && (guarded_cid == kFloat64x2Cid)) {
+      simd128_value_t raw_value;
+      raw_value.readFrom(Float64x2::RawCast(value)->ptr()->value_);
+      ASSERT(*(reinterpret_cast<RawFloat64x2**>(instance->ptr()) +
+               offset_in_words) == null_value);  // Initializing store.
+      if (!AllocateFloat64x2Box(thread, raw_value, pc, FP, SP)) {
+        HANDLE_EXCEPTION;
+      }
+      RawFloat64x2* box = Float64x2::RawCast(SP[0]);
+      instance = reinterpret_cast<RawInstance*>(SP[-1]);
+      instance->StorePointer(
+          reinterpret_cast<RawFloat64x2**>(instance->ptr()) + offset_in_words,
+          box, thread);
+    } else {
+      instance->StorePointer(
+          reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words,
+          value, thread);
+    }
 
+    SP -= 2;  // Drop instance and value.
     DISPATCH();
   }
 
@@ -2289,6 +2498,16 @@
 
   {
     BYTECODE(LoadFieldTOS, __D);
+#if defined(DEBUG)
+    // Currently only used to load closure fields, which are not unboxed.
+    // If used for general field, code for copying the mutable box must be
+    // added.
+    RawField* field = RAW_CAST(Field, LOAD_CONSTANT(rD + 1));
+    const bool unboxing =
+        (field->ptr()->is_nullable_ != kNullCid) &&
+        Field::UnboxingCandidateBit::decode(field->ptr()->kind_bits_);
+    ASSERT(!unboxing);
+#endif
     const uword offset_in_words =
         static_cast<uword>(Smi::Value(RAW_CAST(Smi, LOAD_CONSTANT(rD))));
     RawInstance* instance = static_cast<RawInstance*>(SP[0]);
diff --git a/runtime/vm/interpreter.h b/runtime/vm/interpreter.h
index 4e98f3e..effc48a 100644
--- a/runtime/vm/interpreter.h
+++ b/runtime/vm/interpreter.h
@@ -210,6 +210,21 @@
                         uint32_t* pc,
                         RawObject** FP,
                         RawObject** SP);
+  bool AllocateDoubleBox(Thread* thread,
+                         double value,
+                         uint32_t* pc,
+                         RawObject** FP,
+                         RawObject** SP);
+  bool AllocateFloat32x4Box(Thread* thread,
+                            simd128_value_t value,
+                            uint32_t* pc,
+                            RawObject** FP,
+                            RawObject** SP);
+  bool AllocateFloat64x2Box(Thread* thread,
+                            simd128_value_t value,
+                            uint32_t* pc,
+                            RawObject** FP,
+                            RawObject** SP);
 
 #if defined(DEBUG)
   // Returns true if tracing of executed instructions is enabled.
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 6be1715..ce8ed3f 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -2288,6 +2288,14 @@
 
   jsobj.AddProperty("_threads", thread_registry_);
 }
+
+void Isolate::PrintMemoryUsageJSON(JSONStream* stream) {
+  if (!FLAG_support_service) {
+    return;
+  }
+  heap()->PrintMemoryUsageJSON(stream);
+}
+
 #endif
 
 void Isolate::set_tag_table(const GrowableObjectArray& value) {
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 086831b..40f0c6f 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -238,11 +238,6 @@
 
   Thread* mutator_thread() const;
 
-  // Mutator thread is not scheduled if NULL or no heap is attached
-  // to it. The latter only occurs when the mutator thread object
-  // is unscheduled by the isolate (or never scheduled).
-  bool IsMutatorThreadScheduled() { return scheduled_mutator_thread_ != NULL; }
-
   const char* name() const { return name_; }
   void set_name(const char* name);
 
@@ -520,6 +515,10 @@
 
 #ifndef PRODUCT
   void PrintJSON(JSONStream* stream, bool ref = true);
+
+  // Creates an object with the total heap memory usage statistics for this
+  // isolate.
+  void PrintMemoryUsageJSON(JSONStream* stream);
 #endif
 
 #if !defined(PRODUCT)
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index edf12af..5d67407 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -4,6 +4,7 @@
 
 #include "vm/kernel.h"
 
+#include "vm/bit_vector.h"
 #include "vm/compiler/frontend/constant_evaluator.h"
 #include "vm/compiler/frontend/kernel_translation_helper.h"
 #include "vm/longjump.h"
@@ -585,91 +586,100 @@
   }
 }
 
-bool NeedsDynamicInvocationForwarder(const Function& function) {
+void ReadParameterCovariance(const Function& function,
+                             BitVector* is_covariant,
+                             BitVector* is_generic_covariant_impl) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
 
-  TranslationHelper helper(thread);
-  Script& script = Script::Handle(zone, function.script());
-  helper.InitFromScript(script);
+  const intptr_t num_params = function.NumParameters();
+  ASSERT(is_covariant->length() == num_params);
+  ASSERT(is_generic_covariant_impl->length() == num_params);
 
-  // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used
-  // e.g. for type translation.
-
-  const Class& owner_class = Class::Handle(zone, function.Owner());
-  Function& outermost_function =
-      Function::Handle(zone, function.GetOutermostFunction());
-
-  ActiveClass active_class;
-  ActiveClassScope active_class_scope(&active_class, &owner_class);
-  ActiveMemberScope active_member(&active_class, &outermost_function);
-  ActiveTypeParametersScope active_type_params(&active_class, function, zone);
+  const auto& script = Script::Handle(zone, function.script());
+  TranslationHelper translation_helper(thread);
+  translation_helper.InitFromScript(script);
 
   KernelReaderHelper reader_helper(
-      zone, &helper, script,
+      zone, &translation_helper, script,
       ExternalTypedData::Handle(zone, function.KernelData()),
       function.KernelDataProgramOffset());
 
-  TypeTranslator type_translator(&reader_helper, &active_class,
-                                 /* finalize= */ true);
-
   reader_helper.SetOffset(function.kernel_offset());
-
-  // Handle setters.
-  if (reader_helper.PeekTag() == kField) {
-    ASSERT(function.IsImplicitSetterFunction());
-    FieldHelper field_helper(&reader_helper);
-    field_helper.ReadUntilIncluding(FieldHelper::kFlags);
-    return !(field_helper.IsCovariant() ||
-             field_helper.IsGenericCovariantImpl());
-  }
-
   reader_helper.ReadUntilFunctionNode();
 
   FunctionNodeHelper function_node_helper(&reader_helper);
-  function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
-  intptr_t num_type_params = reader_helper.ReadListLength();
-
-  for (intptr_t i = 0; i < num_type_params; ++i) {
-    TypeParameterHelper helper(&reader_helper);
-    helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound);
-    AbstractType& bound = type_translator.BuildType();  // read bound
-    helper.Finish();
-
-    if (!bound.IsTopType() && !helper.IsGenericCovariantImpl()) {
-      return true;
-    }
-  }
-  function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters);
   function_node_helper.ReadUntilExcluding(
       FunctionNodeHelper::kPositionalParameters);
 
   // Positional.
   const intptr_t num_positional_params = reader_helper.ReadListLength();
-  for (intptr_t i = 0; i < num_positional_params; ++i) {
+  intptr_t param_index = function.NumImplicitParameters();
+  for (intptr_t i = 0; i < num_positional_params; ++i, ++param_index) {
     VariableDeclarationHelper helper(&reader_helper);
-    helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
-    AbstractType& type = type_translator.BuildType();  // read type.
-    helper.SetJustRead(VariableDeclarationHelper::kType);
     helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);
 
-    if (!type.IsTopType() && !helper.IsGenericCovariantImpl() &&
-        !helper.IsCovariant()) {
-      return true;
+    if (helper.IsCovariant()) {
+      is_covariant->Add(param_index);
+    }
+    if (helper.IsGenericCovariantImpl()) {
+      is_generic_covariant_impl->Add(param_index);
     }
   }
 
   // Named.
   const intptr_t num_named_params = reader_helper.ReadListLength();
-  for (intptr_t i = 0; i < num_named_params; ++i) {
+  for (intptr_t i = 0; i < num_named_params; ++i, ++param_index) {
     VariableDeclarationHelper helper(&reader_helper);
-    helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
-    AbstractType& type = type_translator.BuildType();  // read type.
-    helper.SetJustRead(VariableDeclarationHelper::kType);
     helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);
 
-    if (!type.IsTopType() && !helper.IsGenericCovariantImpl() &&
-        !helper.IsCovariant()) {
+    if (helper.IsCovariant()) {
+      is_covariant->Add(param_index);
+    }
+    if (helper.IsGenericCovariantImpl()) {
+      is_generic_covariant_impl->Add(param_index);
+    }
+  }
+}
+
+bool NeedsDynamicInvocationForwarder(const Function& function) {
+  Zone* zone = Thread::Current()->zone();
+
+  // Covariant parameters (both explicitly covariant and generic-covariant-impl)
+  // are checked in the body of a function and therefore don't need checks in a
+  // dynamic invocation forwarder. So dynamic invocation forwarder is only
+  // needed if there are non-covariant parameters of non-top type.
+
+  ASSERT(!function.IsImplicitGetterFunction());
+  if (function.IsImplicitSetterFunction()) {
+    const auto& field = Field::Handle(zone, function.accessor_field());
+    return !(field.is_covariant() || field.is_generic_covariant_impl());
+  }
+
+  const auto& type_params =
+      TypeArguments::Handle(zone, function.type_parameters());
+  if (!type_params.IsNull()) {
+    auto& type_param = TypeParameter::Handle(zone);
+    auto& bound = AbstractType::Handle(zone);
+    for (intptr_t i = 0, n = type_params.Length(); i < n; ++i) {
+      type_param ^= type_params.TypeAt(i);
+      bound = type_param.bound();
+      if (!bound.IsTopType() && !type_param.IsGenericCovariantImpl()) {
+        return true;
+      }
+    }
+  }
+
+  const intptr_t num_params = function.NumParameters();
+  BitVector is_covariant(zone, num_params);
+  BitVector is_generic_covariant_impl(zone, num_params);
+  ReadParameterCovariance(function, &is_covariant, &is_generic_covariant_impl);
+
+  auto& type = AbstractType::Handle(zone);
+  for (intptr_t i = function.NumImplicitParameters(); i < num_params; ++i) {
+    type = function.ParameterTypeAt(i);
+    if (!type.IsTopType() && !is_generic_covariant_impl.Contains(i) &&
+        !is_covariant.Contains(i)) {
       return true;
     }
   }
diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h
index 34609b8..db52690 100644
--- a/runtime/vm/kernel.h
+++ b/runtime/vm/kernel.h
@@ -32,6 +32,7 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
 namespace dart {
 
+class BitVector;
 class Field;
 class ParsedFunction;
 class Zone;
@@ -194,6 +195,15 @@
                             bool is_annotations_offset);
 RawObject* BuildParameterDescriptor(const Function& function);
 
+// Fills in [is_covariant] and [is_generic_covariant_impl] vectors
+// according to covariance attributes of [function] parameters.
+//
+// [is_covariant] and [is_generic_covariant_impl] should contain bitvectors
+// of function.NumParameters() length.
+void ReadParameterCovariance(const Function& function,
+                             BitVector* is_covariant,
+                             BitVector* is_generic_covariant_impl);
+
 // Returns true if the given function needs dynamic invocation forwarder:
 // that is if any of the arguments require checking on the dynamic
 // call-site: if function has no parameters or has only covariant parameters
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 7129b5f..28e92be 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -20,7 +20,7 @@
 
 // Both version numbers are inclusive.
 static const uint32_t kMinSupportedKernelFormatVersion = 18;
-static const uint32_t kMaxSupportedKernelFormatVersion = 20;
+static const uint32_t kMaxSupportedKernelFormatVersion = 21;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \
@@ -62,6 +62,9 @@
   V(LogicalExpression, 34)                                                     \
   V(ConditionalExpression, 35)                                                 \
   V(StringConcatenation, 36)                                                   \
+  V(ListConcatenation, 111)                                                    \
+  V(SetConcatenation, 112)                                                     \
+  V(MapConcatenation, 113)                                                     \
   V(IsExpression, 37)                                                          \
   V(AsExpression, 38)                                                          \
   V(StringLiteral, 39)                                                         \
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index d962d85..fa5549e 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -676,6 +676,14 @@
       }
     }
 
+    // Set pending fields array to flag constant table loading.
+    ASSERT(I->object_store()->pending_unevaluated_const_fields() ==
+           GrowableObjectArray::null());
+    GrowableObjectArray& pending_unevaluated_const_fields =
+        GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
+    I->object_store()->set_pending_unevaluated_const_fields(
+        pending_unevaluated_const_fields);
+
     // All classes were successfully loaded, so let's:
     //     a) load & canonicalize the constant table
     const Array& constants = ReadConstantTable();
@@ -690,6 +698,22 @@
     kernel_program_info_.set_constants(constants);
     kernel_program_info_.set_constants_table(ExternalTypedData::Handle(Z));
 
+    //     d) evaluate pending field initializers
+    Error& error = Error::Handle(Z);
+    Field& field = Field::Handle(Z);
+    for (intptr_t i = 0, n = pending_unevaluated_const_fields.Length(); i < n;
+         i++) {
+      field ^= pending_unevaluated_const_fields.At(i);
+      error = field.EvaluateInitializer();
+      if (!error.IsNull()) {
+        H.ReportError(error, "postponed field initializer");
+      }
+    }
+    pending_unevaluated_const_fields = GrowableObjectArray::null();
+    I->object_store()->set_pending_unevaluated_const_fields(
+        pending_unevaluated_const_fields);
+
+    //     e) evaluate pragmas that were delayed
     EvaluateDelayedPragmas();
 
     NameIndex main = program_->main_method();
@@ -1067,6 +1091,9 @@
     // In the VM all const fields are implicitly final whereas in Kernel they
     // are not final because they are not explicitly declared that way.
     const bool is_final = field_helper.IsConst() || field_helper.IsFinal();
+    // Only instance fields could be covariant.
+    ASSERT(!field_helper.IsCovariant() &&
+           !field_helper.IsGenericCovariantImpl());
     const Field& field = Field::Handle(
         Z,
         Field::NewTopLevel(name, is_final, field_helper.IsConst(), script_class,
@@ -1197,7 +1224,7 @@
         target_library.url() == Symbols::DartMirrors().raw()) {
       H.ReportError("import of dart:mirrors with --enable-mirrors=false");
     }
-    if (!Api::ffiEnabled() &&
+    if (!Api::IsFfiEnabled() &&
         target_library.url() == Symbols::DartFfi().raw()) {
       H.ReportError("import of dart:ffi with --enable-ffi=false");
     }
@@ -1490,6 +1517,9 @@
                      field_helper.position_, field_helper.end_position_));
       field.set_kernel_offset(field_offset);
       field.set_has_pragma(has_pragma_annotation);
+      field.set_is_covariant(field_helper.IsCovariant());
+      field.set_is_generic_covariant_impl(
+          field_helper.IsGenericCovariantImpl());
       ReadInferredType(field, field_offset + library_kernel_offset_);
       CheckForInitializer(field);
       field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 864555d..86b63a5 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1223,6 +1223,7 @@
       intptr_t leftover_len = (leftover_size - TypedData::InstanceSize(0));
       ASSERT(TypedData::InstanceSize(leftover_len) == leftover_size);
       raw->StoreSmi(&(raw->ptr()->length_), Smi::New(leftover_len));
+      raw->ResetData();
     } else {
       // Update the leftover space as a basic object.
       ASSERT(leftover_size == Object::InstanceSize());
@@ -1641,9 +1642,11 @@
   pending_classes.Add(cls);
 
     CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_VIEW_CLASS);
+
     cls = Class::NewTypedDataViewClass(kByteDataViewCid);
     RegisterPrivateClass(cls, Symbols::_ByteDataView(), lib);
     pending_classes.Add(cls);
+
 #undef REGISTER_TYPED_DATA_VIEW_CLASS
 #define REGISTER_EXT_TYPED_DATA_CLASS(clazz)                                   \
   cls = Class::NewExternalTypedDataClass(kExternalTypedData##clazz##Cid);      \
@@ -2015,7 +2018,12 @@
 bool Object::IsReadOnly() const {
   if (FLAG_verify_handles && raw()->IsReadOnly()) {
     Heap* vm_isolate_heap = Dart::vm_isolate()->heap();
-    ASSERT(vm_isolate_heap->Contains(RawObject::ToAddr(raw())));
+    uword addr = RawObject::ToAddr(raw());
+    if (!vm_isolate_heap->Contains(addr)) {
+      ASSERT(FLAG_write_protect_code);
+      addr = RawObject::ToAddr(HeapPage::ToWritable(raw()));
+      ASSERT(vm_isolate_heap->Contains(addr));
+    }
   }
   return raw()->IsReadOnly();
 }
@@ -2072,8 +2080,12 @@
       Isolate* isolate = Isolate::Current();
       Heap* isolate_heap = isolate->heap();
       Heap* vm_isolate_heap = Dart::vm_isolate()->heap();
-      ASSERT(isolate_heap->Contains(RawObject::ToAddr(raw_)) ||
-             vm_isolate_heap->Contains(RawObject::ToAddr(raw_)));
+      uword addr = RawObject::ToAddr(raw_);
+      if (!isolate_heap->Contains(addr) && !vm_isolate_heap->Contains(addr)) {
+        ASSERT(FLAG_write_protect_code);
+        addr = RawObject::ToAddr(HeapPage::ToWritable(raw_));
+        ASSERT(isolate_heap->Contains(addr) || vm_isolate_heap->Contains(addr));
+      }
     }
   }
 #endif
@@ -2997,7 +3009,7 @@
   return false;
 }
 
-bool Function::IsDynamicInvocationForwaderName(const String& name) {
+bool Function::IsDynamicInvocationForwarderName(const String& name) {
   return name.StartsWith(Symbols::DynamicPrefix());
 }
 
@@ -3047,7 +3059,7 @@
 RawFunction* Function::GetDynamicInvocationForwarder(
     const String& mangled_name,
     bool allow_add /* = true */) const {
-  ASSERT(IsDynamicInvocationForwaderName(mangled_name));
+  ASSERT(IsDynamicInvocationForwarderName(mangled_name));
   const Class& owner = Class::Handle(Owner());
   Function& result = Function::Handle(owner.GetInvocationDispatcher(
       mangled_name, Array::null_array(),
@@ -3699,9 +3711,11 @@
 
 RawClass* Class::NewTypedDataViewClass(intptr_t class_id) {
   ASSERT(RawObject::IsTypedDataViewClassId(class_id));
-  Class& result = Class::Handle(New<Instance>(class_id));
-  result.set_instance_size(0);
-  result.set_next_field_offset(-kWordSize);
+  const intptr_t instance_size = TypedDataView::InstanceSize();
+  Class& result = Class::Handle(New<TypedDataView>(class_id));
+  result.set_instance_size(instance_size);
+  result.set_next_field_offset(TypedDataView::NextFieldOffset());
+  result.set_is_prefinalized();
   return result.raw();
 }
 
@@ -5857,7 +5871,8 @@
 RawField* Function::accessor_field() const {
   ASSERT(kind() == RawFunction::kImplicitGetter ||
          kind() == RawFunction::kImplicitSetter ||
-         kind() == RawFunction::kImplicitStaticFinalGetter);
+         kind() == RawFunction::kImplicitStaticFinalGetter ||
+         kind() == RawFunction::kDynamicInvocationForwarder);
   return Field::RawCast(raw_ptr()->data_);
 }
 
@@ -5975,6 +5990,20 @@
   }
 }
 
+void Function::SetFfiCSignature(const Function& sig) const {
+  ASSERT(IsFfiTrampoline());
+  const Object& obj = Object::Handle(raw_ptr()->data_);
+  ASSERT(!obj.IsNull());
+  FfiTrampolineData::Cast(obj).set_c_signature(sig);
+}
+
+RawFunction* Function::FfiCSignature() const {
+  ASSERT(IsFfiTrampoline());
+  const Object& obj = Object::Handle(raw_ptr()->data_);
+  ASSERT(!obj.IsNull());
+  return FfiTrampolineData::Cast(obj).c_signature();
+}
+
 RawType* Function::SignatureType() const {
   Type& type = Type::Handle(ExistingSignatureType());
   if (type.IsNull()) {
@@ -7334,46 +7363,17 @@
 
   // Change covariant parameter types to Object in the implicit closure.
   if (!is_static()) {
-    const Script& function_script = Script::Handle(zone, script());
-    kernel::TranslationHelper translation_helper(thread);
-    translation_helper.InitFromScript(function_script);
+    BitVector is_covariant(zone, NumParameters());
+    BitVector is_generic_covariant_impl(zone, NumParameters());
+    kernel::ReadParameterCovariance(*this, &is_covariant,
+                                    &is_generic_covariant_impl);
 
-    kernel::KernelReaderHelper kernel_reader_helper(
-        zone, &translation_helper, function_script,
-        ExternalTypedData::Handle(zone, KernelData()),
-        KernelDataProgramOffset());
-
-    kernel_reader_helper.SetOffset(kernel_offset());
-    kernel_reader_helper.ReadUntilFunctionNode();
-
-    kernel::FunctionNodeHelper fn_helper(&kernel_reader_helper);
-
-    // Check the positional parameters, including the optional positional ones.
-    fn_helper.ReadUntilExcluding(
-        kernel::FunctionNodeHelper::kPositionalParameters);
-    intptr_t num_pos_params = kernel_reader_helper.ReadListLength();
-    ASSERT(num_pos_params ==
-           num_fixed_params - 1 + (has_opt_pos_params ? num_opt_params : 0));
     const Type& object_type = Type::Handle(zone, Type::ObjectType());
-    for (intptr_t i = 0; i < num_pos_params; ++i) {
-      kernel::VariableDeclarationHelper var_helper(&kernel_reader_helper);
-      var_helper.ReadUntilExcluding(kernel::VariableDeclarationHelper::kEnd);
-      if (var_helper.IsCovariant() || var_helper.IsGenericCovariantImpl()) {
-        closure_function.SetParameterTypeAt(i + 1, object_type);
-      }
-    }
-    fn_helper.SetJustRead(kernel::FunctionNodeHelper::kPositionalParameters);
-
-    // Check the optional named parameters.
-    fn_helper.ReadUntilExcluding(kernel::FunctionNodeHelper::kNamedParameters);
-    intptr_t num_named_params = kernel_reader_helper.ReadListLength();
-    ASSERT(num_named_params == (has_opt_pos_params ? 0 : num_opt_params));
-    for (intptr_t i = 0; i < num_named_params; ++i) {
-      kernel::VariableDeclarationHelper var_helper(&kernel_reader_helper);
-      var_helper.ReadUntilExcluding(kernel::VariableDeclarationHelper::kEnd);
-      if (var_helper.IsCovariant() || var_helper.IsGenericCovariantImpl()) {
-        closure_function.SetParameterTypeAt(num_pos_params + 1 + i,
-                                            object_type);
+    for (intptr_t i = kClosure; i < num_params; ++i) {
+      const intptr_t original_param_index = has_receiver - kClosure + i;
+      if (is_covariant.Contains(original_param_index) ||
+          is_generic_covariant_impl.Contains(original_param_index)) {
+        closure_function.SetParameterTypeAt(i, object_type);
       }
     }
   }
@@ -7991,13 +7991,13 @@
       kind_str = " no-such-method-dispatcher";
       break;
     case RawFunction::kDynamicInvocationForwarder:
-      kind_str = " dynamic-invocation-forwader";
+      kind_str = " dynamic-invocation-forwarder";
       break;
     case RawFunction::kInvokeFieldDispatcher:
-      kind_str = "invoke-field-dispatcher";
+      kind_str = " invoke-field-dispatcher";
       break;
     case RawFunction::kIrregexpFunction:
-      kind_str = "irregexp-function";
+      kind_str = " irregexp-function";
       break;
     case RawFunction::kFfiTrampoline:
       kind_str = " ffi-trampoline-function";
@@ -8117,6 +8117,10 @@
   StorePointer(&raw_ptr()->signature_type_, value.raw());
 }
 
+void FfiTrampolineData::set_c_signature(const Function& value) const {
+  StorePointer(&raw_ptr()->c_signature_, value.raw());
+}
+
 RawFfiTrampolineData* FfiTrampolineData::New() {
   ASSERT(Object::ffi_trampoline_data_class() != Class::null());
   RawObject* raw =
@@ -8278,27 +8282,6 @@
   return PatchClass::Cast(obj).library_kernel_offset();
 }
 
-#if !defined(DART_PRECOMPILED_RUNTIME)
-void Field::GetCovarianceAttributes(bool* is_covariant,
-                                    bool* is_generic_covariant) const {
-  Thread* thread = Thread::Current();
-  Zone* zone = Thread::Current()->zone();
-  auto& script = Script::Handle(zone, Script());
-
-  kernel::TranslationHelper translation_helper(thread);
-  translation_helper.InitFromScript(script);
-
-  kernel::KernelReaderHelper kernel_reader_helper(
-      zone, &translation_helper, script,
-      ExternalTypedData::Handle(zone, KernelData()), KernelDataProgramOffset());
-  kernel_reader_helper.SetOffset(kernel_offset());
-  kernel::FieldHelper field_helper(&kernel_reader_helper);
-  field_helper.ReadUntilIncluding(kernel::FieldHelper::kFlags);
-  *is_covariant = field_helper.IsCovariant();
-  *is_generic_covariant = field_helper.IsGenericCovariantImpl();
-}
-#endif
-
 // Called at finalization time
 void Field::SetFieldType(const AbstractType& value) const {
   ASSERT(Thread::Current()->IsMutatorThread());
@@ -8339,7 +8322,7 @@
   result.set_token_pos(token_pos);
   result.set_end_token_pos(end_token_pos);
   result.set_has_initializer(false);
-  result.set_is_unboxing_candidate(true);
+  result.set_is_unboxing_candidate(!is_final);
   result.set_initializer_changed_after_initialization(false);
   result.set_kernel_offset(0);
   result.set_has_pragma(false);
@@ -13357,7 +13340,7 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   if (smi_op_target.IsNull() &&
-      Function::IsDynamicInvocationForwaderName(name)) {
+      Function::IsDynamicInvocationForwarderName(name)) {
     const String& demangled =
         String::Handle(Function::DemangleDynamicInvocationForwarderName(name));
     smi_op_target = Resolver::ResolveDynamicAnyArgs(zone, smi_class, demangled);
@@ -13423,7 +13406,7 @@
 bool ICData::ValidateInterceptor(const Function& target) const {
 #if !defined(DART_PRECOMPILED_RUNTIME)
   const String& name = String::Handle(target_name());
-  if (Function::IsDynamicInvocationForwaderName(name)) {
+  if (Function::IsDynamicInvocationForwarderName(name)) {
     return Function::DemangleDynamicInvocationForwarderName(name) ==
            target.name();
   }
@@ -14562,6 +14545,24 @@
                                object->raw());
     }
 
+    // Write protect instructions and, if supported by OS, use dual mapping
+    // for execution.
+    if (FLAG_write_protect_code) {
+      uword address = RawObject::ToAddr(instrs.raw());
+      // Check if a dual mapping exists.
+      instrs = Instructions::RawCast(HeapPage::ToExecutable(instrs.raw()));
+      uword exec_address = RawObject::ToAddr(instrs.raw());
+      if (exec_address != address) {
+        VirtualMemory::Protect(reinterpret_cast<void*>(address),
+                               instrs.raw()->HeapSize(),
+                               VirtualMemory::kReadOnly);
+        address = exec_address;
+      }
+      VirtualMemory::Protect(reinterpret_cast<void*>(address),
+                             instrs.raw()->HeapSize(),
+                             VirtualMemory::kReadExecute);
+    }
+
     // Hook up Code and Instructions objects.
     code.SetActiveInstructions(instrs);
     code.set_instructions(instrs);
@@ -14572,13 +14573,6 @@
       code.set_object_pool(object_pool->raw());
     }
 
-    if (FLAG_write_protect_code) {
-      uword address = RawObject::ToAddr(instrs.raw());
-      VirtualMemory::Protect(reinterpret_cast<void*>(address),
-                             instrs.raw()->HeapSize(),
-                             VirtualMemory::kReadExecute);
-    }
-
 #if defined(DART_PRECOMPILER)
     if (stats != nullptr) {
       stats->Finalize();
@@ -16391,13 +16385,11 @@
 
 intptr_t Instance::DataOffsetFor(intptr_t cid) {
   if (RawObject::IsExternalTypedDataClassId(cid) ||
-      RawObject::IsExternalStringClassId(cid)) {
-    // Elements start at offset 0 of the external data.
+      RawObject::IsExternalStringClassId(cid) ||
+      RawObject::IsTypedDataClassId(cid)) {
+    // Elements start at offset 0 of the external and typed data.
     return 0;
   }
-  if (RawObject::IsTypedDataClassId(cid)) {
-    return TypedData::data_offset();
-  }
   switch (cid) {
     case kArrayCid:
     case kImmutableArrayCid:
@@ -20863,9 +20855,11 @@
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.SetLength(len);
+    result.ResetData();
     if (len > 0) {
       memset(result.DataAddr(0), 0, lengthInBytes);
     }
+    ASSERT(result.Length() == len);
   }
   return result.raw();
 }
@@ -20907,6 +20901,37 @@
   return result.raw();
 }
 
+RawTypedDataView* TypedDataView::New(intptr_t class_id, Heap::Space space) {
+  auto& result = TypedDataView::Handle();
+  {
+    RawObject* raw =
+        Object::Allocate(class_id, TypedDataView::InstanceSize(), space);
+    NoSafepointScope no_safepoint;
+    result ^= raw;
+    result.clear_typed_data();
+    result.set_offset_in_bytes(0);
+    result.set_length(0);
+  }
+  return result.raw();
+}
+
+RawTypedDataView* TypedDataView::New(intptr_t class_id,
+                                     const Instance& typed_data,
+                                     intptr_t offset_in_bytes,
+                                     intptr_t length,
+                                     Heap::Space space) {
+  auto& result = TypedDataView::Handle(TypedDataView::New(class_id, space));
+  result.set_typed_data(typed_data);
+  result.set_offset_in_bytes(offset_in_bytes);
+  result.set_length(length);
+  return result.raw();
+}
+
+const char* TypedDataView::ToCString() const {
+  auto zone = Thread::Current()->zone();
+  return OS::SCreate(zone, "TypedDataView(cid: %" Pd ")", GetClassId());
+}
+
 const char* ExternalTypedData::ToCString() const {
   return "ExternalTypedData";
 }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index e19f357..044ecc5 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1256,7 +1256,7 @@
   // Allocate the raw TypedData classes.
   static RawClass* NewTypedDataClass(intptr_t class_id);
 
-  // Allocate the raw TypedDataView classes.
+  // Allocate the raw TypedDataView/ByteDataView classes.
   static RawClass* NewTypedDataViewClass(intptr_t class_id);
 
   // Allocate the raw ExternalTypedData classes.
@@ -1978,6 +1978,14 @@
   // Update the signature type (with a canonical version).
   void SetSignatureType(const Type& value) const;
 
+  // Set the "C signature" function for an FFI trampoline.
+  // Can only be used on FFI trampolines.
+  void SetFfiCSignature(const Function& sig) const;
+
+  // Retrieves the "C signature" function for an FFI trampoline.
+  // Can only be used on FFI trampolines.
+  RawFunction* FfiCSignature() const;
+
   // Return a new function with instantiated result and parameter types.
   RawFunction* InstantiateSignatureFrom(
       const TypeArguments& instantiator_type_arguments,
@@ -2185,7 +2193,7 @@
     return kind() == RawFunction::kInvokeFieldDispatcher;
   }
 
-  bool IsDynamicInvocationForwader() const {
+  bool IsDynamicInvocationForwarder() const {
     return kind() == RawFunction::kDynamicInvocationForwarder;
   }
 
@@ -2244,6 +2252,13 @@
   bool IsFactory() const {
     return (kind() == RawFunction::kConstructor) && is_static();
   }
+
+  // Whether this function can receive an invocation where the number and names
+  // of arguments have not been checked.
+  bool CanReceiveDynamicInvocation() const {
+    return IsClosureFunction() || IsFfiTrampoline();
+  }
+
   bool IsDynamicFunction(bool allow_abstract = false) const {
     if (is_static() || (!allow_abstract && is_abstract())) {
       return false;
@@ -2420,6 +2435,13 @@
   bool IsOptimizable() const;
   void SetIsOptimizable(bool value) const;
 
+  // Whether this function must be optimized immediately and cannot be compiled
+  // with the unoptimizing compiler. Such a function must be sure to not
+  // deoptimize, since we won't generate deoptimization info or register
+  // dependencies. It will be compiled into optimized code immediately when it's
+  // run.
+  bool ForceOptimize() const { return IsFfiTrampoline(); }
+
   bool CanBeInlined() const;
 
   MethodRecognizer::Kind recognized_kind() const {
@@ -2655,7 +2677,7 @@
   RawFunction* CreateMethodExtractor(const String& getter_name) const;
   RawFunction* GetMethodExtractor(const String& getter_name) const;
 
-  static bool IsDynamicInvocationForwaderName(const String& name);
+  static bool IsDynamicInvocationForwarderName(const String& name);
 
   static RawString* DemangleDynamicInvocationForwarderName(const String& name);
 
@@ -2989,6 +3011,9 @@
   RawType* signature_type() const { return raw_ptr()->signature_type_; }
   void set_signature_type(const Type& value) const;
 
+  RawFunction* c_signature() const { return raw_ptr()->c_signature_; }
+  void set_c_signature(const Function& value) const;
+
   static RawFfiTrampolineData* New();
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData, Object);
@@ -3055,6 +3080,21 @@
     set_kind_bits(HasPragmaBit::update(value, raw_ptr()->kind_bits_));
   }
 
+  bool is_covariant() const {
+    return CovariantBit::decode(raw_ptr()->kind_bits_);
+  }
+  void set_is_covariant(bool value) const {
+    set_kind_bits(CovariantBit::update(value, raw_ptr()->kind_bits_));
+  }
+
+  bool is_generic_covariant_impl() const {
+    return GenericCovariantImplBit::decode(raw_ptr()->kind_bits_);
+  }
+  void set_is_generic_covariant_impl(bool value) const {
+    set_kind_bits(
+        GenericCovariantImplBit::update(value, raw_ptr()->kind_bits_));
+  }
+
   intptr_t kernel_offset() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
     return 0;
@@ -3073,11 +3113,6 @@
 
   intptr_t KernelDataProgramOffset() const;
 
-#if !defined(DART_PRECOMPILED_RUNTIME)
-  void GetCovarianceAttributes(bool* is_covariant,
-                               bool* is_generic_covariant) const;
-#endif
-
   inline intptr_t Offset() const;
   // Called during class finalization.
   inline void SetOffset(intptr_t offset_in_bytes) const;
@@ -3301,6 +3336,7 @@
                             const Object& owner,
                             TokenPosition token_pos,
                             TokenPosition end_token_pos);
+  friend class Interpreter;              // Access to bit field.
   friend class StoreInstanceFieldInstr;  // Generated code access to bit field.
 
   enum {
@@ -3313,6 +3349,8 @@
     kDoubleInitializedBit,
     kInitializerChangedAfterInitializatonBit,
     kHasPragmaBit,
+    kCovariantBit,
+    kGenericCovariantImplBit,
   };
   class ConstBit : public BitField<uint16_t, bool, kConstBit, 1> {};
   class StaticBit : public BitField<uint16_t, bool, kStaticBit, 1> {};
@@ -3330,6 +3368,9 @@
                         kInitializerChangedAfterInitializatonBit,
                         1> {};
   class HasPragmaBit : public BitField<uint16_t, bool, kHasPragmaBit, 1> {};
+  class CovariantBit : public BitField<uint16_t, bool, kCovariantBit, 1> {};
+  class GenericCovariantImplBit
+      : public BitField<uint16_t, bool, kGenericCovariantImplBit, 1> {};
 
   // Update guarded cid and guarded length for this field. Returns true, if
   // deoptimization of dependent code is required.
@@ -4651,6 +4692,7 @@
 
 class Code : public Object {
  public:
+  // When dual mapping, this returns the executable view.
   RawInstructions* active_instructions() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
     UNREACHABLE();
@@ -4660,6 +4702,7 @@
 #endif
   }
 
+  // When dual mapping, these return the executable view.
   RawInstructions* instructions() const { return raw_ptr()->instructions_; }
   static RawInstructions* InstructionsOf(const RawCode* code) {
     return code->ptr()->instructions_;
@@ -5140,6 +5183,7 @@
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Code, Object);
   friend class Class;
+  friend class CodeTestHelper;
   friend class SnapshotWriter;
   friend class StubCode;     // for set_object_pool
   friend class Precompiler;  // for set_object_pool
@@ -8177,13 +8221,9 @@
 
   static intptr_t length_offset() { return OFFSET_OF(RawTypedData, length_); }
 
-  static intptr_t data_offset() {
-    return OFFSET_OF_RETURNED_VALUE(RawTypedData, data);
-  }
+  static intptr_t data_offset() { return OFFSET_OF(RawTypedData, data_); }
 
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(RawTypedData) ==
-           OFFSET_OF_RETURNED_VALUE(RawTypedData, data));
     return 0;
   }
 
@@ -8275,6 +8315,13 @@
     StoreSmi(&raw_ptr()->length_, Smi::New(value));
   }
 
+  void SetData(uint8_t* data) const {
+    ASSERT(Isolate::Current()->heap()->Contains(reinterpret_cast<uword>(data)));
+    StoreNonPointer(&raw_ptr()->data_, data);
+  }
+
+  void ResetData() { raw()->ResetData(); }
+
  private:
   // Provides const access to non-pointer, non-aligned data within the object.
   // Such access does not need a write barrier, but it is *not* GC-safe, since
@@ -8419,49 +8466,55 @@
   friend class Class;
 };
 
-class TypedDataView : public AllStatic {
+class TypedDataView : public Instance {
  public:
-  static intptr_t ElementSizeInBytes(const Instance& view_obj) {
+  static RawTypedDataView* New(intptr_t class_id,
+                               Heap::Space space = Heap::kNew);
+  static RawTypedDataView* New(intptr_t class_id,
+                               const Instance& typed_data,
+                               intptr_t offset_in_bytes,
+                               intptr_t length,
+                               Heap::Space space = Heap::kNew);
+
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(RawTypedDataView));
+  }
+
+  static intptr_t ElementSizeInBytes(const TypedDataView& view_obj) {
     ASSERT(!view_obj.IsNull());
     intptr_t cid = view_obj.raw()->GetClassId();
     return ElementSizeInBytes(cid);
   }
 
-  static RawInstance* Data(const Instance& view_obj) {
-    ASSERT(!view_obj.IsNull());
-    return *reinterpret_cast<RawInstance* const*>(view_obj.raw_ptr() +
-                                                  kDataOffset);
+  static RawInstance* Data(const TypedDataView& view) {
+    return view.typed_data();
   }
 
-  static RawSmi* OffsetInBytes(const Instance& view_obj) {
-    ASSERT(!view_obj.IsNull());
-    return *reinterpret_cast<RawSmi* const*>(view_obj.raw_ptr() +
-                                             kOffsetInBytesOffset);
+  static RawSmi* OffsetInBytes(const TypedDataView& view) {
+    return view.offset_in_bytes();
   }
 
-  static RawSmi* Length(const Instance& view_obj) {
-    ASSERT(!view_obj.IsNull());
-    return *reinterpret_cast<RawSmi* const*>(view_obj.raw_ptr() +
-                                             kLengthOffset);
-  }
+  static RawSmi* Length(const TypedDataView& view) { return view.length(); }
 
-  static bool IsExternalTypedDataView(const Instance& view_obj) {
-    const Instance& data = Instance::Handle(Data(view_obj));
+  static bool IsExternalTypedDataView(const TypedDataView& view_obj) {
+    const auto& data = Instance::Handle(Data(view_obj));
     intptr_t cid = data.raw()->GetClassId();
     ASSERT(RawObject::IsTypedDataClassId(cid) ||
            RawObject::IsExternalTypedDataClassId(cid));
     return RawObject::IsExternalTypedDataClassId(cid);
   }
 
-  static intptr_t NumberOfFields() { return kLengthOffset; }
-
-  static intptr_t data_offset() { return kWordSize * kDataOffset; }
-
-  static intptr_t offset_in_bytes_offset() {
-    return kWordSize * kOffsetInBytesOffset;
+  static intptr_t data_offset() {
+    return OFFSET_OF(RawTypedDataView, typed_data_);
   }
 
-  static intptr_t length_offset() { return kWordSize * kLengthOffset; }
+  static intptr_t length_offset() {
+    return OFFSET_OF(RawTypedDataView, length_);
+  }
+
+  static intptr_t offset_in_bytes_offset() {
+    return OFFSET_OF(RawTypedDataView, offset_in_bytes_);
+  }
 
   static intptr_t ElementSizeInBytes(intptr_t class_id) {
     ASSERT(RawObject::IsTypedDataViewClassId(class_id));
@@ -8470,12 +8523,34 @@
                : TypedData::element_size(class_id - kTypedDataInt8ArrayViewCid);
   }
 
+  RawInstance* typed_data() const { return raw_ptr()->typed_data_; }
+
+  void set_typed_data(const Instance& typed_data) {
+    const classid_t cid = typed_data.GetClassId();
+    ASSERT(RawObject::IsTypedDataClassId(cid) ||
+           RawObject::IsExternalTypedDataClassId(cid));
+    StorePointer(&raw_ptr()->typed_data_, typed_data.raw());
+  }
+
+  void set_length(intptr_t value) {
+    StorePointer(&raw_ptr()->length_, Smi::New(value));
+  }
+
+  void set_offset_in_bytes(intptr_t value) {
+    StorePointer(&raw_ptr()->offset_in_bytes_, Smi::New(value));
+  }
+
+  RawSmi* offset_in_bytes() const { return raw_ptr()->offset_in_bytes_; }
+
+  RawSmi* length() const { return raw_ptr()->length_; }
+
  private:
-  enum {
-    kDataOffset = 1,
-    kOffsetInBytesOffset = 2,
-    kLengthOffset = 3,
-  };
+  void clear_typed_data() {
+    StorePointer(&raw_ptr()->typed_data_, Instance::RawCast(Object::null()));
+  }
+
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(TypedDataView, Instance);
+  friend class Class;
 };
 
 class ByteBuffer : public AllStatic {
@@ -9140,8 +9215,12 @@
     Isolate* isolate = Isolate::Current();
     Heap* isolate_heap = isolate->heap();
     Heap* vm_isolate_heap = Dart::vm_isolate()->heap();
-    ASSERT(isolate_heap->Contains(RawObject::ToAddr(raw_)) ||
-           vm_isolate_heap->Contains(RawObject::ToAddr(raw_)));
+    uword addr = RawObject::ToAddr(raw_);
+    if (!isolate_heap->Contains(addr) && !vm_isolate_heap->Contains(addr)) {
+      ASSERT(FLAG_write_protect_code);
+      addr = RawObject::ToAddr(HeapPage::ToWritable(raw_));
+      ASSERT(isolate_heap->Contains(addr) || vm_isolate_heap->Contains(addr));
+    }
   }
 #endif
 }
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index 5a5e740..3e52f53 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -44,7 +44,12 @@
         if (!include_vm_objects_ && !IsUserClass((*current)->GetClassId())) {
           continue;
         }
-        (*current)->SetGraphMarked();
+        if (FLAG_write_protect_code && (*current)->IsInstructions()) {
+          // A non-writable alias mapping may exist for instruction pages.
+          HeapPage::ToWritable(*current)->SetGraphMarked();
+        } else {
+          (*current)->SetGraphMarked();
+        }
         Node node;
         node.ptr = current;
         node.obj = *current;
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 1562714..8157ccf 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -1389,6 +1389,10 @@
   }
 }
 
+void TypedDataView::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  Instance::PrintJSONImpl(stream, ref);
+}
+
 void ExternalTypedData::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
   PrintSharedInstanceJSON(&jsobj, ref);
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 3b9a10b..d3277a4 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -105,6 +105,7 @@
   RW(Array, libraries_map)                                                     \
   RW(GrowableObjectArray, closure_functions)                                   \
   RW(GrowableObjectArray, pending_classes)                                     \
+  RW(GrowableObjectArray, pending_unevaluated_const_fields)                    \
   R_(GrowableObjectArray, pending_deferred_loads)                              \
   R_(GrowableObjectArray, resume_capabilities)                                 \
   R_(GrowableObjectArray, exit_listeners)                                      \
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index c0d9526..4664ee7 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -23,6 +23,7 @@
 
 namespace dart {
 
+DECLARE_FLAG(bool, dual_map_code);
 DECLARE_FLAG(bool, write_protect_code);
 
 static RawClass* CreateDummyClass(const String& class_name,
@@ -2507,8 +2508,56 @@
   if (!FLAG_write_protect_code) {
     // Since this test is expected to crash, crash if write protection of code
     // is switched off.
-    // TODO(regis, fschneider): Should this be FATAL() instead?
-    OS::DebugBreak();
+    FATAL("Test requires --write-protect-code; skip by forcing expected crash");
+  }
+  MallocHooks::set_stack_trace_collection_enabled(
+      stack_trace_collection_enabled);
+}
+
+class CodeTestHelper {
+ public:
+  static void SetInstructions(const Code& code,
+                              const Instructions& instructions) {
+    code.SetActiveInstructions(instructions);
+    code.set_instructions(instructions);
+  }
+};
+
+// Test for executability of generated instructions. The test crashes with a
+// segmentation fault when executing the writeable view.
+ISOLATE_UNIT_TEST_CASE(CodeExecutability) {
+  bool stack_trace_collection_enabled =
+      MallocHooks::stack_trace_collection_enabled();
+  MallocHooks::set_stack_trace_collection_enabled(false);
+  extern void GenerateIncrement(Assembler * assembler);
+  ObjectPoolBuilder object_pool_builder;
+  Assembler _assembler_(&object_pool_builder);
+  GenerateIncrement(&_assembler_);
+  const Function& function = Function::Handle(CreateFunction("Test_Code"));
+  Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
+      function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
+  function.AttachCode(code);
+  Instructions& instructions = Instructions::Handle(code.instructions());
+  uword payload_start = instructions.PayloadStart();
+  EXPECT_EQ(instructions.raw(), Instructions::FromPayloadStart(payload_start));
+  // Execute the executable view of the instructions (default).
+  Object& result =
+      Object::Handle(DartEntry::InvokeFunction(function, Array::empty_array()));
+  EXPECT_EQ(1, Smi::Cast(result).Value());
+  // Switch to the writeable but non-executable view of the instructions.
+  instructions ^= HeapPage::ToWritable(instructions.raw());
+  payload_start = instructions.PayloadStart();
+  EXPECT_EQ(instructions.raw(), Instructions::FromPayloadStart(payload_start));
+  // Hook up Code and Instructions objects.
+  CodeTestHelper::SetInstructions(code, instructions);
+  function.AttachCode(code);
+  // Try executing the generated code, expected to crash.
+  result = DartEntry::InvokeFunction(function, Array::empty_array());
+  EXPECT_EQ(1, Smi::Cast(result).Value());
+  if (!FLAG_dual_map_code) {
+    // Since this test is expected to crash, crash if dual mapping of code
+    // is switched off.
+    FATAL("Test requires --dual-map-code; skip by forcing expected crash");
   }
   MallocHooks::set_stack_trace_collection_enabled(
       stack_trace_collection_enabled);
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index 1079bdb..20db94d 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -558,9 +558,7 @@
   }
 }
 
-// TODO(regis, iposva): When this function is no longer called from the
-// CodeImmutability test in object_test.cc, it will be called only from the
-// simulator, which means that only the Intel implementation is needed.
+// TODO(regis): Function called only from the simulator.
 void OS::DebugBreak() {
   __builtin_trap();
 }
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index b4b4135..17a4a79 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -78,7 +78,8 @@
 
   const bool load_optional_arguments = function.HasOptionalParameters();
 
-  const bool check_arguments = function_.IsClosureFunction();
+  const bool check_arguments =
+      function_.IsClosureFunction() || function.IsFfiTrampoline();
 
   const bool need_argument_descriptor =
       load_optional_arguments || check_arguments || reify_generic_argument;
@@ -216,7 +217,7 @@
 
   raw_parameters_ = new (Z) ZoneGrowableArray<LocalVariable*>(Z, num_params);
   for (intptr_t param = 0; param < num_params; ++param) {
-    LocalVariable* variable = scope->VariableAt(param);
+    LocalVariable* variable = ParameterVariable(param);
     LocalVariable* raw_parameter = variable;
     if (variable->is_captured()) {
       String& tmp = String::ZoneHandle(Z);
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index bc7b0d2..25dc2b6 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -103,6 +103,17 @@
   bool has_arg_desc_var() const { return arg_desc_var_ != NULL; }
   LocalVariable* arg_desc_var() const { return arg_desc_var_; }
 
+  LocalVariable* receiver_var() const {
+    ASSERT(receiver_var_ != nullptr);
+    return receiver_var_;
+  }
+  void set_receiver_var(LocalVariable* value) {
+    ASSERT(receiver_var_ == nullptr);
+    ASSERT(value != nullptr);
+    receiver_var_ = value;
+  }
+  bool has_receiver_var() const { return receiver_var_ != nullptr; }
+
   LocalVariable* expression_temp_var() const {
     ASSERT(has_expression_temp_var());
     return expression_temp_var_;
@@ -198,6 +209,12 @@
     return raw_parameters_->At(i);
   }
 
+  LocalVariable* ParameterVariable(intptr_t i) const {
+    ASSERT((i >= 0) && (i < function_.NumParameters()));
+    ASSERT(node_sequence() != nullptr && node_sequence()->scope() != nullptr);
+    return node_sequence()->scope()->VariableAt(i);
+  }
+
   void SetDefaultFunctionTypeArguments(const TypeArguments& value) {
     default_function_type_arguments_ = value.raw();
   }
@@ -216,6 +233,7 @@
   LocalVariable* parent_type_arguments_;
   LocalVariable* current_context_var_;
   LocalVariable* arg_desc_var_;
+  LocalVariable* receiver_var_ = nullptr;
   LocalVariable* expression_temp_var_;
   LocalVariable* entry_points_temp_var_;
   LocalVariable* finally_return_temp_var_;
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 7735f4d..1e933eb 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -269,22 +269,25 @@
 #undef RAW_VISITPOINTERS
 #define RAW_VISITPOINTERS(clazz) case kExternalTypedData##clazz##Cid:
     CLASS_LIST_TYPED_DATA(RAW_VISITPOINTERS) {
-      RawExternalTypedData* raw_obj =
-          reinterpret_cast<RawExternalTypedData*>(this);
+      auto raw_obj = reinterpret_cast<RawExternalTypedData*>(this);
       size = RawExternalTypedData::VisitExternalTypedDataPointers(raw_obj,
                                                                   visitor);
       break;
     }
 #undef RAW_VISITPOINTERS
-#define RAW_VISITPOINTERS(clazz) case kTypedData##clazz##ViewCid:
-    CLASS_LIST_TYPED_DATA(RAW_VISITPOINTERS)
     case kByteDataViewCid:
+#define RAW_VISITPOINTERS(clazz) case kTypedData##clazz##ViewCid:
+      CLASS_LIST_TYPED_DATA(RAW_VISITPOINTERS) {
+        auto raw_obj = reinterpret_cast<RawTypedDataView*>(this);
+        size = RawTypedDataView::VisitTypedDataViewPointers(raw_obj, visitor);
+        break;
+      }
+#undef RAW_VISITPOINTERS
     case kByteBufferCid: {
       RawInstance* raw_obj = reinterpret_cast<RawInstance*>(this);
       size = RawInstance::VisitInstancePointers(raw_obj, visitor);
       break;
     }
-#undef RAW_VISITPOINTERS
     case kFfiPointerCid: {
       RawPointer* raw_obj = reinterpret_cast<RawPointer*>(this);
       size = RawPointer::VisitPointerPointers(raw_obj, visitor);
@@ -427,6 +430,7 @@
 COMPRESSED_VISITOR(GrowableObjectArray)
 COMPRESSED_VISITOR(LinkedHashMap)
 COMPRESSED_VISITOR(ExternalTypedData)
+REGULAR_VISITOR(TypedDataView)
 REGULAR_VISITOR(ReceivePort)
 REGULAR_VISITOR(StackTrace)
 REGULAR_VISITOR(RegExp)
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 5cd9448..79372ea 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -712,6 +712,7 @@
   friend class RawInstance;
   friend class RawString;
   friend class RawTypedData;
+  friend class RawTypedDataView;
   friend class Scavenger;
   friend class ScavengerVisitor;
   friend class SizeExcludingClassVisitor;  // GetClassId
@@ -1036,7 +1037,8 @@
 
   VISIT_FROM(RawObject*, signature_type_);
   RawType* signature_type_;
-  VISIT_TO(RawObject*, signature_type_);
+  RawFunction* c_signature_;
+  VISIT_TO(RawObject*, c_signature_);
 };
 
 class RawField : public RawObject {
@@ -2080,6 +2082,25 @@
   friend class String;
 };
 
+// All _*ArrayView/_ByteDataView classes share the same layout.
+class RawTypedDataView : public RawInstance {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(TypedDataView);
+
+ protected:
+  VISIT_FROM(RawObject*, typed_data_)
+  RawInstance* typed_data_;
+  RawSmi* offset_in_bytes_;
+  RawSmi* length_;
+  VISIT_TO(RawObject*, length_)
+
+  friend class Api;
+  friend class Object;
+  friend class ObjectPoolDeserializationCluster;
+  friend class ObjectPoolSerializationCluster;
+  friend class RawObjectPool;
+  friend class SnapshotReader;
+};
+
 class RawExternalOneByteString : public RawString {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalOneByteString);
 
@@ -2227,13 +2248,31 @@
 class RawTypedData : public RawInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(TypedData);
 
+ public:
+  // Reset data_ pointer to internal data.
+  void ResetData() { ptr()->data_ = ptr()->internal_data(); }
+
  protected:
   VISIT_FROM(RawCompressed, length_)
   RawSmi* length_;
   VISIT_TO_LENGTH(RawCompressed, &ptr()->length_)
+
+  uint8_t* data_;
   // Variable length data follows here.
-  uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
-  const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
+
+  uint8_t* internal_data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
+  const uint8_t* internal_data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
+
+  uint8_t* data() {
+    // TODO(alexmarkov): revise after merging with ExternalTypedData
+    ASSERT(data_ == internal_data());
+    return data_;
+  }
+  const uint8_t* data() const {
+    // TODO(alexmarkov): revise after merging with ExternalTypedData
+    ASSERT(data_ == internal_data());
+    return data_;
+  }
 
   friend class Api;
   friend class Instance;
@@ -2620,7 +2659,7 @@
 // is defined by the VM but are used in the VM code by computing the
 // implicit field offsets of the various fields in the dart object.
 inline bool RawObject::IsImplicitFieldClassId(intptr_t index) {
-  return (IsTypedDataViewClassId(index) || index == kByteBufferCid);
+  return index == kByteBufferCid;
 }
 
 inline intptr_t RawObject::NumberOfTypedDataClasses() {
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index f743ea6..58ec79e 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1964,6 +1964,45 @@
       IsolateMessageTypedDataFinalizer);
 }
 
+void RawTypedDataView::WriteTo(SnapshotWriter* writer,
+                               intptr_t object_id,
+                               Snapshot::Kind kind,
+                               bool as_reference) {
+  // Write out the serialization header value for this object.
+  writer->WriteInlinedObjectHeader(object_id);
+
+  // Write out the class and tags information.
+  writer->WriteIndexedObject(GetClassId());
+  writer->WriteTags(writer->GetObjectTags(this));
+
+  // Write members.
+  writer->Write<RawObject*>(ptr()->offset_in_bytes_);
+  writer->Write<RawObject*>(ptr()->length_);
+  writer->WriteObjectImpl(ptr()->typed_data_, as_reference);
+}
+
+RawTypedDataView* TypedDataView::ReadFrom(SnapshotReader* reader,
+                                          intptr_t object_id,
+                                          intptr_t tags,
+                                          Snapshot::Kind kind,
+                                          bool as_reference) {
+  auto& typed_data = *reader->InstanceHandle();
+  const classid_t cid = RawObject::ClassIdTag::decode(tags);
+
+  auto& view = *reader->TypedDataViewHandle();
+  view = TypedDataView::New(cid);
+  reader->AddBackRef(object_id, &view, kIsDeserialized);
+
+  const intptr_t offset_in_bytes = reader->ReadSmiValue();
+  const intptr_t length = reader->ReadSmiValue();
+  typed_data ^= reader->ReadObjectImpl(as_reference);
+  view.set_offset_in_bytes(offset_in_bytes);
+  view.set_length(length);
+  view.set_typed_data(typed_data);
+
+  return view.raw();
+}
+
 RawPointer* Pointer::ReadFrom(SnapshotReader* reader,
                               intptr_t object_id,
                               intptr_t tags,
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index 9e7e8bb..c2b4fe7 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -317,6 +317,8 @@
 
   inline bool ignore_case() { return ignore_case_; }
   inline bool one_byte() const { return is_one_byte_; }
+  bool read_backward() { return read_backward_; }
+  void set_read_backward(bool value) { read_backward_ = value; }
   FrequencyCollator* frequency_collator() { return &frequency_collator_; }
 
   intptr_t current_expansion_factor() { return current_expansion_factor_; }
@@ -337,6 +339,7 @@
   bool ignore_case_;
   bool is_one_byte_;
   bool reg_exp_too_big_;
+  bool read_backward_;
   intptr_t current_expansion_factor_;
   FrequencyCollator frequency_collator_;
   Zone* zone_;
@@ -368,6 +371,7 @@
       ignore_case_(ignore_case),
       is_one_byte_(is_one_byte),
       reg_exp_too_big_(false),
+      read_backward_(false),
       current_expansion_factor_(1),
       zone_(Thread::Current()->zone()) {
   accept_ = new (Z) EndNode(EndNode::ACCEPT, Z);
@@ -520,7 +524,8 @@
     intptr_t value = 0;
     bool absolute = false;
     bool clear = false;
-    intptr_t store_position = -1;
+    static const intptr_t kNoStore = kMinInt32;
+    intptr_t store_position = kNoStore;
     // This is a little tricky because we are scanning the actions in reverse
     // historical order (newest first).
     for (DeferredAction* action = actions_; action != NULL;
@@ -540,7 +545,7 @@
             // can set undo_action to ACTION_IGNORE if we know there is no
             // value to restore.
             undo_action = ACTION_RESTORE;
-            ASSERT(store_position == -1);
+            ASSERT(store_position == kNoStore);
             ASSERT(!clear);
             break;
           }
@@ -548,14 +553,14 @@
             if (!absolute) {
               value++;
             }
-            ASSERT(store_position == -1);
+            ASSERT(store_position == kNoStore);
             ASSERT(!clear);
             undo_action = ACTION_RESTORE;
             break;
           case ActionNode::STORE_POSITION: {
             Trace::DeferredCapture* pc =
                 static_cast<Trace::DeferredCapture*>(action);
-            if (!clear && store_position == -1) {
+            if (!clear && store_position == kNoStore) {
               store_position = pc->cp_offset();
             }
 
@@ -579,7 +584,7 @@
             // Since we're scanning in reverse order, if we've already
             // set the position we have to ignore historically earlier
             // clearing operations.
-            if (store_position == -1) {
+            if (store_position == kNoStore) {
               clear = true;
             }
             undo_action = ACTION_RESTORE;
@@ -602,7 +607,7 @@
     }
     // Perform the chronologically last action (or accumulated increment)
     // for the register.
-    if (store_position != -1) {
+    if (store_position != kNoStore) {
       assembler->WriteCurrentPositionToRegister(reg, store_position);
     } else if (clear) {
       assembler->ClearRegisters(reg, reg);
@@ -1494,6 +1499,7 @@
 intptr_t BackReferenceNode::EatsAtLeast(intptr_t still_to_find,
                                         intptr_t budget,
                                         bool not_at_start) {
+  if (read_backward()) return 0;
   if (budget <= 0) return 0;
   return on_success()->EatsAtLeast(still_to_find, budget - 1, not_at_start);
 }
@@ -1501,6 +1507,7 @@
 intptr_t TextNode::EatsAtLeast(intptr_t still_to_find,
                                intptr_t budget,
                                bool not_at_start) {
+  if (read_backward()) return 0;
   intptr_t answer = Length();
   if (answer >= still_to_find) return answer;
   if (budget <= 0) return answer;
@@ -1509,9 +1516,9 @@
          on_success()->EatsAtLeast(still_to_find - answer, budget - 1, true);
 }
 
-intptr_t NegativeLookaheadChoiceNode::EatsAtLeast(intptr_t still_to_find,
-                                                  intptr_t budget,
-                                                  bool not_at_start) {
+intptr_t NegativeLookaroundChoiceNode::EatsAtLeast(intptr_t still_to_find,
+                                                   intptr_t budget,
+                                                   bool not_at_start) {
   if (budget <= 0) return 0;
   // Alternative 0 is the negative lookahead, alternative 1 is what comes
   // afterwards.
@@ -1519,7 +1526,7 @@
   return node->EatsAtLeast(still_to_find, budget - 1, not_at_start);
 }
 
-void NegativeLookaheadChoiceNode::GetQuickCheckDetails(
+void NegativeLookaroundChoiceNode::GetQuickCheckDetails(
     QuickCheckDetails* details,
     RegExpCompiler* compiler,
     intptr_t filled_in,
@@ -1682,6 +1689,9 @@
   ASSERT(details->characters() == 1 ||
          (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__));
 #endif
+  // Do not collect any quick check details if the text node reads backward,
+  // since it reads in the opposite direction than we use for quick checks.
+  if (read_backward()) return;
   ASSERT(characters_filled_in < details->characters());
   intptr_t characters = details->characters();
   intptr_t char_mask;
@@ -1838,8 +1848,9 @@
 }
 
 void QuickCheckDetails::Advance(intptr_t by, bool one_byte) {
-  ASSERT(by >= 0);
-  if (by >= characters_) {
+  if (by >= characters_ || by < 0) {
+    // check that by < 0 => characters_ == 0
+    ASSERT(by >= 0 || characters_ == 0);
     Clear();
     return;
   }
@@ -2060,8 +2071,8 @@
   return this;
 }
 
-RegExpNode* NegativeLookaheadChoiceNode::FilterOneByte(intptr_t depth,
-                                                       bool ignore_case) {
+RegExpNode* NegativeLookaroundChoiceNode::FilterOneByte(intptr_t depth,
+                                                        bool ignore_case) {
   if (info()->replacement_calculated) return replacement();
   if (depth < 0) return this;
   if (info()->visited) return this;
@@ -2294,9 +2305,9 @@
         return;
       }
       if (trace->at_start() == Trace::UNKNOWN) {
-        assembler->CheckNotAtStart(trace->backtrack());
+        assembler->CheckNotAtStart(trace->cp_offset(), trace->backtrack());
         Trace at_start_trace = *trace;
-        at_start_trace.set_at_start(true);
+        at_start_trace.set_at_start(Trace::TRUE_VALUE);
         on_success()->Emit(compiler, &at_start_trace);
         return;
       }
@@ -2365,9 +2376,10 @@
   BlockLabel* backtrack = trace->backtrack();
   QuickCheckDetails* quick_check = trace->quick_check_performed();
   intptr_t element_count = elms_->length();
+  intptr_t backward_offset = read_backward() ? -Length() : 0;
   for (intptr_t i = preloaded ? 0 : element_count - 1; i >= 0; i--) {
     TextElement elm = elms_->At(i);
-    intptr_t cp_offset = trace->cp_offset() + elm.cp_offset();
+    intptr_t cp_offset = trace->cp_offset() + elm.cp_offset() + backward_offset;
     if (elm.text_type() == TextElement::ATOM) {
       ZoneGrowableArray<uint16_t>* quarks = elm.atom()->data();
       for (intptr_t j = preloaded ? 0 : quarks->length() - 1; j >= 0; j--) {
@@ -2395,9 +2407,11 @@
             break;
         }
         if (emit_function != NULL) {
-          bool bound_checked = emit_function(
-              Z, compiler, quarks->At(j), backtrack, cp_offset + j,
-              *checked_up_to < cp_offset + j, preloaded);
+          const bool bounds_check =
+              *checked_up_to < (cp_offset + j) || read_backward();
+          bool bound_checked =
+              emit_function(Z, compiler, quarks->At(j), backtrack,
+                            cp_offset + j, bounds_check, preloaded);
           if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to);
         }
       }
@@ -2407,8 +2421,9 @@
         if (first_element_checked && i == 0) continue;
         if (DeterminedAlready(quick_check, elm.cp_offset())) continue;
         RegExpCharacterClass* cc = elm.char_class();
+        bool bounds_check = *checked_up_to < cp_offset || read_backward();
         EmitCharClass(assembler, cc, one_byte, backtrack, cp_offset,
-                      *checked_up_to < cp_offset, preloaded, Z);
+                      bounds_check, preloaded, Z);
         UpdateBoundsCheck(cp_offset, checked_up_to);
       }
     }
@@ -2475,8 +2490,11 @@
   }
 
   Trace successor_trace(*trace);
-  successor_trace.set_at_start(false);
-  successor_trace.AdvanceCurrentPositionInTrace(Length(), compiler);
+  // If we advance backward, we may end up at the start.
+  successor_trace.AdvanceCurrentPositionInTrace(
+      read_backward() ? -Length() : Length(), compiler);
+  successor_trace.set_at_start(read_backward() ? Trace::UNKNOWN
+                                               : Trace::FALSE_VALUE);
   RecursionCheck rc(compiler);
   on_success()->Emit(compiler, &successor_trace);
 }
@@ -2487,7 +2505,6 @@
 
 void Trace::AdvanceCurrentPositionInTrace(intptr_t by,
                                           RegExpCompiler* compiler) {
-  ASSERT(by > 0);
   // We don't have an instruction for shifting the current character register
   // down or for using a shifted value for anything so lets just forget that
   // we preloaded any characters into it.
@@ -2530,6 +2547,7 @@
 
 RegExpNode* TextNode::GetSuccessorOfOmnivorousTextNode(
     RegExpCompiler* compiler) {
+  if (read_backward()) return nullptr;
   if (elms_->length() != 1) return NULL;
   TextElement elm = elms_->At(0);
   if (elm.text_type() != TextElement::CHAR_CLASS) return NULL;
@@ -2574,7 +2592,7 @@
     SeqRegExpNode* seq_node = static_cast<SeqRegExpNode*>(node);
     node = seq_node->on_success();
   }
-  return length;
+  return read_backward() ? -length : length;
 }
 
 void LoopChoiceNode::AddLoopAlternative(GuardedAlternative alt) {
@@ -3002,7 +3020,7 @@
 
 GreedyLoopState::GreedyLoopState(bool not_at_start) {
   counter_backtrack_trace_.set_backtrack(&label_);
-  if (not_at_start) counter_backtrack_trace_.set_at_start(false);
+  if (not_at_start) counter_backtrack_trace_.set_at_start(Trace::FALSE_VALUE);
 }
 
 void ChoiceNode::AssertGuardsMentionRegisters(Trace* trace) {
@@ -3115,7 +3133,7 @@
   macro_assembler->PushCurrentPosition();
   BlockLabel greedy_match_failed;
   Trace greedy_match_trace;
-  if (not_at_start()) greedy_match_trace.set_at_start(false);
+  if (not_at_start()) greedy_match_trace.set_at_start(Trace::FALSE_VALUE);
   greedy_match_trace.set_backtrack(&greedy_match_failed);
   BlockLabel loop_label;
   macro_assembler->BindBlock(&loop_label);
@@ -3446,10 +3464,15 @@
 
   ASSERT(start_reg_ + 1 == end_reg_);
   if (compiler->ignore_case()) {
-    assembler->CheckNotBackReferenceIgnoreCase(start_reg_, trace->backtrack());
+    assembler->CheckNotBackReferenceIgnoreCase(start_reg_, read_backward(),
+                                               trace->backtrack());
   } else {
-    assembler->CheckNotBackReference(start_reg_, trace->backtrack());
+    assembler->CheckNotBackReference(start_reg_, read_backward(),
+                                     trace->backtrack());
   }
+  // We are going to advance backward, so we may end up at the start.
+  if (read_backward()) trace->set_at_start(Trace::UNKNOWN);
+
   on_success()->Emit(compiler, trace);
 }
 
@@ -3694,7 +3717,7 @@
   ZoneGrowableArray<TextElement>* elms =
       new (OZ) ZoneGrowableArray<TextElement>(1);
   elms->Add(TextElement::Atom(this));
-  return new (OZ) TextNode(elms, on_success);
+  return new (OZ) TextNode(elms, compiler->read_backward(), on_success);
 }
 
 RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler,
@@ -3704,7 +3727,7 @@
   for (intptr_t i = 0; i < elements()->length(); i++) {
     elms->Add(elements()->At(i));
   }
-  return new (OZ) TextNode(elms, on_success);
+  return new (OZ) TextNode(elms, compiler->read_backward(), on_success);
 }
 
 static bool CompareInverseRanges(ZoneGrowableArray<CharacterRange>* ranges,
@@ -3795,7 +3818,7 @@
 
 RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler,
                                          RegExpNode* on_success) {
-  return new (OZ) TextNode(this, on_success);
+  return new (OZ) TextNode(this, compiler->read_backward(), on_success);
 }
 
 RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler,
@@ -3931,7 +3954,9 @@
                 GuardedAlternative(body->ToNode(compiler, answer)));
           }
           answer = alternation;
-          if (not_at_start) alternation->set_not_at_start();
+          if (not_at_start && !compiler->read_backward()) {
+            alternation->set_not_at_start();
+          }
         }
         return answer;
       }
@@ -3942,9 +3967,9 @@
   bool needs_counter = has_min || has_max;
   intptr_t reg_ctr = needs_counter ? compiler->AllocateRegister()
                                    : RegExpCompiler::kNoRegister;
-  LoopChoiceNode* center =
-      new (zone) LoopChoiceNode(body->min_match() == 0, zone);
-  if (not_at_start) center->set_not_at_start();
+  LoopChoiceNode* center = new (zone)
+      LoopChoiceNode(body->min_match() == 0, compiler->read_backward(), zone);
+  if (not_at_start && !compiler->read_backward()) center->set_not_at_start();
   RegExpNode* loop_return =
       needs_counter ? static_cast<RegExpNode*>(
                           ActionNode::IncrementRegister(reg_ctr, center))
@@ -4015,12 +4040,13 @@
           new ZoneGrowableArray<CharacterRange>(3);
       CharacterRange::AddClassEscape('n', newline_ranges);
       RegExpCharacterClass* newline_atom = new RegExpCharacterClass('n');
-      TextNode* newline_matcher = new TextNode(
-          newline_atom, ActionNode::PositiveSubmatchSuccess(
-                            stack_pointer_register, position_register,
-                            0,   // No captures inside.
-                            -1,  // Ignored if no captures.
-                            on_success));
+      TextNode* newline_matcher =
+          new TextNode(newline_atom, /*read_backwards=*/false,
+                       ActionNode::PositiveSubmatchSuccess(
+                           stack_pointer_register, position_register,
+                           0,   // No captures inside.
+                           -1,  // Ignored if no captures.
+                           on_success));
       // Create an end-of-input matcher.
       RegExpNode* end_of_line = ActionNode::BeginSubmatch(
           stack_pointer_register, position_register, newline_matcher);
@@ -4039,9 +4065,9 @@
 
 RegExpNode* RegExpBackReference::ToNode(RegExpCompiler* compiler,
                                         RegExpNode* on_success) {
-  return new (OZ)
-      BackReferenceNode(RegExpCapture::StartRegister(index()),
-                        RegExpCapture::EndRegister(index()), on_success);
+  return new (OZ) BackReferenceNode(RegExpCapture::StartRegister(index()),
+                                    RegExpCapture::EndRegister(index()),
+                                    compiler->read_backward(), on_success);
 }
 
 RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler,
@@ -4049,8 +4075,47 @@
   return on_success;
 }
 
-RegExpNode* RegExpLookahead::ToNode(RegExpCompiler* compiler,
-                                    RegExpNode* on_success) {
+RegExpLookaround::Builder::Builder(bool is_positive,
+                                   RegExpNode* on_success,
+                                   intptr_t stack_pointer_register,
+                                   intptr_t position_register,
+                                   intptr_t capture_register_count,
+                                   intptr_t capture_register_start)
+    : is_positive_(is_positive),
+      on_success_(on_success),
+      stack_pointer_register_(stack_pointer_register),
+      position_register_(position_register) {
+  if (is_positive_) {
+    on_match_success_ = ActionNode::PositiveSubmatchSuccess(
+        stack_pointer_register, position_register, capture_register_count,
+        capture_register_start, on_success);
+  } else {
+    on_match_success_ = new (OZ) NegativeSubmatchSuccess(
+        stack_pointer_register, position_register, capture_register_count,
+        capture_register_start, OZ);
+  }
+}
+
+RegExpNode* RegExpLookaround::Builder::ForMatch(RegExpNode* match) {
+  if (is_positive_) {
+    return ActionNode::BeginSubmatch(stack_pointer_register_,
+                                     position_register_, match);
+  } else {
+    Zone* zone = on_success_->zone();
+    // We use a ChoiceNode to represent the negative lookaround. The first
+    // alternative is the negative match. On success, the end node backtracks.
+    // On failure, the second alternative is tried and leads to success.
+    // NegativeLookaroundChoiceNode is a special ChoiceNode that ignores the
+    // first exit when calculating quick checks.
+    ChoiceNode* choice_node = new (zone) NegativeLookaroundChoiceNode(
+        GuardedAlternative(match), GuardedAlternative(on_success_), zone);
+    return ActionNode::BeginSubmatch(stack_pointer_register_,
+                                     position_register_, choice_node);
+  }
+}
+
+RegExpNode* RegExpLookaround::ToNode(RegExpCompiler* compiler,
+                                     RegExpNode* on_success) {
   intptr_t stack_pointer_register = compiler->AllocateRegister();
   intptr_t position_register = compiler->AllocateRegister();
 
@@ -4060,36 +4125,15 @@
   intptr_t register_start =
       register_of_first_capture + capture_from_ * registers_per_capture;
 
-  RegExpNode* success;
-  if (is_positive()) {
-    RegExpNode* node = ActionNode::BeginSubmatch(
-        stack_pointer_register, position_register,
-        body()->ToNode(compiler,
-                       ActionNode::PositiveSubmatchSuccess(
-                           stack_pointer_register, position_register,
-                           register_count, register_start, on_success)));
-    return node;
-  } else {
-    // We use a ChoiceNode for a negative lookahead because it has most of
-    // the characteristics we need.  It has the body of the lookahead as its
-    // first alternative and the expression after the lookahead of the second
-    // alternative.  If the first alternative succeeds then the
-    // NegativeSubmatchSuccess will unwind the stack including everything the
-    // choice node set up and backtrack.  If the first alternative fails then
-    // the second alternative is tried, which is exactly the desired result
-    // for a negative lookahead.  The NegativeLookaheadChoiceNode is a special
-    // ChoiceNode that knows to ignore the first exit when calculating quick
-    // checks.
-
-    GuardedAlternative body_alt(
-        body()->ToNode(compiler, success = new (OZ) NegativeSubmatchSuccess(
-                                     stack_pointer_register, position_register,
-                                     register_count, register_start, OZ)));
-    ChoiceNode* choice_node = new (OZ) NegativeLookaheadChoiceNode(
-        body_alt, GuardedAlternative(on_success), OZ);
-    return ActionNode::BeginSubmatch(stack_pointer_register, position_register,
-                                     choice_node);
-  }
+  RegExpNode* result;
+  bool was_reading_backward = compiler->read_backward();
+  compiler->set_read_backward(type() == LOOKBEHIND);
+  Builder builder(is_positive(), on_success, stack_pointer_register,
+                  position_register, register_count, register_start);
+  RegExpNode* match = body_->ToNode(compiler, builder.on_match_success());
+  result = builder.ForMatch(match);
+  compiler->set_read_backward(was_reading_backward);
+  return result;
 }
 
 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler,
@@ -4101,8 +4145,14 @@
                                   intptr_t index,
                                   RegExpCompiler* compiler,
                                   RegExpNode* on_success) {
+  ASSERT(body != nullptr);
   intptr_t start_reg = RegExpCapture::StartRegister(index);
   intptr_t end_reg = RegExpCapture::EndRegister(index);
+  if (compiler->read_backward()) {
+    intptr_t tmp = end_reg;
+    end_reg = start_reg;
+    start_reg = tmp;
+  }
   RegExpNode* store_end = ActionNode::StorePosition(end_reg, true, on_success);
   RegExpNode* body_node = body->ToNode(compiler, store_end);
   return ActionNode::StorePosition(start_reg, true, body_node);
@@ -4112,8 +4162,14 @@
                                       RegExpNode* on_success) {
   ZoneGrowableArray<RegExpTree*>* children = nodes();
   RegExpNode* current = on_success;
-  for (intptr_t i = children->length() - 1; i >= 0; i--) {
-    current = children->At(i)->ToNode(compiler, current);
+  if (compiler->read_backward()) {
+    for (intptr_t i = 0; i < children->length(); i++) {
+      current = children->At(i)->ToNode(compiler, current);
+    }
+  } else {
+    for (intptr_t i = children->length() - 1; i >= 0; i--) {
+      current = children->At(i)->ToNode(compiler, current);
+    }
   }
   return current;
 }
@@ -4686,8 +4742,9 @@
       // at the start of input.
       ChoiceNode* first_step_node = new (zone) ChoiceNode(2, zone);
       first_step_node->AddAlternative(GuardedAlternative(captured_body));
-      first_step_node->AddAlternative(GuardedAlternative(new (zone) TextNode(
-          new (zone) RegExpCharacterClass('*'), loop_node)));
+      first_step_node->AddAlternative(GuardedAlternative(
+          new (zone) TextNode(new (zone) RegExpCharacterClass('*'),
+                              /*read_backwards=*/false, loop_node)));
       node = first_step_node;
     } else {
       node = loop_node;
@@ -4789,8 +4846,9 @@
       // at the start of input.
       ChoiceNode* first_step_node = new (zone) ChoiceNode(2, zone);
       first_step_node->AddAlternative(GuardedAlternative(captured_body));
-      first_step_node->AddAlternative(GuardedAlternative(new (zone) TextNode(
-          new (zone) RegExpCharacterClass('*'), loop_node)));
+      first_step_node->AddAlternative(GuardedAlternative(
+          new (zone) TextNode(new (zone) RegExpCharacterClass('*'),
+                              /*read_backwards=*/false, loop_node)));
       node = first_step_node;
     } else {
       node = loop_node;
diff --git a/runtime/vm/regexp.h b/runtime/vm/regexp.h
index b263166..3a477e9 100644
--- a/runtime/vm/regexp.h
+++ b/runtime/vm/regexp.h
@@ -121,7 +121,7 @@
   VISIT(Atom)                                                                  \
   VISIT(Quantifier)                                                            \
   VISIT(Capture)                                                               \
-  VISIT(Lookahead)                                                             \
+  VISIT(Lookaround)                                                            \
   VISIT(BackReference)                                                         \
   VISIT(Empty)                                                                 \
   VISIT(Text)
@@ -549,11 +549,16 @@
 
 class TextNode : public SeqRegExpNode {
  public:
-  TextNode(ZoneGrowableArray<TextElement>* elms, RegExpNode* on_success)
-      : SeqRegExpNode(on_success), elms_(elms) {}
-  TextNode(RegExpCharacterClass* that, RegExpNode* on_success)
+  TextNode(ZoneGrowableArray<TextElement>* elms,
+           bool read_backward,
+           RegExpNode* on_success)
+      : SeqRegExpNode(on_success), elms_(elms), read_backward_(read_backward) {}
+  TextNode(RegExpCharacterClass* that,
+           bool read_backward,
+           RegExpNode* on_success)
       : SeqRegExpNode(on_success),
-        elms_(new (zone()) ZoneGrowableArray<TextElement>(1)) {
+        elms_(new (zone()) ZoneGrowableArray<TextElement>(1)),
+        read_backward_(read_backward) {
     elms_->Add(TextElement::CharClass(that));
   }
   virtual void Accept(NodeVisitor* visitor);
@@ -566,6 +571,7 @@
                                     intptr_t characters_filled_in,
                                     bool not_at_start);
   ZoneGrowableArray<TextElement>* elements() { return elms_; }
+  bool read_backward() { return read_backward_; }
   void MakeCaseIndependent(bool is_one_byte);
   virtual intptr_t GreedyLoopTextLength();
   virtual RegExpNode* GetSuccessorOfOmnivorousTextNode(
@@ -596,6 +602,7 @@
                     intptr_t* checked_up_to);
   intptr_t Length();
   ZoneGrowableArray<TextElement>* elms_;
+  bool read_backward_;
 };
 
 class AssertionNode : public SeqRegExpNode {
@@ -652,11 +659,16 @@
  public:
   BackReferenceNode(intptr_t start_reg,
                     intptr_t end_reg,
+                    bool read_backward,
                     RegExpNode* on_success)
-      : SeqRegExpNode(on_success), start_reg_(start_reg), end_reg_(end_reg) {}
+      : SeqRegExpNode(on_success),
+        start_reg_(start_reg),
+        end_reg_(end_reg),
+        read_backward_(read_backward) {}
   virtual void Accept(NodeVisitor* visitor);
   intptr_t start_register() { return start_reg_; }
   intptr_t end_register() { return end_reg_; }
+  bool read_backward() { return read_backward_; }
   virtual void Emit(RegExpCompiler* compiler, Trace* trace);
   virtual intptr_t EatsAtLeast(intptr_t still_to_find,
                                intptr_t recursion_depth,
@@ -675,6 +687,7 @@
  private:
   intptr_t start_reg_;
   intptr_t end_reg_;
+  bool read_backward_;
 };
 
 class EndNode : public RegExpNode {
@@ -799,6 +812,7 @@
     return true;
   }
   virtual RegExpNode* FilterOneByte(intptr_t depth, bool ignore_case);
+  virtual bool read_backward() { return false; }
 
  protected:
   intptr_t GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative);
@@ -840,11 +854,11 @@
   bool being_calculated_;
 };
 
-class NegativeLookaheadChoiceNode : public ChoiceNode {
+class NegativeLookaroundChoiceNode : public ChoiceNode {
  public:
-  explicit NegativeLookaheadChoiceNode(GuardedAlternative this_must_fail,
-                                       GuardedAlternative then_do_this,
-                                       Zone* zone)
+  explicit NegativeLookaroundChoiceNode(GuardedAlternative this_must_fail,
+                                        GuardedAlternative then_do_this,
+                                        Zone* zone)
       : ChoiceNode(2, zone) {
     AddAlternative(this_must_fail);
     AddAlternative(then_do_this);
@@ -877,11 +891,14 @@
 
 class LoopChoiceNode : public ChoiceNode {
  public:
-  explicit LoopChoiceNode(bool body_can_be_zero_length, Zone* zone)
+  explicit LoopChoiceNode(bool body_can_be_zero_length,
+                          bool read_backward,
+                          Zone* zone)
       : ChoiceNode(2, zone),
         loop_node_(NULL),
         continue_node_(NULL),
-        body_can_be_zero_length_(body_can_be_zero_length) {}
+        body_can_be_zero_length_(body_can_be_zero_length),
+        read_backward_(read_backward) {}
   void AddLoopAlternative(GuardedAlternative alt);
   void AddContinueAlternative(GuardedAlternative alt);
   virtual void Emit(RegExpCompiler* compiler, Trace* trace);
@@ -899,6 +916,7 @@
   RegExpNode* loop_node() { return loop_node_; }
   RegExpNode* continue_node() { return continue_node_; }
   bool body_can_be_zero_length() { return body_can_be_zero_length_; }
+  virtual bool read_backward() { return read_backward_; }
   virtual void Accept(NodeVisitor* visitor);
   virtual RegExpNode* FilterOneByte(intptr_t depth, bool ignore_case);
 
@@ -913,6 +931,7 @@
   RegExpNode* loop_node_;
   RegExpNode* continue_node_;
   bool body_can_be_zero_length_;
+  bool read_backward_;
 };
 
 // Improve the speed that we scan for an initial point where a non-anchored
@@ -1161,9 +1180,7 @@
            quick_check_performed_.characters() == 0 && at_start_ == UNKNOWN;
   }
   TriBool at_start() { return at_start_; }
-  void set_at_start(bool at_start) {
-    at_start_ = at_start ? TRUE_VALUE : FALSE_VALUE;
-  }
+  void set_at_start(TriBool at_start) { at_start_ = at_start; }
   BlockLabel* backtrack() { return backtrack_; }
   BlockLabel* loop_label() { return loop_label_; }
   RegExpNode* stop_node() { return stop_node_; }
diff --git a/runtime/vm/regexp_assembler.h b/runtime/vm/regexp_assembler.h
index 23d32c7..a7b087e 100644
--- a/runtime/vm/regexp_assembler.h
+++ b/runtime/vm/regexp_assembler.h
@@ -120,10 +120,13 @@
   virtual void CheckCharacterGT(uint16_t limit, BlockLabel* on_greater) = 0;
   virtual void CheckCharacterLT(uint16_t limit, BlockLabel* on_less) = 0;
   virtual void CheckGreedyLoop(BlockLabel* on_tos_equals_current_position) = 0;
-  virtual void CheckNotAtStart(BlockLabel* on_not_at_start) = 0;
+  virtual void CheckNotAtStart(intptr_t cp_offset,
+                               BlockLabel* on_not_at_start) = 0;
   virtual void CheckNotBackReference(intptr_t start_reg,
+                                     bool read_backward,
                                      BlockLabel* on_no_match) = 0;
   virtual void CheckNotBackReferenceIgnoreCase(intptr_t start_reg,
+                                               bool read_backward,
                                                BlockLabel* on_no_match) = 0;
   // Check the current character for a match with a literal character.  If we
   // fail to match then goto the on_failure label.  End of input always
diff --git a/runtime/vm/regexp_assembler_bytecode.cc b/runtime/vm/regexp_assembler_bytecode.cc
index f63bfec..fac8a82 100644
--- a/runtime/vm/regexp_assembler_bytecode.cc
+++ b/runtime/vm/regexp_assembler_bytecode.cc
@@ -246,8 +246,9 @@
 }
 
 void BytecodeRegExpMacroAssembler::CheckNotAtStart(
+    intptr_t cp_offset,
     BlockLabel* on_not_at_start) {
-  Emit(BC_CHECK_NOT_AT_START, 0);
+  Emit(BC_CHECK_NOT_AT_START, cp_offset);
   EmitOrLink(on_not_at_start);
 }
 
@@ -336,19 +337,24 @@
 
 void BytecodeRegExpMacroAssembler::CheckNotBackReference(
     intptr_t start_reg,
+    bool read_backward,
     BlockLabel* on_not_equal) {
   ASSERT(start_reg >= 0);
   ASSERT(start_reg <= kMaxRegister);
-  Emit(BC_CHECK_NOT_BACK_REF, start_reg);
+  Emit(read_backward ? BC_CHECK_NOT_BACK_REF_BACKWARD : BC_CHECK_NOT_BACK_REF,
+       start_reg);
   EmitOrLink(on_not_equal);
 }
 
 void BytecodeRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(
     intptr_t start_reg,
+    bool read_backward,
     BlockLabel* on_not_equal) {
   ASSERT(start_reg >= 0);
   ASSERT(start_reg <= kMaxRegister);
-  Emit(BC_CHECK_NOT_BACK_REF_NO_CASE, start_reg);
+  Emit(read_backward ? BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD
+                     : BC_CHECK_NOT_BACK_REF_NO_CASE,
+       start_reg);
   EmitOrLink(on_not_equal);
 }
 
diff --git a/runtime/vm/regexp_assembler_bytecode.h b/runtime/vm/regexp_assembler_bytecode.h
index 81e8d3d..3e17d49 100644
--- a/runtime/vm/regexp_assembler_bytecode.h
+++ b/runtime/vm/regexp_assembler_bytecode.h
@@ -62,7 +62,7 @@
   virtual void CheckCharacterLT(uint16_t limit, BlockLabel* on_less);
   virtual void CheckGreedyLoop(BlockLabel* on_tos_equals_current_position);
   virtual void CheckAtStart(BlockLabel* on_at_start);
-  virtual void CheckNotAtStart(BlockLabel* on_not_at_start);
+  virtual void CheckNotAtStart(intptr_t cp_offset, BlockLabel* on_not_at_start);
   virtual void CheckNotCharacter(unsigned c, BlockLabel* on_not_equal);
   virtual void CheckNotCharacterAfterAnd(unsigned c,
                                          unsigned mask,
@@ -79,8 +79,10 @@
                                         BlockLabel* on_not_in_range);
   virtual void CheckBitInTable(const TypedData& table, BlockLabel* on_bit_set);
   virtual void CheckNotBackReference(intptr_t start_reg,
+                                     bool read_backward,
                                      BlockLabel* on_no_match);
   virtual void CheckNotBackReferenceIgnoreCase(intptr_t start_reg,
+                                               bool read_backward,
                                                BlockLabel* on_no_match);
   virtual void IfRegisterLT(intptr_t register_index,
                             intptr_t comparand,
diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc
index 888061d..bc0a132 100644
--- a/runtime/vm/regexp_assembler_ir.cc
+++ b/runtime/vm/regexp_assembler_ir.cc
@@ -770,38 +770,27 @@
 void IRRegExpMacroAssembler::CheckAtStart(BlockLabel* on_at_start) {
   TAG();
 
-  BlockLabel not_at_start;
-
-  // Did we start the match at the start of the string at all?
-  BranchOrBacktrack(
-      Comparison(kNE, LoadLocal(start_index_param_), Uint64Constant(0)),
-      &not_at_start);
-
-  // If we did, are we still at the start of the input, i.e. is
-  // (offset == string_length * -1)?
+  // Are we at the start of the input, i.e. is (offset == string_length * -1)?
   Definition* neg_len_def =
       InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE),
                    PushLocal(string_param_length_));
   Definition* offset_def = LoadLocal(current_position_);
   BranchOrBacktrack(Comparison(kEQ, neg_len_def, offset_def), on_at_start);
-
-  BindBlock(&not_at_start);
 }
 
-void IRRegExpMacroAssembler::CheckNotAtStart(BlockLabel* on_not_at_start) {
+// cp_offset => offset from the current (character) pointer
+// This offset may be negative due to traversing backwards during lookbehind.
+void IRRegExpMacroAssembler::CheckNotAtStart(intptr_t cp_offset,
+                                             BlockLabel* on_not_at_start) {
   TAG();
 
-  // Did we start the match at the start of the string at all?
-  BranchOrBacktrack(
-      Comparison(kNE, LoadLocal(start_index_param_), Uint64Constant(0)),
-      on_not_at_start);
-
-  // If we did, are we still at the start of the input, i.e. is
-  // (offset == string_length * -1)?
-  Definition* neg_len_def =
-      InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE),
-                   PushLocal(string_param_length_));
-  Definition* offset_def = LoadLocal(current_position_);
+  // Are we at the start of the input, i.e. is (offset == string_length * -1)?
+  auto offset_def =
+      PushArgument(Bind(Add(PushLocal(current_position_),
+                            PushArgument(Bind(Int64Constant(cp_offset))))));
+  auto neg_len_def = PushArgument(
+      Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE),
+                        PushLocal(string_param_length_))));
   BranchOrBacktrack(Comparison(kNE, neg_len_def, offset_def), on_not_at_start);
 }
 
@@ -832,6 +821,7 @@
 
 void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(
     intptr_t start_reg,
+    bool read_backward,
     BlockLabel* on_no_match) {
   TAG();
   ASSERT(start_reg + 1 <= registers_count_);
@@ -857,20 +847,38 @@
       Comparison(kEQ, LoadLocal(capture_length_), Uint64Constant(0)),
       &fallthrough);
 
-  // Check that there are sufficient characters left in the input.
-  PushArgumentInstr* pos_push = PushLocal(current_position_);
-  PushArgumentInstr* len_push = PushLocal(capture_length_);
-  BranchOrBacktrack(
-      Comparison(kGT,
-                 InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD),
-                              pos_push, len_push),
-                 Uint64Constant(0)),
-      on_no_match);
+  PushArgumentInstr* pos_push = nullptr;
+  PushArgumentInstr* len_push = nullptr;
+
+  if (!read_backward) {
+    // Check that there are sufficient characters left in the input.
+    pos_push = PushLocal(current_position_);
+    len_push = PushLocal(capture_length_);
+    BranchOrBacktrack(
+        Comparison(kGT,
+                   InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD),
+                                pos_push, len_push),
+                   Uint64Constant(0)),
+        on_no_match);
+  }
 
   pos_push = PushLocal(current_position_);
   len_push = PushLocal(string_param_length_);
   StoreLocal(match_start_index_, Bind(Add(pos_push, len_push)));
 
+  if (read_backward) {
+    // First check that there are enough characters before this point in
+    // the string that we can match the backreference.
+    BranchOrBacktrack(Comparison(kLT, LoadLocal(match_start_index_),
+                                 LoadLocal(capture_length_)),
+                      on_no_match);
+
+    // The string to check is before the current position, not at it.
+    pos_push = PushLocal(match_start_index_);
+    len_push = PushLocal(capture_length_);
+    StoreLocal(match_start_index_, Bind(Sub(pos_push, len_push)));
+  }
+
   pos_push = PushArgument(LoadRegister(start_reg));
   len_push = PushLocal(string_param_length_);
   StoreLocal(capture_start_index_, Bind(Add(pos_push, len_push)));
@@ -970,15 +978,23 @@
 
   BindBlock(&success);
 
-  // Move current character position to position after match.
-  PushArgumentInstr* match_end_push = PushLocal(match_end_index_);
-  len_push = PushLocal(string_param_length_);
-  StoreLocal(current_position_, Bind(Sub(match_end_push, len_push)));
+  if (read_backward) {
+    // Move current character position to start of match.
+    pos_push = PushLocal(current_position_);
+    len_push = PushLocal(capture_length_);
+    StoreLocal(current_position_, Bind(Sub(pos_push, len_push)));
+  } else {
+    // Move current character position to position after match.
+    PushArgumentInstr* match_end_push = PushLocal(match_end_index_);
+    len_push = PushLocal(string_param_length_);
+    StoreLocal(current_position_, Bind(Sub(match_end_push, len_push)));
+  }
 
   BindBlock(&fallthrough);
 }
 
 void IRRegExpMacroAssembler::CheckNotBackReference(intptr_t start_reg,
+                                                   bool read_backward,
                                                    BlockLabel* on_no_match) {
   TAG();
   ASSERT(start_reg + 1 <= registers_count_);
@@ -1001,21 +1017,39 @@
       Comparison(kEQ, LoadLocal(capture_length_), Uint64Constant(0)),
       &fallthrough);
 
-  // Check that there are sufficient characters left in the input.
-  PushArgumentInstr* pos_push = PushLocal(current_position_);
-  PushArgumentInstr* len_push = PushLocal(capture_length_);
-  BranchOrBacktrack(
-      Comparison(kGT,
-                 InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD),
-                              pos_push, len_push),
-                 Uint64Constant(0)),
-      on_no_match);
+  PushArgumentInstr* pos_push = nullptr;
+  PushArgumentInstr* len_push = nullptr;
+
+  if (!read_backward) {
+    // Check that there are sufficient characters left in the input.
+    pos_push = PushLocal(current_position_);
+    len_push = PushLocal(capture_length_);
+    BranchOrBacktrack(
+        Comparison(kGT,
+                   InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD),
+                                pos_push, len_push),
+                   Uint64Constant(0)),
+        on_no_match);
+  }
 
   // Compute pointers to match string and capture string.
   pos_push = PushLocal(current_position_);
   len_push = PushLocal(string_param_length_);
   StoreLocal(match_start_index_, Bind(Add(pos_push, len_push)));
 
+  if (read_backward) {
+    // First check that there are enough characters before this point in
+    // the string that we can match the backreference.
+    BranchOrBacktrack(Comparison(kLT, LoadLocal(match_start_index_),
+                                 LoadLocal(capture_length_)),
+                      on_no_match);
+
+    // The string to check is before the current position, not at it.
+    pos_push = PushLocal(match_start_index_);
+    len_push = PushLocal(capture_length_);
+    StoreLocal(match_start_index_, Bind(Sub(pos_push, len_push)));
+  }
+
   pos_push = PushArgument(LoadRegister(start_reg));
   len_push = PushLocal(string_param_length_);
   StoreLocal(capture_start_index_, Bind(Add(pos_push, len_push)));
@@ -1050,10 +1084,17 @@
 
   BindBlock(&success);
 
-  // Move current character position to position after match.
-  PushArgumentInstr* match_end_push = PushLocal(match_end_index_);
-  len_push = PushLocal(string_param_length_);
-  StoreLocal(current_position_, Bind(Sub(match_end_push, len_push)));
+  if (read_backward) {
+    // Move current character position to start of match.
+    pos_push = PushLocal(current_position_);
+    len_push = PushLocal(capture_length_);
+    StoreLocal(current_position_, Bind(Sub(pos_push, len_push)));
+  } else {
+    // Move current character position to position after match.
+    PushArgumentInstr* match_end_push = PushLocal(match_end_index_);
+    len_push = PushLocal(string_param_length_);
+    StoreLocal(current_position_, Bind(Sub(match_end_push, len_push)));
+  }
 
   BindBlock(&fallthrough);
 }
@@ -1361,10 +1402,13 @@
                                                   bool check_bounds,
                                                   intptr_t characters) {
   TAG();
-  ASSERT(cp_offset >= -1);        // ^ and \b can look behind one character.
   ASSERT(cp_offset < (1 << 30));  // Be sane! (And ensure negation works)
   if (check_bounds) {
-    CheckPosition(cp_offset + characters - 1, on_end_of_input);
+    if (cp_offset >= 0) {
+      CheckPosition(cp_offset + characters - 1, on_end_of_input);
+    } else {
+      CheckPosition(cp_offset, on_end_of_input);
+    }
   }
   LoadCurrentCharacterUnchecked(cp_offset, characters);
 }
@@ -1594,13 +1638,24 @@
 void IRRegExpMacroAssembler::CheckPosition(intptr_t cp_offset,
                                            BlockLabel* on_outside_input) {
   TAG();
-  Definition* curpos_def = LoadLocal(current_position_);
-  Definition* cp_off_def = Int64Constant(-cp_offset);
+  if (cp_offset >= 0) {
+    Definition* curpos_def = LoadLocal(current_position_);
+    Definition* cp_off_def = Int64Constant(-cp_offset);
+    // If (current_position_ < -cp_offset), we are in bounds.
+    // Remember, current_position_ is a negative offset from the string end.
 
-  // If (current_position_ < -cp_offset), we are in bounds.
-  // Remember, current_position_ is a negative offset from the string end.
-
-  BranchOrBacktrack(Comparison(kGTE, curpos_def, cp_off_def), on_outside_input);
+    BranchOrBacktrack(Comparison(kGTE, curpos_def, cp_off_def),
+                      on_outside_input);
+  } else {
+    // We need to see if there's enough characters left in the string to go
+    // back cp_offset characters, so get the normalized position and then
+    // make sure that (normalized_position >= -cp_offset).
+    PushArgumentInstr* pos_push = PushLocal(current_position_);
+    PushArgumentInstr* len_push = PushLocal(string_param_length_);
+    BranchOrBacktrack(
+        Comparison(kLT, Add(pos_push, len_push), Uint64Constant(-cp_offset)),
+        on_outside_input);
+  }
 }
 
 void IRRegExpMacroAssembler::BranchOrBacktrack(ComparisonInstr* comparison,
diff --git a/runtime/vm/regexp_assembler_ir.h b/runtime/vm/regexp_assembler_ir.h
index 3652b72..c4f6e1f 100644
--- a/runtime/vm/regexp_assembler_ir.h
+++ b/runtime/vm/regexp_assembler_ir.h
@@ -61,10 +61,12 @@
   // A "greedy loop" is a loop that is both greedy and with a simple
   // body. It has a particularly simple implementation.
   virtual void CheckGreedyLoop(BlockLabel* on_tos_equals_current_position);
-  virtual void CheckNotAtStart(BlockLabel* on_not_at_start);
+  virtual void CheckNotAtStart(intptr_t cp_offset, BlockLabel* on_not_at_start);
   virtual void CheckNotBackReference(intptr_t start_reg,
+                                     bool read_backward,
                                      BlockLabel* on_no_match);
   virtual void CheckNotBackReferenceIgnoreCase(intptr_t start_reg,
+                                               bool read_backward,
                                                BlockLabel* on_no_match);
   virtual void CheckNotCharacter(uint32_t c, BlockLabel* on_not_equal);
   virtual void CheckNotCharacterAfterAnd(uint32_t c,
diff --git a/runtime/vm/regexp_ast.cc b/runtime/vm/regexp_ast.cc
index 5b51a6f..e096e2b 100644
--- a/runtime/vm/regexp_ast.cc
+++ b/runtime/vm/regexp_ast.cc
@@ -43,7 +43,7 @@
   return ListCaptureRegisters(alternatives());
 }
 
-Interval RegExpLookahead::CaptureRegisters() const {
+Interval RegExpLookaround::CaptureRegisters() const {
   return body()->CaptureRegisters();
 }
 
@@ -108,8 +108,8 @@
   return true;
 }
 
-bool RegExpLookahead::IsAnchoredAtStart() const {
-  return is_positive() && body()->IsAnchoredAtStart();
+bool RegExpLookaround::IsAnchoredAtStart() const {
+  return is_positive() && type() == LOOKAHEAD && body()->IsAnchoredAtStart();
 }
 
 bool RegExpCapture::IsAnchoredAtStart() const {
@@ -241,8 +241,11 @@
   return NULL;
 }
 
-void* RegExpUnparser::VisitLookahead(RegExpLookahead* that, void* data) {
-  OS::PrintErr("(-> %s", (that->is_positive() ? "+ " : "- "));
+void* RegExpUnparser::VisitLookaround(RegExpLookaround* that, void* data) {
+  OS::PrintErr("(");
+  OS::PrintErr("(%s %s",
+               (that->type() == RegExpLookaround::LOOKAHEAD ? "->" : "<-"),
+               (that->is_positive() ? "+ " : "- "));
   that->body()->Accept(this, data);
   OS::PrintErr(")");
   return NULL;
diff --git a/runtime/vm/regexp_ast.h b/runtime/vm/regexp_ast.h
index 438dc3c..55f2f8c 100644
--- a/runtime/vm/regexp_ast.h
+++ b/runtime/vm/regexp_ast.h
@@ -21,7 +21,7 @@
 class RegExpCompiler;
 class RegExpDisjunction;
 class RegExpEmpty;
-class RegExpLookahead;
+class RegExpLookaround;
 class RegExpQuantifier;
 class RegExpText;
 
@@ -277,8 +277,7 @@
 
 class RegExpCapture : public RegExpTree {
  public:
-  explicit RegExpCapture(RegExpTree* body, intptr_t index)
-      : body_(body), index_(index) {}
+  explicit RegExpCapture(intptr_t index) : body_(nullptr), index_(index) {}
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success);
   static RegExpNode* ToNode(RegExpTree* body,
@@ -293,6 +292,11 @@
   virtual intptr_t min_match() const { return body_->min_match(); }
   virtual intptr_t max_match() const { return body_->max_match(); }
   RegExpTree* body() const { return body_; }
+  // When a backreference is parsed before the corresponding capture group,
+  // which can happen because of lookbehind, we create the capture object when
+  // we create the backreference, and fill in the body later when the actual
+  // capture group is parsed.
+  void set_body(RegExpTree* body) { body_ = body; }
   intptr_t index() const { return index_; }
   static intptr_t StartRegister(intptr_t index) { return index * 2; }
   static intptr_t EndRegister(intptr_t index) { return index * 2 + 1; }
@@ -302,22 +306,25 @@
   intptr_t index_;
 };
 
-class RegExpLookahead : public RegExpTree {
+class RegExpLookaround : public RegExpTree {
  public:
-  RegExpLookahead(RegExpTree* body,
-                  bool is_positive,
-                  intptr_t capture_count,
-                  intptr_t capture_from)
+  enum Type { LOOKAHEAD, LOOKBEHIND };
+  RegExpLookaround(RegExpTree* body,
+                   bool is_positive,
+                   intptr_t capture_count,
+                   intptr_t capture_from,
+                   Type type)
       : body_(body),
         is_positive_(is_positive),
         capture_count_(capture_count),
-        capture_from_(capture_from) {}
+        capture_from_(capture_from),
+        type_(type) {}
 
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success);
-  virtual RegExpLookahead* AsLookahead();
+  virtual RegExpLookaround* AsLookaround();
   virtual Interval CaptureRegisters() const;
-  virtual bool IsLookahead() const;
+  virtual bool IsLookaround() const;
   virtual bool IsAnchoredAtStart() const;
   virtual intptr_t min_match() const { return 0; }
   virtual intptr_t max_match() const { return 0; }
@@ -325,12 +332,36 @@
   bool is_positive() const { return is_positive_; }
   intptr_t capture_count() const { return capture_count_; }
   intptr_t capture_from() const { return capture_from_; }
+  Type type() const { return type_; }
+
+  // The RegExpLookaround::Builder class abstracts out the process of building
+  // the compiling a RegExpLookaround object by splitting it into two phases,
+  // represented by the provided methods.
+  class Builder : public ValueObject {
+   public:
+    Builder(bool is_positive,
+            RegExpNode* on_success,
+            intptr_t stack_pointer_register,
+            intptr_t position_register,
+            intptr_t capture_register_count = 0,
+            intptr_t capture_register_start = 0);
+    RegExpNode* on_match_success() { return on_match_success_; }
+    RegExpNode* ForMatch(RegExpNode* match);
+
+   private:
+    bool is_positive_;
+    RegExpNode* on_match_success_;
+    RegExpNode* on_success_;
+    intptr_t stack_pointer_register_;
+    intptr_t position_register_;
+  };
 
  private:
   RegExpTree* body_;
   bool is_positive_;
   intptr_t capture_count_;
   intptr_t capture_from_;
+  Type type_;
 };
 
 class RegExpBackReference : public RegExpTree {
@@ -341,7 +372,10 @@
   virtual RegExpBackReference* AsBackReference();
   virtual bool IsBackReference() const;
   virtual intptr_t min_match() const { return 0; }
-  virtual intptr_t max_match() const { return capture_->max_match(); }
+  // The back reference may be recursive, e.g. /(\2)(\1)/. To avoid infinite
+  // recursion, we give up and just assume arbitrary length, which matches v8's
+  // behavior.
+  virtual intptr_t max_match() const { return kInfinity; }
   intptr_t index() const { return capture_->index(); }
   RegExpCapture* capture() const { return capture_; }
 
diff --git a/runtime/vm/regexp_bytecodes.h b/runtime/vm/regexp_bytecodes.h
index c2ef82b..858eef5 100644
--- a/runtime/vm/regexp_bytecodes.h
+++ b/runtime/vm/regexp_bytecodes.h
@@ -55,15 +55,17 @@
 V(CHECK_GT,          36, 8)   /* bc8 pad8 uc16 addr32                       */ \
 V(CHECK_NOT_BACK_REF, 37, 8)  /* bc8 reg_idx24 addr32                       */ \
 V(CHECK_NOT_BACK_REF_NO_CASE, 38, 8) /* bc8 reg_idx24 addr32                */ \
-V(CHECK_NOT_REGS_EQUAL, 39, 12) /* bc8 regidx24 reg_idx32 addr32            */ \
-V(CHECK_REGISTER_LT, 40, 12)  /* bc8 reg_idx24 value32 addr32               */ \
-V(CHECK_REGISTER_GE, 41, 12)  /* bc8 reg_idx24 value32 addr32               */ \
-V(CHECK_REGISTER_EQ_POS, 42, 8) /* bc8 reg_idx24 addr32                     */ \
-V(CHECK_AT_START,    43, 8)   /* bc8 pad24 addr32                           */ \
-V(CHECK_NOT_AT_START, 44, 8)  /* bc8 pad24 addr32                           */ \
-V(CHECK_GREEDY,      45, 8)   /* bc8 pad24 addr32                           */ \
-V(ADVANCE_CP_AND_GOTO, 46, 8) /* bc8 offset24 addr32                        */ \
-V(SET_CURRENT_POSITION_FROM_END, 47, 4) /* bc8 idx24                        */
+V(CHECK_NOT_BACK_REF_BACKWARD, 39, 8) /* bc8 reg_idx24 addr32               */ \
+V(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD, 40, 8) /* bc8 reg_idx24 addr32       */ \
+V(CHECK_NOT_REGS_EQUAL, 41, 12) /* bc8 regidx24 reg_idx32 addr32            */ \
+V(CHECK_REGISTER_LT, 42, 12)  /* bc8 reg_idx24 value32 addr32               */ \
+V(CHECK_REGISTER_GE, 43, 12)  /* bc8 reg_idx24 value32 addr32               */ \
+V(CHECK_REGISTER_EQ_POS, 44, 8) /* bc8 reg_idx24 addr32                     */ \
+V(CHECK_AT_START,    45, 8)   /* bc8 pad24 addr32                           */ \
+V(CHECK_NOT_AT_START, 46, 8)  /* bc8 offset24 addr32                        */ \
+V(CHECK_GREEDY,      47, 8)   /* bc8 pad24 addr32                           */ \
+V(ADVANCE_CP_AND_GOTO, 48, 8) /* bc8 offset24 addr32                        */ \
+V(SET_CURRENT_POSITION_FROM_END, 49, 4) /* bc8 idx24                        */
 
 // clang-format on
 
diff --git a/runtime/vm/regexp_interpreter.cc b/runtime/vm/regexp_interpreter.cc
index c83f474..ecc7586 100644
--- a/runtime/vm/regexp_interpreter.cc
+++ b/runtime/vm/regexp_interpreter.cc
@@ -268,7 +268,7 @@
       break;
       BYTECODE(LOAD_CURRENT_CHAR) {
         int pos = current + (insn >> BYTECODE_SHIFT);
-        if (pos >= subject_length) {
+        if (pos < 0 || pos >= subject_length) {
           pc = code_base + Load32Aligned(pc + 4);
         } else {
           current_char = subject.CharAt(pos);
@@ -534,6 +534,55 @@
         }
         break;
       }
+      BYTECODE(CHECK_NOT_BACK_REF_BACKWARD) {
+        const int from = registers[insn >> BYTECODE_SHIFT];
+        const int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
+        if (from < 0 || len <= 0) {
+          pc += BC_CHECK_NOT_BACK_REF_BACKWARD_LENGTH;
+          break;
+        }
+        if ((current - len) < 0) {
+          pc = code_base + Load32Aligned(pc + 4);
+          break;
+        } else {
+          // When looking behind, the string to match (if it is there) lies
+          // before the current position, so we will check the [len] characters
+          // before the current position, excluding the current position itself.
+          const int start = current - len;
+          int i;
+          for (i = 0; i < len; i++) {
+            if (subject.CharAt(from + i) != subject.CharAt(start + i)) {
+              pc = code_base + Load32Aligned(pc + 4);
+              break;
+            }
+          }
+          if (i < len) break;
+          current -= len;
+        }
+        pc += BC_CHECK_NOT_BACK_REF_BACKWARD_LENGTH;
+        break;
+      }
+      BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD) {
+        int from = registers[insn >> BYTECODE_SHIFT];
+        int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
+        if (from < 0 || len <= 0) {
+          pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH;
+          break;
+        }
+        if (current < len) {
+          pc = code_base + Load32Aligned(pc + 4);
+          break;
+        } else {
+          if (BackRefMatchesNoCase<Char>(&canonicalize, from, current - len,
+                                         len, subject)) {
+            current -= len;
+            pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH;
+          } else {
+            pc = code_base + Load32Aligned(pc + 4);
+          }
+        }
+        break;
+      }
       BYTECODE(CHECK_AT_START)
       if (current == 0) {
         pc = code_base + Load32Aligned(pc + 4);
@@ -541,13 +590,15 @@
         pc += BC_CHECK_AT_START_LENGTH;
       }
       break;
-      BYTECODE(CHECK_NOT_AT_START)
-      if (current == 0) {
-        pc += BC_CHECK_NOT_AT_START_LENGTH;
-      } else {
-        pc = code_base + Load32Aligned(pc + 4);
+      BYTECODE(CHECK_NOT_AT_START) {
+        const int32_t cp_offset = insn >> BYTECODE_SHIFT;
+        if (current + cp_offset == 0) {
+          pc += BC_CHECK_NOT_AT_START_LENGTH;
+        } else {
+          pc = code_base + Load32Aligned(pc + 4);
+        }
+        break;
       }
-      break;
       BYTECODE(SET_CURRENT_POSITION_FROM_END) {
         int by = static_cast<uint32_t>(insn) >> BYTECODE_SHIFT;
         if (subject_length - current > by) {
diff --git a/runtime/vm/regexp_parser.cc b/runtime/vm/regexp_parser.cc
index 10c9c00..e08071a 100644
--- a/runtime/vm/regexp_parser.cc
+++ b/runtime/vm/regexp_parser.cc
@@ -129,13 +129,13 @@
   return new (Z) RegExpDisjunction(alternatives);
 }
 
-void RegExpBuilder::AddQuantifierToAtom(
+bool RegExpBuilder::AddQuantifierToAtom(
     intptr_t min,
     intptr_t max,
     RegExpQuantifier::QuantifierType quantifier_type) {
   if (pending_empty_) {
     pending_empty_ = false;
-    return;
+    return true;
   }
   RegExpTree* atom;
   if (characters_ != NULL) {
@@ -167,22 +167,28 @@
   } else if (terms_.length() > 0) {
     DEBUG_ASSERT(last_added_ == ADD_ATOM);
     atom = terms_.RemoveLast();
+    if (auto lookaround = atom->AsLookaround()) {
+      // Lookbehinds are not quantifiable.
+      if (lookaround->type() == RegExpLookaround::LOOKBEHIND) {
+        return false;
+      }
+    }
     if (atom->max_match() == 0) {
       // Guaranteed to only match an empty string.
       LAST(ADD_TERM);
       if (min == 0) {
-        return;
+        return true;
       }
       terms_.Add(atom);
-      return;
+      return true;
     }
   } else {
     // Only call immediately after adding an atom or character!
     UNREACHABLE();
-    return;
   }
   terms_.Add(new (Z) RegExpQuantifier(min, max, quantifier_type, atom));
   LAST(ADD_TERM);
+  return true;
 }
 
 // ----------------------------------------------------------------------------
@@ -194,6 +200,7 @@
       in_(in),
       current_(kEndMarker),
       next_pos_(0),
+      captures_started_(0),
       capture_count_(0),
       has_more_(true),
       multiline_(multiline),
@@ -275,7 +282,8 @@
 //   Atom Quantifier
 RegExpTree* RegExpParser::ParseDisjunction() {
   // Used to store current state while parsing subexpressions.
-  RegExpParserState initial_state(NULL, INITIAL, 0, Z);
+  RegExpParserState initial_state(NULL, INITIAL, RegExpLookaround::LOOKAHEAD, 0,
+                                  Z);
   RegExpParserState* stored_state = &initial_state;
   // Cache the builder in a local variable for quick access.
   RegExpBuilder* builder = initial_state.builder();
@@ -307,23 +315,24 @@
         intptr_t capture_index = stored_state->capture_index();
         SubexpressionType group_type = stored_state->group_type();
 
+        // Build result of subexpression.
+        if (group_type == CAPTURE) {
+          RegExpCapture* capture = GetCapture(capture_index);
+          capture->set_body(body);
+          body = capture;
+        } else if (group_type != GROUPING) {
+          ASSERT(group_type == POSITIVE_LOOKAROUND ||
+                 group_type == NEGATIVE_LOOKAROUND);
+          bool is_positive = (group_type == POSITIVE_LOOKAROUND);
+          body = new (Z) RegExpLookaround(
+              body, is_positive, end_capture_index - capture_index,
+              capture_index, stored_state->lookaround_type());
+        }
+
         // Restore previous state.
         stored_state = stored_state->previous_state();
         builder = stored_state->builder();
 
-        // Build result of subexpression.
-        if (group_type == CAPTURE) {
-          RegExpCapture* capture = new (Z) RegExpCapture(body, capture_index);
-          (*captures_)[capture_index - 1] = capture;
-          body = capture;
-        } else if (group_type != GROUPING) {
-          ASSERT(group_type == POSITIVE_LOOKAHEAD ||
-                 group_type == NEGATIVE_LOOKAHEAD);
-          bool is_positive = (group_type == POSITIVE_LOOKAHEAD);
-          body = new (Z)
-              RegExpLookahead(body, is_positive,
-                              end_capture_index - capture_index, capture_index);
-        }
         builder->AddAtom(body);
         // For compatibility with JSC and ES3, we allow quantifiers after
         // lookaheads, and break in all cases.
@@ -370,37 +379,7 @@
         break;
       }
       case '(': {
-        SubexpressionType subexpr_type = CAPTURE;
-        Advance();
-        if (current() == '?') {
-          switch (Next()) {
-            case ':':
-              subexpr_type = GROUPING;
-              break;
-            case '=':
-              subexpr_type = POSITIVE_LOOKAHEAD;
-              break;
-            case '!':
-              subexpr_type = NEGATIVE_LOOKAHEAD;
-              break;
-            default:
-              ReportError("Invalid group");
-              UNREACHABLE();
-          }
-          Advance(2);
-        } else {
-          if (captures_ == NULL) {
-            captures_ = new ZoneGrowableArray<RegExpCapture*>(2);
-          }
-          if (captures_started() >= kMaxCaptures) {
-            ReportError("Too many captures");
-            UNREACHABLE();
-          }
-          captures_->Add(NULL);
-        }
-        // Store current state and begin new disjunction parsing.
-        stored_state = new RegExpParserState(stored_state, subexpr_type,
-                                             captures_started(), Z);
+        stored_state = ParseOpenParenthesis(stored_state);
         builder = stored_state->builder();
         continue;
       }
@@ -457,16 +436,18 @@
           case '9': {
             intptr_t index = 0;
             if (ParseBackReferenceIndex(&index)) {
-              RegExpCapture* capture = NULL;
-              if (captures_ != NULL && index <= captures_->length()) {
-                capture = captures_->At(index - 1);
-              }
-              if (capture == NULL) {
+              if (stored_state->IsInsideCaptureGroup(index)) {
+                // The back reference is inside the capture group it refers to.
+                // Nothing can possibly have been captured yet, so we use empty
+                // instead. This ensures that, when checking a back reference,
+                // the capture registers of the referenced capture are either
+                // both set or both cleared.
                 builder->AddEmpty();
-                break;
+              } else {
+                RegExpCapture* capture = GetCapture(index);
+                RegExpTree* atom = new RegExpBackReference(capture);
+                builder->AddAtom(atom);
               }
-              RegExpTree* atom = new RegExpBackReference(capture);
-              builder->AddAtom(atom);
               break;
             }
             uint32_t first_digit = Next();
@@ -610,7 +591,10 @@
       quantifier_type = RegExpQuantifier::POSSESSIVE;
       Advance();
     }
-    builder->AddQuantifierToAtom(min, max, quantifier_type);
+    if (!builder->AddQuantifierToAtom(min, max, quantifier_type)) {
+      ReportError("invalid quantifier.");
+      UNREACHABLE();
+    }
   }
 }
 
@@ -631,6 +615,57 @@
 }
 #endif
 
+RegExpParser::RegExpParserState* RegExpParser::ParseOpenParenthesis(
+    RegExpParserState* state) {
+  RegExpLookaround::Type lookaround_type = state->lookaround_type();
+  SubexpressionType subexpr_type = CAPTURE;
+  Advance();
+  if (current() == '?') {
+    switch (Next()) {
+      case ':':
+        Advance(2);
+        subexpr_type = GROUPING;
+        break;
+      case '=':
+        Advance(2);
+        lookaround_type = RegExpLookaround::LOOKAHEAD;
+        subexpr_type = POSITIVE_LOOKAROUND;
+        break;
+      case '!':
+        Advance(2);
+        lookaround_type = RegExpLookaround::LOOKAHEAD;
+        subexpr_type = NEGATIVE_LOOKAROUND;
+        break;
+      case '<':
+        Advance();
+        if (Next() == '=') {
+          Advance(2);
+          lookaround_type = RegExpLookaround::LOOKBEHIND;
+          subexpr_type = POSITIVE_LOOKAROUND;
+        } else if (Next() == '!') {
+          Advance(2);
+          lookaround_type = RegExpLookaround::LOOKBEHIND;
+          subexpr_type = NEGATIVE_LOOKAROUND;
+        }
+        break;
+      default:
+        ReportError("Invalid group");
+        UNREACHABLE();
+    }
+  }
+
+  if (subexpr_type == CAPTURE) {
+    if (captures_started_ >= kMaxCaptures) {
+      ReportError("Too many captures");
+      UNREACHABLE();
+    }
+    captures_started_++;
+  }
+  // Store current state and begin new disjunction parsing.
+  return new RegExpParserState(state, subexpr_type, lookaround_type,
+                               captures_started_, Z);
+}
+
 // In order to know whether an escape is a backreference or not we have to scan
 // the entire regexp and find the number of capturing parentheses.  However we
 // don't want to scan the regexp twice unless it is necessary.  This mini-parser
@@ -638,6 +673,8 @@
 // noncapturing parentheses and can skip character classes and backslash-escaped
 // characters.
 void RegExpParser::ScanForCaptures() {
+  ASSERT(!is_scanned_for_captures_);
+  const intptr_t saved_position = position();
   // Start with captures started previous to current position
   intptr_t capture_count = captures_started();
   // Add count of captures after this position.
@@ -667,6 +704,7 @@
   }
   capture_count_ = capture_count;
   is_scanned_for_captures_ = true;
+  Reset(saved_position);
 }
 
 static inline bool IsDecimalDigit(int32_t c) {
@@ -695,11 +733,7 @@
     }
   }
   if (value > captures_started()) {
-    if (!is_scanned_for_captures_) {
-      intptr_t saved_position = position();
-      ScanForCaptures();
-      Reset(saved_position);
-    }
+    if (!is_scanned_for_captures_) ScanForCaptures();
     if (value > capture_count_) {
       Reset(start);
       return false;
@@ -709,6 +743,32 @@
   return true;
 }
 
+RegExpCapture* RegExpParser::GetCapture(intptr_t index) {
+  // The index for the capture groups are one-based. Its index in the list is
+  // zero-based.
+  const intptr_t know_captures =
+      is_scanned_for_captures_ ? capture_count_ : captures_started_;
+  ASSERT(index <= know_captures);
+  if (captures_ == nullptr) {
+    captures_ = new (Z) ZoneGrowableArray<RegExpCapture*>(know_captures);
+  }
+  while (captures_->length() < know_captures) {
+    captures_->Add(new (Z) RegExpCapture(captures_->length() + 1));
+  }
+  return captures_->At(index - 1);
+}
+
+bool RegExpParser::RegExpParserState::IsInsideCaptureGroup(intptr_t index) {
+  for (RegExpParserState* s = this; s != nullptr; s = s->previous_state()) {
+    if (s->group_type() != CAPTURE) continue;
+    // Return true if we found the matching capture index.
+    if (index == s->capture_index()) return true;
+    // Abort if index is larger than what has been parsed up till this state.
+    if (index > s->capture_index()) return false;
+  }
+  return false;
+}
+
 // QuantifierPrefix ::
 //   { DecimalDigits }
 //   { DecimalDigits , }
diff --git a/runtime/vm/regexp_parser.h b/runtime/vm/regexp_parser.h
index 51e44c5..c4e127b 100644
--- a/runtime/vm/regexp_parser.h
+++ b/runtime/vm/regexp_parser.h
@@ -23,7 +23,10 @@
   void AddAtom(RegExpTree* tree);
   void AddAssertion(RegExpTree* tree);
   void NewAlternative();  // '|'
-  void AddQuantifierToAtom(intptr_t min,
+  // Attempt to add a quantifier to the last atom added. The return value
+  // denotes whether the attempt succeeded, since some atoms like lookbehind
+  // cannot be quantified.
+  bool AddQuantifierToAtom(intptr_t min,
                            intptr_t max,
                            RegExpQuantifier::QuantifierType type);
   RegExpTree* ToRegExp();
@@ -93,9 +96,7 @@
   bool simple();
   bool contains_anchor() { return contains_anchor_; }
   void set_contains_anchor() { contains_anchor_ = true; }
-  intptr_t captures_started() {
-    return captures_ == NULL ? 0 : captures_->length();
-  }
+  intptr_t captures_started() { return captures_started_; }
   intptr_t position() { return next_pos_ - 1; }
 
   static const intptr_t kMaxCaptures = 1 << 16;
@@ -105,8 +106,8 @@
   enum SubexpressionType {
     INITIAL,
     CAPTURE,  // All positive values represent captures.
-    POSITIVE_LOOKAHEAD,
-    NEGATIVE_LOOKAHEAD,
+    POSITIVE_LOOKAROUND,
+    NEGATIVE_LOOKAROUND,
     GROUPING
   };
 
@@ -114,11 +115,13 @@
    public:
     RegExpParserState(RegExpParserState* previous_state,
                       SubexpressionType group_type,
+                      RegExpLookaround::Type lookaround_type,
                       intptr_t disjunction_capture_index,
                       Zone* zone)
         : previous_state_(previous_state),
           builder_(new (zone) RegExpBuilder()),
           group_type_(group_type),
+          lookaround_type_(lookaround_type),
           disjunction_capture_index_(disjunction_capture_index) {}
     // Parser state of containing expression, if any.
     RegExpParserState* previous_state() { return previous_state_; }
@@ -127,11 +130,16 @@
     RegExpBuilder* builder() { return builder_; }
     // Type of regexp being parsed (parenthesized group or entire regexp).
     SubexpressionType group_type() { return group_type_; }
+    // Lookahead or lookbehind.
+    RegExpLookaround::Type lookaround_type() { return lookaround_type_; }
     // Index in captures array of first capture in this sub-expression, if any.
     // Also the capture index of this sub-expression itself, if group_type
     // is CAPTURE.
     intptr_t capture_index() { return disjunction_capture_index_; }
 
+    // Check whether the parser is inside a capture group with the given index.
+    bool IsInsideCaptureGroup(intptr_t index);
+
    private:
     // Linked list implementation of stack of states.
     RegExpParserState* previous_state_;
@@ -139,10 +147,17 @@
     RegExpBuilder* builder_;
     // Stored disjunction type (capture, look-ahead or grouping), if any.
     SubexpressionType group_type_;
+    // Stored read direction.
+    const RegExpLookaround::Type lookaround_type_;
     // Stored disjunction's capture index (if any).
     intptr_t disjunction_capture_index_;
   };
 
+  // Return the 1-indexed RegExpCapture object, allocate if necessary.
+  RegExpCapture* GetCapture(intptr_t index);
+
+  RegExpParserState* ParseOpenParenthesis(RegExpParserState* state);
+
   Zone* zone() { return zone_; }
 
   uint32_t current() { return current_; }
@@ -157,6 +172,7 @@
   const String& in_;
   uint32_t current_;
   intptr_t next_pos_;
+  intptr_t captures_started_;
   // The capture count is only valid after we have scanned for captures.
   intptr_t capture_count_;
   bool has_more_;
diff --git a/runtime/vm/resolver.cc b/runtime/vm/resolver.cc
index bd13f8c..d7a9fc6 100644
--- a/runtime/vm/resolver.cc
+++ b/runtime/vm/resolver.cc
@@ -78,7 +78,7 @@
     demangled ^= Field::NameFromGetter(function_name);
   }
 
-  if (Function::IsDynamicInvocationForwaderName(function_name)) {
+  if (Function::IsDynamicInvocationForwarderName(function_name)) {
     demangled ^=
         Function::DemangleDynamicInvocationForwarderName(function_name);
 #ifdef DART_PRECOMPILED_RUNTIME
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 212b0fd..8e90333 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -1041,7 +1041,7 @@
 
   // Handle noSuchMethod for dyn:methodName by getting a noSuchMethod dispatcher
   // (or a call-through getter for methodName).
-  if (Function::IsDynamicInvocationForwaderName(target_name)) {
+  if (Function::IsDynamicInvocationForwarderName(target_name)) {
     const String& demangled = String::Handle(
         Function::DemangleDynamicInvocationForwarderName(target_name));
     return InlineCacheMissHelper(receiver, args_descriptor, demangled);
@@ -1682,7 +1682,7 @@
     target_name = MegamorphicCache::Cast(ic_data_or_cache).target_name();
   }
 
-  if (Function::IsDynamicInvocationForwaderName(target_name)) {
+  if (Function::IsDynamicInvocationForwarderName(target_name)) {
     target_name = Function::DemangleDynamicInvocationForwarderName(target_name);
   }
 
@@ -1805,6 +1805,11 @@
 //  - hot reload
 static void HandleStackOverflowTestCases(Thread* thread) {
   Isolate* isolate = thread->isolate();
+
+  if (FLAG_shared_slow_path_triggers_gc) {
+    isolate->heap()->CollectAllGarbage();
+  }
+
   bool do_deopt = false;
   bool do_stacktrace = false;
   bool do_reload = false;
@@ -2023,15 +2028,11 @@
   // persist.
   uword stack_overflow_flags = thread->GetAndClearStackOverflowFlags();
 
-  if (FLAG_shared_slow_path_triggers_gc) {
-    isolate->heap()->CollectAllGarbage();
-  }
-
   bool interpreter_stack_overflow = false;
 #if !defined(DART_PRECOMPILED_RUNTIME)
   if (FLAG_enable_interpreter) {
     // Do not allocate an interpreter, if none is allocated yet.
-    Interpreter* interpreter = Thread::Current()->interpreter();
+    Interpreter* interpreter = thread->interpreter();
     if (interpreter != NULL) {
       interpreter_stack_overflow =
           interpreter->get_sp() >= interpreter->overflow_stack_limit();
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index c866994..f08dc42 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -173,13 +173,16 @@
   Object& object = Object::Handle();
   {
     Api::Scope api_scope(T);
-    TransitionVMToNative transition(T);
-    if (get_service_assets_callback_ == NULL) {
-      return Object::null();
-    }
-    Dart_Handle handle = get_service_assets_callback_();
-    if (Dart_IsError(handle)) {
-      Dart_PropagateError(handle);
+    Dart_Handle handle;
+    {
+      TransitionVMToNative transition(T);
+      if (get_service_assets_callback_ == NULL) {
+        return Object::null();
+      }
+      handle = get_service_assets_callback_();
+      if (Dart_IsError(handle)) {
+        Dart_PropagateError(handle);
+      }
     }
     object = Api::UnwrapHandle(handle);
   }
@@ -1374,6 +1377,16 @@
   return true;
 }
 
+static const MethodParameter* get_memory_usage_params[] = {
+    ISOLATE_PARAMETER,
+    NULL,
+};
+
+static bool GetMemoryUsage(Thread* thread, JSONStream* js) {
+  thread->isolate()->PrintMemoryUsageJSON(js);
+  return true;
+}
+
 static const MethodParameter* get_scripts_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
@@ -2362,6 +2375,11 @@
     return true;
   }
 
+  bool disable_breakpoints =
+      BoolParameter::Parse(js->LookupParam("disableBreakpoints"), false);
+  DisableBreakpointsScope db(thread->isolate()->debugger(),
+                             disable_breakpoints);
+
   Zone* zone = thread->zone();
   ObjectIdRing::LookupResult lookup_result;
   Object& receiver = Object::Handle(
@@ -2842,6 +2860,11 @@
   }
 
   Isolate* isolate = thread->isolate();
+
+  bool disable_breakpoints =
+      BoolParameter::Parse(js->LookupParam("disableBreakpoints"), false);
+  DisableBreakpointsScope db(isolate->debugger(), disable_breakpoints);
+
   DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
   intptr_t frame_pos = UIntParameter::Parse(js->LookupParam("frameIndex"));
   if (frame_pos >= stack->Length()) {
@@ -4863,6 +4886,8 @@
     get_instances_params },
   { "getIsolate", GetIsolate,
     get_isolate_params },
+  { "getMemoryUsage", GetMemoryUsage,
+    get_memory_usage_params },
   { "_getIsolateMetric", GetIsolateMetric,
     get_isolate_metric_params },
   { "_getIsolateMetricList", GetIsolateMetricList,
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index df5e2da..0040087 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.14
+# Dart VM Service Protocol 3.16
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.14_ of the Dart VM Service Protocol. This
+This document describes of _version 3.16_ of the Dart VM Service Protocol. This
 protocol is used to communicate with a running Dart Virtual Machine.
 
 To use the Service Protocol, start the VM with the *--observe* flag.
@@ -31,6 +31,7 @@
   - [evaluateInFrame](#evaluateinframe)
   - [getFlagList](#getflaglist)
   - [getIsolate](#getisolate)
+  - [getMemoryUsage](#getmemoryusage)
   - [getScripts](#getscripts)
   - [getObject](#getobject)
   - [getSourceReport](#getsourcereport)
@@ -75,6 +76,7 @@
   - [Library](#library)
   - [LibraryDependency](#librarydependency)
   - [MapAssociation](#mapassociation)
+  - [MemoryUsage](#memoryusage)
   - [Message](#message)
   - [Null](#null)
   - [Object](#object)
@@ -479,7 +481,8 @@
 @Instance|@Error|Sentinel invoke(string isolateId,
                                  string targetId,
                                  string selector,
-                                 string[] argumentIds)
+                                 string[] argumentIds,
+                                 bool disableBreakpoints [optional])
 ```
 
 The _invoke_ RPC is used to perform regular method invocation on some receiver,
@@ -491,6 +494,10 @@
 
 Each elements of _argumentId_ may refer to an [Instance](#instance).
 
+If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
+result of this invocation are ignored, including pauses resulting from a call
+to `debugger()` from `dart:developer`. Defaults to false if not provided.
+
 If _targetId_ or any element of _argumentIds_ is a temporary id which has
 expired, then the _Expired_ [Sentinel](#sentinel) is returned.
 
@@ -513,7 +520,8 @@
 @Instance|@Error|Sentinel evaluate(string isolateId,
                                    string targetId,
                                    string expression,
-                                   map<string,string> scope [optional])
+                                   map<string,string> scope [optional],
+                                   bool disableBreakpoints [optional])
 ```
 
 The _evaluate_ RPC is used to evaluate an expression in the context of
@@ -535,6 +543,9 @@
 targets respectively. This means bindings provided in _scope_ may shadow
 instance members, class members and top-level members.
 
+If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
+result of this evaluation are ignored. Defaults to false if not provided.
+
 If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
 "Expression compilation error" is returned.
 
@@ -550,7 +561,8 @@
 @Instance|@Error|Sentinel evaluateInFrame(string isolateId,
                                           int frameIndex,
                                           string expression,
-                                          map<string,string> scope [optional])
+                                          map<string,string> scope [optional],
+                                          bool disableBreakpoints [optional])
 ```
 
 The _evaluateInFrame_ RPC is used to evaluate an expression in the
@@ -564,6 +576,9 @@
 provided in _scope_ may shadow instance members, class members, top-level
 members, parameters and locals.
 
+If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
+result of this evaluation are ignored. Defaults to false if not provided.
+
 If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
 "Expression compilation error" is returned.
 
@@ -597,6 +612,20 @@
 
 See [Isolate](#isolate).
 
+### getMemoryUsage
+
+```
+MemoryUsage|Sentinel getMemoryUsage(string isolateId)
+```
+
+The _getMemoryUsage_ RPC is used to lookup an isolate's memory usage
+statistics by its _id_.
+
+If _isolateId_ refers to an isolate which has exited, then the
+_Collected_ [Sentinel](#sentinel) is returned.
+
+See [Isolate](#isolate).
+
 ### getScripts
 
 ```
@@ -2194,6 +2223,31 @@
 }
 ```
 
+### MemoryUsage
+
+```
+class MemoryUsage extends Response {
+  // The amount of non-Dart memory that is retained by Dart objects. For
+  // example, memory associated with Dart objects through APIs such as
+  // Dart_NewWeakPersistentHandle and Dart_NewExternalTypedData.  This usage is
+  // only as accurate as the values supplied to these APIs from the VM embedder or
+  // native extensions. This external memory applies GC pressure, but is separate
+  // from heapUsage and heapCapacity.
+  int externalUsage;
+
+  // The total capacity of the heap in bytes. This is the amount of memory used
+  // by the Dart heap from the perspective of the operating system.
+  int heapCapacity;
+
+  // The current heap memory usage in bytes. Heap usage is always less than or
+  // equal to the heap capacity.
+  int heapUsage;
+}
+```
+
+An _MemoryUsage_ object provides heap usage information for a specific
+isolate at a given point in time.
+
 ### Message
 
 ```
@@ -2751,5 +2805,7 @@
 3.12 | Add 'getScripts' RPC and `ScriptList` object.
 3.13 | Class 'mixin' field now properly set for kernel transformed mixin applications.
 3.14 | Flag 'profile_period' can now be set at runtime, allowing for the profiler sample rate to be changed while the program is running.
+3.15 | Added `disableBreakpoints` parameter to `invoke`, `evaluate`, and `evaluateInFrame`.
+3.16 | Add 'getMemoryUsage' RPC and 'MemoryUsage' object.
 
 [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service/service_dev.md b/runtime/vm/service/service_dev.md
index 1808c86..a440425 100644
--- a/runtime/vm/service/service_dev.md
+++ b/runtime/vm/service/service_dev.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.15-dev
+# Dart VM Service Protocol 3.17-dev
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.15-dev_ of the Dart VM Service Protocol. This
+This document describes of _version 3.17-dev_ of the Dart VM Service Protocol. This
 protocol is used to communicate with a running Dart Virtual Machine.
 
 To use the Service Protocol, start the VM with the *--observe* flag.
@@ -31,6 +31,7 @@
   - [evaluateInFrame](#evaluateinframe)
   - [getFlagList](#getflaglist)
   - [getIsolate](#getisolate)
+  - [getMemoryUsage](#getmemoryusage)
   - [getScripts](#getscripts)
   - [getObject](#getobject)
   - [getSourceReport](#getsourcereport)
@@ -75,6 +76,7 @@
   - [Library](#library)
   - [LibraryDependency](#librarydependency)
   - [MapAssociation](#mapassociation)
+  - [MemoryUsage](#memoryusage)
   - [Message](#message)
   - [Null](#null)
   - [Object](#object)
@@ -479,7 +481,8 @@
 @Instance|@Error|Sentinel invoke(string isolateId,
                                  string targetId,
                                  string selector,
-                                 string[] argumentIds)
+                                 string[] argumentIds,
+                                 bool disableBreakpoints [optional])
 ```
 
 The _invoke_ RPC is used to perform regular method invocation on some receiver,
@@ -491,6 +494,10 @@
 
 Each elements of _argumentId_ may refer to an [Instance](#instance).
 
+If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
+result of this invocation are ignored, including pauses resulting from a call
+to `debugger()` from `dart:developer`. Defaults to false if not provided.
+
 If _targetId_ or any element of _argumentIds_ is a temporary id which has
 expired, then the _Expired_ [Sentinel](#sentinel) is returned.
 
@@ -513,7 +520,8 @@
 @Instance|@Error|Sentinel evaluate(string isolateId,
                                    string targetId,
                                    string expression,
-                                   map<string,string> scope [optional])
+                                   map<string,string> scope [optional],
+                                   bool disableBreakpoints [optional])
 ```
 
 The _evaluate_ RPC is used to evaluate an expression in the context of
@@ -535,6 +543,9 @@
 targets respectively. This means bindings provided in _scope_ may shadow
 instance members, class members and top-level members.
 
+If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
+result of this evaluation are ignored. Defaults to false if not provided.
+
 If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
 "Expression compilation error" is returned.
 
@@ -550,7 +561,8 @@
 @Instance|@Error|Sentinel evaluateInFrame(string isolateId,
                                           int frameIndex,
                                           string expression,
-                                          map<string,string> scope [optional])
+                                          map<string,string> scope [optional],
+                                          bool disableBreakpoints [optional])
 ```
 
 The _evaluateInFrame_ RPC is used to evaluate an expression in the
@@ -564,6 +576,9 @@
 provided in _scope_ may shadow instance members, class members, top-level
 members, parameters and locals.
 
+If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
+result of this evaluation are ignored. Defaults to false if not provided.
+
 If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
 "Expression compilation error" is returned.
 
@@ -597,6 +612,20 @@
 
 See [Isolate](#isolate).
 
+### getMemoryUsage
+
+```
+MemoryUsage|Sentinel getMemoryUsage(string isolateId)
+```
+
+The _getMemoryUsage_ RPC is used to lookup an isolate's memory usage
+statistics by its _id_.
+
+If _isolateId_ refers to an isolate which has exited, then the
+_Collected_ [Sentinel](#sentinel) is returned.
+
+See [Isolate](#isolate).
+
 ### getScripts
 
 ```
@@ -2194,6 +2223,31 @@
 }
 ```
 
+### MemoryUsage
+
+```
+class MemoryUsage extends Response {
+  // The amount of non-Dart memory that is retained by Dart objects. For
+  // example, memory associated with Dart objects through APIs such as
+  // Dart_NewWeakPersistentHandle and Dart_NewExternalTypedData.  This usage is
+  // only as accurate as the values supplied to these APIs from the VM embedder or
+  // native extensions. This external memory applies GC pressure, but is separate
+  // from heapUsage and heapCapacity.
+  int externalUsage;
+
+  // The total capacity of the heap in bytes. This is the amount of memory used
+  // by the Dart heap from the perspective of the operating system.
+  int heapCapacity;
+
+  // The current heap memory usage in bytes. Heap usage is always less than or
+  // equal to the heap capacity.
+  int heapUsage;
+}
+```
+
+An _MemoryUsage_ object provides heap usage information for a specific
+isolate at a given point in time.
+
 ### Message
 
 ```
@@ -2751,5 +2805,7 @@
 3.12 | Add 'getScripts' RPC and `ScriptList` object.
 3.13 | Class 'mixin' field now properly set for kernel transformed mixin applications.
 3.14 | Flag 'profile_period' can now be set at runtime, allowing for the profiler sample rate to be changed while the program is running.
+3.15 | Added `disableBreakpoints` parameter to `invoke`, `evaluate`, and `evaluateInFrame`.
+3.16 | Add 'getMemoryUsage' RPC and 'MemoryUsage' object.
 
 [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 0b9df59..58b38e3 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -37,15 +37,15 @@
           (class_id >= kNullCid && class_id <= kVoidCid));
 }
 
-static bool IsObjectStoreClassId(intptr_t class_id) {
-  // Check if this is a class which is stored in the object store.
+static bool IsBootstrapedClassId(intptr_t class_id) {
+  // Check if this is a class which is created during bootstrapping.
   return (class_id == kObjectCid ||
           (class_id >= kInstanceCid && class_id <= kUserTagCid) ||
           class_id == kArrayCid || class_id == kImmutableArrayCid ||
           RawObject::IsStringClassId(class_id) ||
           RawObject::IsTypedDataClassId(class_id) ||
           RawObject::IsExternalTypedDataClassId(class_id) ||
-          class_id == kNullCid);
+          RawObject::IsTypedDataViewClassId(class_id) || class_id == kNullCid);
 }
 
 static bool IsObjectStoreTypeId(intptr_t index) {
@@ -70,7 +70,6 @@
 
 static intptr_t ObjectIdFromClassId(intptr_t class_id) {
   ASSERT((class_id > kIllegalCid) && (class_id < kNumPredefinedCids));
-  ASSERT(!(RawObject::IsImplicitFieldClassId(class_id)));
   return (class_id + kClassIdsOffset);
 }
 
@@ -209,6 +208,7 @@
       old_space_(thread_->isolate()->heap()->old_space()),
       cls_(Class::Handle(zone_)),
       code_(Code::Handle(zone_)),
+      instance_(Instance::Handle(zone_)),
       instructions_(Instructions::Handle(zone_)),
       obj_(Object::Handle(zone_)),
       pobj_(PassiveObject::Handle(zone_)),
@@ -221,6 +221,7 @@
       tokens_(GrowableObjectArray::Handle(zone_)),
       data_(ExternalTypedData::Handle(zone_)),
       typed_data_(TypedData::Handle(zone_)),
+      typed_data_view_(TypedDataView::Handle(zone_)),
       function_(Function::Handle(zone_)),
       error_(UnhandledException::Handle(zone_)),
       set_class_(Class::ZoneHandle(
@@ -315,7 +316,7 @@
   ASSERT(!IsVMIsolateObject(class_header) ||
          !IsSingletonClassId(GetVMIsolateObjectId(class_header)));
   ASSERT((SerializedHeaderTag::decode(class_header) != kObjectId) ||
-         !IsObjectStoreClassId(SerializedHeaderData::decode(class_header)));
+         !IsBootstrapedClassId(SerializedHeaderData::decode(class_header)));
   Class& cls = Class::ZoneHandle(zone(), Class::null());
   AddBackRef(object_id, &cls, kIsDeserialized);
   // Read the library/class information and lookup the class.
@@ -479,6 +480,15 @@
       break;
     }
 #undef SNAPSHOT_READ
+#define SNAPSHOT_READ(clazz) case kTypedData##clazz##ViewCid:
+
+    case kByteDataViewCid:
+      CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
+        tags = RawObject::ClassIdTag::update(class_id, tags);
+        pobj_ = TypedDataView::ReadFrom(this, object_id, tags, kind_, true);
+        break;
+      }
+#undef SNAPSHOT_READ
 #define SNAPSHOT_READ(clazz) case kFfi##clazz##Cid:
 
     CLASS_LIST_FFI(SNAPSHOT_READ) { UNREACHABLE(); }
@@ -688,7 +698,7 @@
   }
   ASSERT(SerializedHeaderTag::decode(class_header) == kObjectId);
   intptr_t class_id = SerializedHeaderData::decode(class_header);
-  ASSERT(IsObjectStoreClassId(class_id) || IsSingletonClassId(class_id));
+  ASSERT(IsBootstrapedClassId(class_id) || IsSingletonClassId(class_id));
   return class_id;
 }
 
@@ -758,7 +768,7 @@
 
 RawObject* SnapshotReader::ReadIndexedObject(intptr_t object_id) {
   intptr_t class_id = ClassIdFromObjectId(object_id);
-  if (IsObjectStoreClassId(class_id)) {
+  if (IsBootstrapedClassId(class_id)) {
     return isolate()->class_table()->At(class_id);  // get singleton class.
   }
   if (IsObjectStoreTypeId(object_id)) {
@@ -1025,7 +1035,7 @@
   if (cid == kClassCid) {
     RawClass* raw_class = reinterpret_cast<RawClass*>(rawobj);
     intptr_t class_id = raw_class->ptr()->id_;
-    if (IsObjectStoreClassId(class_id)) {
+    if (IsBootstrapedClassId(class_id)) {
       intptr_t object_id = ObjectIdFromClassId(class_id);
       WriteIndexedObject(object_id);
       return true;
@@ -1110,6 +1120,16 @@
       return;
     }
 #undef SNAPSHOT_WRITE
+#define SNAPSHOT_WRITE(clazz) case kTypedData##clazz##ViewCid:
+
+    case kByteDataViewCid:
+      CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
+        auto* raw_obj = reinterpret_cast<RawTypedDataView*>(raw);
+        raw_obj->WriteTo(this, object_id, kind_, as_reference);
+        return;
+      }
+#undef SNAPSHOT_WRITE
+
 #define SNAPSHOT_WRITE(clazz) case kFfi##clazz##Cid:
 
     CLASS_LIST_FFI(SNAPSHOT_WRITE) { UNREACHABLE(); }
@@ -1171,7 +1191,7 @@
 void SnapshotWriter::WriteClassId(RawClass* cls) {
   ASSERT(!Snapshot::IsFull(kind_));
   int class_id = cls->ptr()->id_;
-  ASSERT(!IsSingletonClassId(class_id) && !IsObjectStoreClassId(class_id));
+  ASSERT(!IsSingletonClassId(class_id) && !IsBootstrapedClassId(class_id));
 
   // Write out the library url and class name.
   RawLibrary* library = cls->ptr()->library_;
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 5a4ab63..248127c 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -28,6 +28,7 @@
 class ExternalTypedData;
 class GrowableObjectArray;
 class Heap;
+class Instance;
 class Instructions;
 class LanguageError;
 class Library;
@@ -37,6 +38,7 @@
 class ObjectStore;
 class MegamorphicCache;
 class PageSpace;
+class TypedDataView;
 class RawApiError;
 class RawArray;
 class RawCapability;
@@ -86,6 +88,7 @@
 class RawType;
 class RawTypeArguments;
 class RawTypedData;
+class RawTypedDataView;
 class RawTypeParameter;
 class RawTypeRef;
 class RawUnhandledException;
@@ -98,8 +101,8 @@
 // Serialized object header encoding is as follows:
 // - Smi: the Smi value is written as is (last bit is not tagged).
 // - VM object (from VM isolate): (object id in vm isolate | 0x3)
-//   This valus is serialized as a negative number.
-//   (note VM objects are never serialized they are expected to be found
+//   This value is serialized as a negative number.
+//   (note VM objects are never serialized, they are expected to be found
 //    using ths unique ID assigned to them).
 // - Reference to object that has already been written: (object id | 0x3)
 //   This valus is serialized as a positive number.
@@ -300,6 +303,7 @@
   Array* ArrayHandle() { return &array_; }
   Class* ClassHandle() { return &cls_; }
   Code* CodeHandle() { return &code_; }
+  Instance* InstanceHandle() { return &instance_; }
   Instructions* InstructionsHandle() { return &instructions_; }
   String* StringHandle() { return &str_; }
   AbstractType* TypeHandle() { return &type_; }
@@ -307,6 +311,7 @@
   GrowableObjectArray* TokensHandle() { return &tokens_; }
   ExternalTypedData* DataHandle() { return &data_; }
   TypedData* TypedDataHandle() { return &typed_data_; }
+  TypedDataView* TypedDataViewHandle() { return &typed_data_view_; }
   Function* FunctionHandle() { return &function_; }
   Snapshot::Kind kind() const { return kind_; }
 
@@ -386,6 +391,7 @@
   PageSpace* old_space_;           // Old space of the current isolate.
   Class& cls_;                     // Temporary Class handle.
   Code& code_;                     // Temporary Code handle.
+  Instance& instance_;             // Temporary Instance handle
   Instructions& instructions_;     // Temporary Instructions handle
   Object& obj_;                    // Temporary Object handle.
   PassiveObject& pobj_;            // Temporary PassiveObject handle.
@@ -398,6 +404,7 @@
   GrowableObjectArray& tokens_;    // Temporary tokens handle.
   ExternalTypedData& data_;        // Temporary stream data handle.
   TypedData& typed_data_;          // Temporary typed data handle.
+  TypedDataView& typed_data_view_;  // Temporary typed data view handle.
   Function& function_;             // Temporary function handle.
   UnhandledException& error_;      // Error handle.
   const Class& set_class_;         // The LinkedHashSet class.
@@ -433,6 +440,7 @@
   friend class SignatureData;
   friend class SubtypeTestCache;
   friend class Type;
+  friend class TypedDataView;
   friend class TypeArguments;
   friend class TypeParameter;
   friend class TypeRef;
@@ -705,6 +713,7 @@
   friend class RawStackTrace;
   friend class RawSubtypeTestCache;
   friend class RawType;
+  friend class RawTypedDataView;
   friend class RawTypeRef;
   friend class RawTypeArguments;
   friend class RawTypeParameter;
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 78cea42..b204514 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -405,7 +405,7 @@
   // The thread setting the stack limit is not necessarily the thread which
   // the stack limit is being set on.
   MonitorLocker ml(thread_lock_);
-  if (stack_limit_ == saved_stack_limit_) {
+  if (!HasScheduledInterrupts()) {
     // No interrupt pending, set stack_limit_ too.
     stack_limit_ = limit;
   }
diff --git a/runtime/vm/timeline_linux.cc b/runtime/vm/timeline_linux.cc
index 4dbad22..dc45ffb 100644
--- a/runtime/vm/timeline_linux.cc
+++ b/runtime/vm/timeline_linux.cc
@@ -28,9 +28,9 @@
   const char* kSystraceDebugPath = "/sys/kernel/debug/tracing/trace_marker";
   const char* kSystracePath = "/sys/kernel/tracing/trace_marker";
 
-  int fd = TEMP_FAILURE_RETRY(::open(kSystraceDebugPath, O_WRONLY));
+  int fd = TEMP_FAILURE_RETRY(::open(kSystracePath, O_WRONLY));
   if (fd < 0) {
-    fd = TEMP_FAILURE_RETRY(::open(kSystracePath, O_WRONLY));
+    fd = TEMP_FAILURE_RETRY(::open(kSystraceDebugPath, O_WRONLY));
   }
 
   if (fd < 0 && FLAG_trace_timeline) {
diff --git a/runtime/vm/unicode.cc b/runtime/vm/unicode.cc
index a3b4fb9..90379d1 100644
--- a/runtime/vm/unicode.cc
+++ b/runtime/vm/unicode.cc
@@ -344,6 +344,7 @@
       return false;  // Invalid input.
     }
     if (is_supplementary) {
+      if (j == (len - 1)) return false;  // Output overflow.
       Utf16::Encode(ch, &dst[j]);
       j = j + 1;
     } else {
diff --git a/runtime/vm/version.h b/runtime/vm/version.h
index 24540c3..fdc6bb0 100644
--- a/runtime/vm/version.h
+++ b/runtime/vm/version.h
@@ -14,7 +14,6 @@
   static const char* String();
   static const char* SnapshotString();
   static const char* CommitString();
-  static int TargetAbiVersion();
   static int CurrentAbiVersion();
   static int OldestSupportedAbiVersion();
 
diff --git a/runtime/vm/version_in.cc b/runtime/vm/version_in.cc
index d59584b..ae3cff7 100644
--- a/runtime/vm/version_in.cc
+++ b/runtime/vm/version_in.cc
@@ -10,12 +10,6 @@
 
 namespace dart {
 
-DEFINE_FLAG(int,
-            use_abi_version,
-            Version::CurrentAbiVersion(),
-            "ABI version to use. Valid values are "
-            "{{OLDEST_SUPPORTED_ABI_VERSION}} to {{ABI_VERSION}}.");
-
 // TODO(iposva): Avoid racy initialization.
 static const char* formatted_version = NULL;
 
@@ -36,14 +30,6 @@
   return commit_;
 }
 
-int Version::TargetAbiVersion() {
-  int ver = FLAG_use_abi_version;
-  if (ver < OldestSupportedAbiVersion() || ver > CurrentAbiVersion()) {
-    ver = CurrentAbiVersion();
-  }
-  return ver;
-}
-
 int Version::CurrentAbiVersion() {
   return {{ABI_VERSION}};
 }
diff --git a/runtime/vm/virtual_memory.cc b/runtime/vm/virtual_memory.cc
index 6d73ba0..48ba867 100644
--- a/runtime/vm/virtual_memory.cc
+++ b/runtime/vm/virtual_memory.cc
@@ -17,12 +17,18 @@
 void VirtualMemory::Truncate(intptr_t new_size) {
   ASSERT(Utils::IsAligned(new_size, PageSize()));
   ASSERT(new_size <= size());
-  if (reserved_.size() == region_.size()) { // Don't create holes in reservation.
+  if (reserved_.size() ==
+      region_.size()) {  // Don't create holes in reservation.
     FreeSubSegment(reinterpret_cast<void*>(start() + new_size),
                    size() - new_size);
     reserved_.set_size(new_size);
+    if (AliasOffset() != 0) {
+      FreeSubSegment(reinterpret_cast<void*>(alias_.start() + new_size),
+                     alias_.size() - new_size);
+    }
   }
   region_.Subregion(region_, 0, new_size);
+  alias_.Subregion(alias_, 0, new_size);
 }
 
 VirtualMemory* VirtualMemory::ForImagePage(void* pointer, uword size) {
@@ -31,7 +37,7 @@
   MemoryRegion region(pointer, size);
   MemoryRegion reserved(0, 0);  // NULL reservation indicates VM should not
                                 // attempt to free this memory.
-  VirtualMemory* memory = new VirtualMemory(region, reserved);
+  VirtualMemory* memory = new VirtualMemory(region, region, reserved);
   ASSERT(!memory->vm_owns_region());
   return memory;
 }
diff --git a/runtime/vm/virtual_memory.h b/runtime/vm/virtual_memory.h
index 6d74541..496e63c 100644
--- a/runtime/vm/virtual_memory.h
+++ b/runtime/vm/virtual_memory.h
@@ -28,10 +28,14 @@
   uword end() const { return region_.end(); }
   void* address() const { return region_.pointer(); }
   intptr_t size() const { return region_.size(); }
+  intptr_t AliasOffset() const { return alias_.start() - region_.start(); }
 
   static void Init();
 
   bool Contains(uword addr) const { return region_.Contains(addr); }
+  bool ContainsAlias(uword addr) const {
+    return (AliasOffset() != 0) && alias_.Contains(addr);
+  }
 
   // Changes the protection of the virtual memory area.
   static void Protect(void* address, intptr_t size, Protection mode);
@@ -72,14 +76,22 @@
   // can give back the virtual memory to the system. Returns true on success.
   static void FreeSubSegment(void* address, intptr_t size);
 
-  // This constructor is only used internally when reserving new virtual spaces.
-  // It does not reserve any virtual address space on its own.
+  // These constructors are only used internally when reserving new virtual
+  // spaces. They do not reserve any virtual address space on their own.
   VirtualMemory(const MemoryRegion& region,
+                const MemoryRegion& alias,
                 const MemoryRegion& reserved)
-      : region_(region), reserved_(reserved) {}
+      : region_(region), alias_(alias), reserved_(reserved) {}
+
+  VirtualMemory(const MemoryRegion& region, const MemoryRegion& reserved)
+      : region_(region), alias_(region), reserved_(reserved) {}
 
   MemoryRegion region_;
 
+  // Optional secondary mapping of region_ to a virtual space with different
+  // protection, e.g. allowing code execution.
+  MemoryRegion alias_;
+
   // The underlying reservation not yet given back to the OS.
   // Its address might disagree with region_ due to aligned allocations.
   // Its size might disagree with region_ due to Truncate.
@@ -87,6 +99,10 @@
 
   static uword page_size_;
 
+#if defined(HOST_OS_FUCHSIA)
+  static uword base_;  // Cached base of root vmar.
+#endif
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(VirtualMemory);
 };
 
diff --git a/runtime/vm/virtual_memory_fuchsia.cc b/runtime/vm/virtual_memory_fuchsia.cc
index 63c47ae..b627ddf 100644
--- a/runtime/vm/virtual_memory_fuchsia.cc
+++ b/runtime/vm/virtual_memory_fuchsia.cc
@@ -35,15 +35,29 @@
 
 namespace dart {
 
+DECLARE_FLAG(bool, dual_map_code);
 DECLARE_FLAG(bool, write_protect_code);
 
 uword VirtualMemory::page_size_ = 0;
+uword VirtualMemory::base_ = 0;
 
 void VirtualMemory::Init() {
   page_size_ = getpagesize();
+
+  // Cache the base of zx_vmar_root_self() which is used to align mappings.
+  zx_info_vmar_t buf[1];
+  size_t actual;
+  size_t avail;
+  zx_status_t status =
+      zx_object_get_info(zx_vmar_root_self(), ZX_INFO_VMAR, buf,
+                         sizeof(zx_info_vmar_t), &actual, &avail);
+  if (status != ZX_OK) {
+    FATAL1("zx_object_get_info failed: %s\n", zx_status_get_string(status));
+  }
+  base_ = buf[0].base;
 }
 
-static void unmap(zx_handle_t vmar, uword start, uword end) {
+static void Unmap(zx_handle_t vmar, uword start, uword end) {
   ASSERT(start <= end);
   const uword size = end - start;
   if (size == 0) {
@@ -56,28 +70,61 @@
   }
 }
 
+static void* MapAligned(zx_handle_t vmar,
+                        zx_handle_t vmo,
+                        zx_vm_option_t options,
+                        uword size,
+                        uword alignment,
+                        uword vmar_base,
+                        uword padded_size) {
+  uword base;
+  zx_status_t status =
+      zx_vmar_map(vmar, options, 0, vmo, 0u, padded_size, &base);
+  LOG_INFO("zx_vmar_map(%u, 0x%lx, 0x%lx)\n", options, base, padded_size);
+
+  if (status != ZX_OK) {
+    LOG_ERR("zx_vmar_map(%u, 0x%lx, 0x%lx) failed: %s\n", options, base,
+            padded_size, zx_status_get_string(status));
+    return NULL;
+  }
+  const uword aligned_base = Utils::RoundUp(base, alignment);
+  const zx_vm_option_t overwrite_options = options | ZX_VM_SPECIFIC_OVERWRITE;
+  status = zx_vmar_map(vmar, overwrite_options, aligned_base - vmar_base, vmo,
+                       0u, size, &base);
+  LOG_INFO("zx_vmar_map(%u, 0x%lx, 0x%lx)\n", overwrite_options,
+           aligned_base - vmar_base, size);
+
+  if (status != ZX_OK) {
+    LOG_ERR("zx_vmar_map(%u, 0x%lx, 0x%lx) failed: %s\n", overwrite_options,
+            aligned_base - vmar_base, size, zx_status_get_string(status));
+    return NULL;
+  }
+  ASSERT(base == aligned_base);
+  return reinterpret_cast<void*>(base);
+}
+
 VirtualMemory* VirtualMemory::AllocateAligned(intptr_t size,
                                               intptr_t alignment,
                                               bool is_executable,
                                               const char* name) {
-  // When FLAG_write_protect_code is active, the VM allocates code
-  // memory with !is_executable, and later changes to executable via
-  // VirtualMemory::Protect, which requires ZX_RIGHT_EXECUTE on the
-  // underlying VMO. Conservatively assume all memory needs to be
-  // executable in this mode.
-  // TODO(mdempsky): Make into parameter.
-  const bool can_prot_exec = FLAG_write_protect_code;
+  // When FLAG_write_protect_code is active, code memory (indicated by
+  // is_executable = true) is allocated as non-executable and later
+  // changed to executable via VirtualMemory::Protect, which requires
+  // ZX_RIGHT_EXECUTE on the underlying VMO.
+  // In addition, dual mapping of the same underlying code memory is provided.
+  const bool dual_mapping =
+      is_executable && FLAG_write_protect_code && FLAG_dual_map_code;
 
   ASSERT(Utils::IsAligned(size, page_size_));
   ASSERT(Utils::IsPowerOfTwo(alignment));
   ASSERT(Utils::IsAligned(alignment, page_size_));
-  const intptr_t allocated_size = size + alignment - page_size_;
+  const intptr_t padded_size = size + alignment - page_size_;
 
   zx_handle_t vmar = zx_vmar_root_self();
   zx_handle_t vmo = ZX_HANDLE_INVALID;
-  zx_status_t status = zx_vmo_create(allocated_size, 0u, &vmo);
+  zx_status_t status = zx_vmo_create(size, 0u, &vmo);
   if (status != ZX_OK) {
-    LOG_ERR("zx_vmo_create(%ld) failed: %s\n", size,
+    LOG_ERR("zx_vmo_create(0x%lx) failed: %s\n", size,
             zx_status_get_string(status));
     return NULL;
   }
@@ -86,9 +133,9 @@
     zx_object_set_property(vmo, ZX_PROP_NAME, name, strlen(name));
   }
 
-  if (is_executable || can_prot_exec) {
+  if (is_executable) {
     // Add ZX_RIGHT_EXECUTE permission to VMO, so it can be mapped
-    // into memory as executable.
+    // into memory as executable (now or later).
     status = zx_vmo_replace_as_executable(vmo, ZX_HANDLE_INVALID, &vmo);
     if (status != ZX_OK) {
       LOG_ERR("zx_vmo_replace_as_executable() failed: %s\n",
@@ -97,39 +144,59 @@
     }
   }
 
-  const zx_vm_option_t options = ZX_VM_PERM_READ | ZX_VM_PERM_WRITE |
-                                 (is_executable ? ZX_VM_PERM_EXECUTE : 0);
-  uword base;
-  status = zx_vmar_map(vmar, options, 0u, vmo, 0u, allocated_size, &base);
-  zx_handle_close(vmo);
-  if (status != ZX_OK) {
-    LOG_ERR("zx_vmar_map(%u, %ld) failed: %s\n", flags, size,
-            zx_status_get_string(status));
+  const zx_vm_option_t region_options =
+      ZX_VM_PERM_READ | ZX_VM_PERM_WRITE |
+      ((is_executable && !FLAG_write_protect_code) ? ZX_VM_PERM_EXECUTE : 0);
+  void* region_ptr = MapAligned(vmar, vmo, region_options, size, alignment,
+                                base_, padded_size);
+  if (region_ptr == NULL) {
     return NULL;
   }
+  MemoryRegion region(region_ptr, size);
 
-  const uword aligned_base = Utils::RoundUp(base, alignment);
+  VirtualMemory* result;
 
-  unmap(vmar, base, aligned_base);
-  unmap(vmar, aligned_base + size, base + allocated_size);
-
-  MemoryRegion region(reinterpret_cast<void*>(aligned_base), size);
-  return new VirtualMemory(region, region);
+  if (dual_mapping) {
+    // ZX_VM_PERM_EXECUTE is added later via VirtualMemory::Protect.
+    const zx_vm_option_t alias_options = ZX_VM_PERM_READ;
+    void* alias_ptr = MapAligned(vmar, vmo, alias_options, size, alignment,
+                                 base_, padded_size);
+    if (alias_ptr == NULL) {
+      const uword region_base = reinterpret_cast<uword>(region_ptr);
+      Unmap(vmar, region_base, region_base + size);
+      return NULL;
+    }
+    ASSERT(region_ptr != alias_ptr);
+    MemoryRegion alias(alias_ptr, size);
+    result = new VirtualMemory(region, alias, region);
+  } else {
+    result = new VirtualMemory(region, region, region);
+  }
+  zx_handle_close(vmo);
+  return result;
 }
 
 VirtualMemory::~VirtualMemory() {
   // Reserved region may be empty due to VirtualMemory::Truncate.
   if (vm_owns_region() && reserved_.size() != 0) {
-    unmap(zx_vmar_root_self(), reserved_.start(), reserved_.end());
-    LOG_INFO("zx_vmar_unmap(%lx, %lx) success\n", reserved_.start(),
+    Unmap(zx_vmar_root_self(), reserved_.start(), reserved_.end());
+    LOG_INFO("zx_vmar_unmap(0x%lx, 0x%lx) success\n", reserved_.start(),
              reserved_.size());
+
+    const intptr_t alias_offset = AliasOffset();
+    if (alias_offset != 0) {
+      Unmap(zx_vmar_root_self(), reserved_.start() + alias_offset,
+            reserved_.end() + alias_offset);
+      LOG_INFO("zx_vmar_unmap(0x%lx, 0x%lx) success\n",
+               reserved_.start() + alias_offset, reserved_.size());
+    }
   }
 }
 
 void VirtualMemory::FreeSubSegment(void* address, intptr_t size) {
   const uword start = reinterpret_cast<uword>(address);
-  unmap(zx_vmar_root_self(), start, start + size);
-  LOG_INFO("zx_vmar_unmap(%p, %lx) success\n", address, size);
+  Unmap(zx_vmar_root_self(), start, start + size);
+  LOG_INFO("zx_vmar_unmap(0x%p, 0x%lx) success\n", address, size);
 }
 
 void VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
@@ -161,12 +228,12 @@
   }
   zx_status_t status = zx_vmar_protect(zx_vmar_root_self(), prot, page_address,
                                        end_address - page_address);
+  LOG_INFO("zx_vmar_protect(%u, 0x%lx, 0x%lx)\n", prot, page_address,
+           end_address - page_address);
   if (status != ZX_OK) {
-    FATAL3("zx_vmar_protect(%lx, %lx) failed: %s\n", page_address,
+    FATAL3("zx_vmar_protect(0x%lx, 0x%lx) failed: %s\n", page_address,
            end_address - page_address, zx_status_get_string(status));
   }
-  LOG_INFO("zx_vmar_protect(%lx, %lx, %x) success\n", page_address,
-           end_address - page_address, prot);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/virtual_memory_posix.cc b/runtime/vm/virtual_memory_posix.cc
index 31c7f15..5751e7f 100644
--- a/runtime/vm/virtual_memory_posix.cc
+++ b/runtime/vm/virtual_memory_posix.cc
@@ -8,14 +8,23 @@
 #include "vm/virtual_memory.h"
 
 #include <errno.h>
+#include <fcntl.h>
 #include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
 #include <unistd.h>
 
 #include "platform/assert.h"
 #include "platform/utils.h"
-
 #include "vm/isolate.h"
 
+// #define VIRTUAL_MEMORY_LOGGING 1
+#if defined(VIRTUAL_MEMORY_LOGGING)
+#define LOG_INFO(msg, ...) OS::PrintErr(msg, ##__VA_ARGS__)
+#else
+#define LOG_INFO(msg, ...)
+#endif  // defined(VIRTUAL_MEMORY_LOGGING)
+
 namespace dart {
 
 // standard MAP_FAILED causes "error: use of old-style cast" as it
@@ -23,10 +32,38 @@
 #undef MAP_FAILED
 #define MAP_FAILED reinterpret_cast<void*>(-1)
 
+DECLARE_FLAG(bool, dual_map_code);
+DECLARE_FLAG(bool, write_protect_code);
+
 uword VirtualMemory::page_size_ = 0;
 
 void VirtualMemory::Init() {
   page_size_ = getpagesize();
+
+#if defined(DUAL_MAPPING_SUPPORTED)
+  // Detect dual mapping exec permission limitation on some platforms,
+  // such as on docker containers, and disable dual mapping in this case.
+  // Also detect for missing support of memfd_create syscall.
+  if (FLAG_dual_map_code) {
+    intptr_t size = page_size_;
+    intptr_t alignment = 256 * 1024;  // e.g. heap page size.
+    VirtualMemory* vm = AllocateAligned(size, alignment, true, NULL);
+    if (vm == NULL) {
+      LOG_INFO("memfd_create not supported; disabling dual mapping of code.\n");
+      FLAG_dual_map_code = false;
+      return;
+    }
+    void* region = reinterpret_cast<void*>(vm->region_.start());
+    void* alias = reinterpret_cast<void*>(vm->alias_.start());
+    if (region == alias ||
+        mprotect(region, size, PROT_READ) != 0 ||  // Remove PROT_WRITE.
+        mprotect(alias, size, PROT_READ | PROT_EXEC) != 0) {  // Add PROT_EXEC.
+      LOG_INFO("mprotect fails; disabling dual mapping of code.\n");
+      FLAG_dual_map_code = false;
+    }
+    delete vm;
+  }
+#endif  // defined(DUAL_MAPPING_SUPPORTED)
 }
 
 static void unmap(uword start, uword end) {
@@ -45,17 +82,110 @@
   }
 }
 
+#if defined(DUAL_MAPPING_SUPPORTED)
+// Do not leak file descriptors to child processes.
+#if !defined(MFD_CLOEXEC)
+#define MFD_CLOEXEC 0x0001U
+#endif
+
+// Wrapper to call memfd_create syscall.
+static inline int memfd_create(const char* name, unsigned int flags) {
+#if !defined(__NR_memfd_create)
+  errno = ENOSYS;
+  return -1;
+#else
+  return syscall(__NR_memfd_create, name, flags);
+#endif
+}
+
+static void* MapAligned(int fd,
+                        int prot,
+                        intptr_t size,
+                        intptr_t alignment,
+                        intptr_t allocated_size) {
+  void* address =
+      mmap(NULL, allocated_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  LOG_INFO("mmap(NULL, 0x%" Px ", PROT_NONE, ...): %p\n", allocated_size,
+           address);
+  if (address == MAP_FAILED) {
+    return NULL;
+  }
+
+  const uword base = reinterpret_cast<uword>(address);
+  const uword aligned_base = Utils::RoundUp(base, alignment);
+
+  // Guarantee the alignment by mapping at a fixed address inside the above
+  // mapping. Overlapping region will be automatically discarded in the above
+  // mapping. Manually discard non-overlapping regions.
+  address = mmap(reinterpret_cast<void*>(aligned_base), size, prot,
+                 MAP_SHARED | MAP_FIXED, fd, 0);
+  LOG_INFO("mmap(0x%" Px ", 0x%" Px ", %u, ...): %p\n", aligned_base, size,
+           prot, address);
+  if (address == MAP_FAILED) {
+    unmap(base, base + allocated_size);
+    return NULL;
+  }
+  ASSERT(address == reinterpret_cast<void*>(aligned_base));
+  unmap(base, aligned_base);
+  unmap(aligned_base + size, base + allocated_size);
+  return address;
+}
+#endif  // defined(DUAL_MAPPING_SUPPORTED)
+
 VirtualMemory* VirtualMemory::AllocateAligned(intptr_t size,
                                               intptr_t alignment,
                                               bool is_executable,
                                               const char* name) {
+  // When FLAG_write_protect_code is active, code memory (indicated by
+  // is_executable = true) is allocated as non-executable and later
+  // changed to executable via VirtualMemory::Protect.
   ASSERT(Utils::IsAligned(size, page_size_));
   ASSERT(Utils::IsPowerOfTwo(alignment));
   ASSERT(Utils::IsAligned(alignment, page_size_));
   const intptr_t allocated_size = size + alignment - page_size_;
-  const int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
+#if defined(DUAL_MAPPING_SUPPORTED)
+  int fd = -1;
+  const bool dual_mapping =
+      is_executable && FLAG_write_protect_code && FLAG_dual_map_code;
+  if (dual_mapping) {
+    fd = memfd_create("dart_vm", MFD_CLOEXEC);
+    if (fd == -1) {
+      return NULL;
+    }
+    if (ftruncate(fd, size) == -1) {
+      close(fd);
+      return NULL;
+    }
+    const int region_prot = PROT_READ | PROT_WRITE;
+    void* region_ptr =
+        MapAligned(fd, region_prot, size, alignment, allocated_size);
+    if (region_ptr == NULL) {
+      close(fd);
+      return NULL;
+    }
+    MemoryRegion region(region_ptr, size);
+    // PROT_EXEC is added later via VirtualMemory::Protect.
+    const int alias_prot = PROT_READ;
+    void* alias_ptr =
+        MapAligned(fd, alias_prot, size, alignment, allocated_size);
+    close(fd);
+    if (alias_ptr == NULL) {
+      const uword region_base = reinterpret_cast<uword>(region_ptr);
+      unmap(region_base, region_base + size);
+      return NULL;
+    }
+    ASSERT(region_ptr != alias_ptr);
+    MemoryRegion alias(alias_ptr, size);
+    return new VirtualMemory(region, alias, region);
+  }
+#endif  // defined(DUAL_MAPPING_SUPPORTED)
+  const int prot =
+      PROT_READ | PROT_WRITE |
+      ((is_executable && !FLAG_write_protect_code) ? PROT_EXEC : 0);
   void* address =
-      mmap(NULL, allocated_size, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
+      mmap(NULL, allocated_size, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  LOG_INFO("mmap(NULL, 0x%" Px ", %u, ...): %p\n", allocated_size, prot,
+           address);
   if (address == MAP_FAILED) {
     return NULL;
   }
@@ -73,6 +203,10 @@
 VirtualMemory::~VirtualMemory() {
   if (vm_owns_region()) {
     unmap(reserved_.start(), reserved_.end());
+    const intptr_t alias_offset = AliasOffset();
+    if (alias_offset != 0) {
+      unmap(reserved_.start() + alias_offset, reserved_.end() + alias_offset);
+    }
   }
 }
 
@@ -114,11 +248,15 @@
     int error = errno;
     const int kBufferSize = 1024;
     char error_buf[kBufferSize];
+    LOG_INFO("mprotect(0x%" Px ", 0x%" Px ", %u) failed\n", page_address,
+             end_address - page_address, prot);
     FATAL2("mprotect error: %d (%s)", error,
            Utils::StrError(error, error_buf, kBufferSize));
   }
+  LOG_INFO("mprotect(0x%" Px ", 0x%" Px ", %u) ok\n", page_address,
+           end_address - page_address, prot);
 }
 
 }  // namespace dart
 
-#endif  // defined(HOST_OS_ANDROID) || defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS)
+#endif  // defined(HOST_OS_ANDROID ... HOST_OS_LINUX ... HOST_OS_MACOS)
diff --git a/runtime/vm/virtual_memory_win.cc b/runtime/vm/virtual_memory_win.cc
index 9c917b3..3ec743f0 100644
--- a/runtime/vm/virtual_memory_win.cc
+++ b/runtime/vm/virtual_memory_win.cc
@@ -14,6 +14,8 @@
 
 namespace dart {
 
+DECLARE_FLAG(bool, write_protect_code);
+
 uword VirtualMemory::page_size_ = 0;
 
 void VirtualMemory::Init() {
@@ -26,11 +28,16 @@
                                               intptr_t alignment,
                                               bool is_executable,
                                               const char* name) {
+  // When FLAG_write_protect_code is active, code memory (indicated by
+  // is_executable = true) is allocated as non-executable and later
+  // changed to executable via VirtualMemory::Protect.
   ASSERT(Utils::IsAligned(size, page_size_));
   ASSERT(Utils::IsPowerOfTwo(alignment));
   ASSERT(Utils::IsAligned(alignment, page_size_));
   intptr_t reserved_size = size + alignment - page_size_;
-  int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
+  int prot = (is_executable && !FLAG_write_protect_code)
+                 ? PAGE_EXECUTE_READWRITE
+                 : PAGE_READWRITE;
   void* address = VirtualAlloc(NULL, reserved_size, MEM_RESERVE, prot);
   if (address == NULL) {
     return NULL;
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index 717b50c..4081d35 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -373,6 +373,7 @@
   "bitfield_test.cc",
   "bitmap_test.cc",
   "boolfield_test.cc",
+  "catch_entry_moves_test.cc",
   "class_finalizer_test.cc",
   "code_descriptors_test.cc",
   "code_patcher_arm64_test.cc",
diff --git a/samples/ffi/dylib_utils.dart b/samples/ffi/dylib_utils.dart
index 1929961..1c924d4 100644
--- a/samples/ffi/dylib_utils.dart
+++ b/samples/ffi/dylib_utils.dart
@@ -9,6 +9,7 @@
   if (path == null) path = "";
   if (Platform.isLinux) return path + "lib" + name + ".so";
   if (Platform.isMacOS) return path + "lib" + name + ".dylib";
+  if (Platform.isWindows) return path + name + ".dll";
   throw Exception("Platform not implemented");
 }
 
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 3f48b0a..50c2682 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -495,6 +495,16 @@
   ]
 }
 
+copy("copy_abi_dill_files") {
+  visibility = [ ":create_common_sdk" ]
+  sources = [
+    "../tools/abiversions",
+  ]
+  outputs = [
+    "$root_out_dir/dart-sdk/lib/_internal/abiversions",
+  ]
+}
+
 copy("copy_dart2js_dill_files") {
   visibility = [ ":create_full_sdk" ]
   deps = [
@@ -889,6 +899,7 @@
 group("create_common_sdk") {
   visibility = [ ":create_sdk" ]
   public_deps = [
+    ":copy_abi_dill_files",
     ":copy_analysis_summaries",
     ":copy_api_readme",
     ":copy_dart",
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index 045a2f1..e31fe29 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -2662,7 +2662,9 @@
     var resultBits = new Uint8List(8);
 
     var length = _digitBits * (_used - 1) + _digits[_used - 1].bitLength;
-    if (length - 53 > maxDoubleExponent) return double.infinity;
+    if (length > maxDoubleExponent + 53) {
+      return _isNegative ? double.negativeInfinity : double.infinity;
+    }
 
     // The most significant bit is for the sign.
     if (_isNegative) resultBits[7] = 0x80;
diff --git a/sdk/lib/_internal/js_runtime/lib/js_string.dart b/sdk/lib/_internal/js_runtime/lib/js_string.dart
index b5be305..39370d7 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_string.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_string.dart
@@ -59,8 +59,7 @@
   }
 
   String replaceAll(Pattern from, String to) {
-    checkString(to);
-    return stringReplaceAllUnchecked(this, from, to);
+    return stringReplaceAllUnchecked(this, from, checkString(to));
   }
 
   String replaceAllMapped(Pattern from, String convert(Match match)) {
diff --git a/sdk/lib/_internal/js_runtime/lib/math_patch.dart b/sdk/lib/_internal/js_runtime/lib/math_patch.dart
index a3d3fc9..677953e 100644
--- a/sdk/lib/_internal/js_runtime/lib/math_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/math_patch.dart
@@ -63,14 +63,14 @@
 
 @patch
 class Random {
-  static final _secureRandom = new _JSSecureRandom();
+  static Random _secureRandom;
 
   @patch
   factory Random([int seed]) =>
       (seed == null) ? const _JSRandom() : new _Random(seed);
 
   @patch
-  factory Random.secure() => _secureRandom;
+  factory Random.secure() => _secureRandom ??= _JSSecureRandom();
 }
 
 class _JSRandom implements Random {
diff --git a/sdk/lib/_internal/js_runtime/lib/string_helper.dart b/sdk/lib/_internal/js_runtime/lib/string_helper.dart
index 0180369..ea5374e 100644
--- a/sdk/lib/_internal/js_runtime/lib/string_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/string_helper.dart
@@ -117,12 +117,23 @@
   }
 }
 
-stringReplaceJS(receiver, replacer, replacement) {
-  // The JavaScript String.replace method recognizes replacement
-  // patterns in the replacement string. Dart does not have that
-  // behavior.
-  replacement = JS('String', r'#.replace(/\$/g, "$$$$")', replacement);
-  return JS('String', r'#.replace(#, #)', receiver, replacer, replacement);
+String stringReplaceJS(String receiver, jsRegExp, String replacement) {
+  return JS('String', r'#.replace(#, #)', receiver, jsRegExp,
+      escapeReplacement(replacement));
+}
+
+String escapeReplacement(String replacement) {
+  // The JavaScript `String.prototype.replace` method recognizes replacement
+  // patterns in the replacement string. Dart does not have that behavior, so
+  // the replacement patterns need to be escaped.
+
+  // `String.prototype.replace` tends to be slower when there are replacement
+  // patterns, and the escaping itself uses replacement patterns, so it is
+  // worthwhile checking for `$` first.
+  if (stringContainsStringUnchecked(replacement, r'$', 0)) {
+    return JS('String', r'#.replace(/\$/g, "$$$$")', replacement);
+  }
+  return replacement;
 }
 
 stringReplaceFirstRE(receiver, regexp, replacement, startIndex) {
@@ -136,38 +147,73 @@
 /// Returns a string for a RegExp pattern that matches [string]. This is done by
 /// escaping all RegExp metacharacters.
 quoteStringForRegExp(string) {
-  return JS('String', r'#.replace(/[[\]{}()*+?.\\^$|]/g, "\\$&")', string);
+  // We test and replace essentially the same RegExp because replacement when
+  // there are replacement patterns is slow enough to be worth avoiding.
+  if (JS('bool', r'/[[\]{}()*+?.\\^$|]/.test(#)', string)) {
+    return JS('String', r'#.replace(/[[\]{}()*+?.\\^$|]/g, "\\$&")', string);
+  }
+  return string;
 }
 
 stringReplaceAllUnchecked(receiver, pattern, replacement) {
   checkString(replacement);
   if (pattern is String) {
-    if (pattern == "") {
-      if (receiver == "") {
-        return JS('String', '#', replacement); // help type inference.
-      } else {
-        StringBuffer result = new StringBuffer('');
-        int length = receiver.length;
-        result.write(replacement);
-        for (int i = 0; i < length; i++) {
-          result.write(receiver[i]);
-          result.write(replacement);
-        }
-        return result.toString();
-      }
-    } else {
-      var quoted = quoteStringForRegExp(pattern);
-      var replacer = JS('', "new RegExp(#, 'g')", quoted);
-      return stringReplaceJS(receiver, replacer, replacement);
-    }
-  } else if (pattern is JSSyntaxRegExp) {
+    return stringReplaceAllUncheckedString(receiver, pattern, replacement);
+  }
+
+  if (pattern is JSSyntaxRegExp) {
     var re = regExpGetGlobalNative(pattern);
     return stringReplaceJS(receiver, re, replacement);
-  } else {
-    checkNull(pattern);
-    // TODO(floitsch): implement generic String.replace (with patterns).
-    throw "String.replaceAll(Pattern) UNIMPLEMENTED";
   }
+
+  checkNull(pattern);
+  // TODO(floitsch): implement generic String.replace (with patterns).
+  throw "String.replaceAll(Pattern) UNIMPLEMENTED";
+}
+
+/// Replaces all non-overlapping occurences of [pattern] in [receiver] with
+/// [replacement].  This should be replace with
+/// (String.prototype.replaceAll)[https://github.com/tc39/proposal-string-replace-all]
+/// when available.
+String stringReplaceAllUncheckedString(
+    String receiver, String pattern, String replacement) {
+  if (pattern == "") {
+    if (receiver == "") {
+      return JS('String', '#', replacement); // help type inference.
+    }
+    StringBuffer result = new StringBuffer('');
+    int length = receiver.length;
+    result.write(replacement);
+    for (int i = 0; i < length; i++) {
+      result.write(receiver[i]);
+      result.write(replacement);
+    }
+    return result.toString();
+  }
+
+  if (!const bool.fromEnvironment(
+      'dart2js.testing.String.replaceAll.force.regexp')) {
+    // First check for no match.
+    int index = stringIndexOfStringUnchecked(receiver, pattern, 0);
+    if (index < 0) return receiver;
+
+    // The fastest approach in general is to replace with a global RegExp, but
+    // this requires the receiver string to be long enough to amortize the cost
+    // of creating the RegExp, and the replacement to have no '$' patterns,
+    // which tend to make `String.prototype.replace` much slower. In these
+    // cases, using split-join usually wins.
+    if (receiver.length < 500 ||
+        stringContainsStringUnchecked(replacement, r'$', 0)) {
+      return stringReplaceAllUsingSplitJoin(receiver, pattern, replacement);
+    }
+  }
+  var quoted = quoteStringForRegExp(pattern);
+  var replacer = JS('', "new RegExp(#, 'g')", quoted);
+  return stringReplaceJS(receiver, replacer, replacement);
+}
+
+String stringReplaceAllUsingSplitJoin(receiver, pattern, replacement) {
+  return JS('String', '#.split(#).join(#)', receiver, pattern, replacement);
 }
 
 String _matchString(Match match) => match[0];
diff --git a/sdk/lib/collection/collection.dart b/sdk/lib/collection/collection.dart
index 7c667ec..b050a48 100644
--- a/sdk/lib/collection/collection.dart
+++ b/sdk/lib/collection/collection.dart
@@ -2,15 +2,13 @@
 // 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.
 
-/**
- * Classes and utilities that supplement the collection support in dart:core.
- *
- * To use this library in your code:
- *
- *     import 'dart:collection';
- *
- * {@category Core}
- */
+/// Classes and utilities that supplement the collection support in dart:core.
+///
+/// To use this library in your code:
+///
+///     import 'dart:collection';
+///
+/// {@category Core}
 library dart.collection;
 
 import 'dart:_internal' hide Symbol;
diff --git a/sdk/lib/collection/collections.dart b/sdk/lib/collection/collections.dart
index d02257b..9b43996 100644
--- a/sdk/lib/collection/collections.dart
+++ b/sdk/lib/collection/collections.dart
@@ -4,24 +4,20 @@
 
 part of dart.collection;
 
-/**
- * An unmodifiable [List] view of another List.
- *
- * The source of the elements may be a [List] or any [Iterable] with
- * efficient [Iterable.length] and [Iterable.elementAt].
- */
+/// An unmodifiable [List] view of another List.
+///
+/// The source of the elements may be a [List] or any [Iterable] with
+/// efficient [Iterable.length] and [Iterable.elementAt].
 class UnmodifiableListView<E> extends UnmodifiableListBase<E> {
   final Iterable<E> _source;
 
-  /**
-   * Creates an unmodifiable list backed by [source].
-   *
-   * The [source] of the elements may be a [List] or any [Iterable] with
-   * efficient [Iterable.length] and [Iterable.elementAt].
-   */
+  /// Creates an unmodifiable list backed by [source].
+  ///
+  /// The [source] of the elements may be a [List] or any [Iterable] with
+  /// efficient [Iterable.length] and [Iterable.elementAt].
   UnmodifiableListView(Iterable<E> source) : _source = source;
 
-  List<R> cast<R>() => new UnmodifiableListView(_source.cast<R>());
+  List<R> cast<R>() => UnmodifiableListView(_source.cast<R>());
   int get length => _source.length;
 
   E operator [](int index) => _source.elementAt(index);
diff --git a/sdk/lib/collection/hash_map.dart b/sdk/lib/collection/hash_map.dart
index 728ff9e6..525f43a 100644
--- a/sdk/lib/collection/hash_map.dart
+++ b/sdk/lib/collection/hash_map.dart
@@ -4,165 +4,152 @@
 
 part of dart.collection;
 
-/** Default function for equality comparison in customized HashMaps */
+/// Default function for equality comparison in customized HashMaps
 bool _defaultEquals(a, b) => a == b;
-/** Default function for hash-code computation in customized HashMaps */
+
+/// Default function for hash-code computation in customized HashMaps
 int _defaultHashCode(a) => a.hashCode;
 
-/** Type of custom equality function */
-typedef bool _Equality<K>(K a, K b);
-/** Type of custom hash code function. */
-typedef int _Hasher<K>(K object);
+/// Type of custom equality function
+typedef _Equality<K> = bool Function(K a, K b);
 
-/**
- * A hash-table based implementation of [Map].
- *
- * The keys of a `HashMap` must have consistent [Object.==]
- * and [Object.hashCode] implementations. This means that the `==` operator
- * must define a stable equivalence relation on the keys (reflexive,
- * symmetric, transitive, and consistent over time), and that `hashCode`
- * must be the same for objects that are considered equal by `==`.
- *
- * The map allows `null` as a key.
- *
- * Iterating the map's keys, values or entries (through [forEach])
- * may happen in any order.
- * The iteration order only changes when the map is modified.
- * Values are iterated in the same order as their associated keys,
- * so iterating the [keys] and [values] in parallel
- * will give matching key and value pairs.
- */
+/// Type of custom hash code function.
+typedef _Hasher<K> = int Function(K object);
+
+/// A hash-table based implementation of [Map].
+///
+/// The keys of a `HashMap` must have consistent [Object.==]
+/// and [Object.hashCode] implementations. This means that the `==` operator
+/// must define a stable equivalence relation on the keys (reflexive,
+/// symmetric, transitive, and consistent over time), and that `hashCode`
+/// must be the same for objects that are considered equal by `==`.
+///
+/// The map allows `null` as a key.
+///
+/// Iterating the map's keys, values or entries (through [forEach])
+/// may happen in any order.
+/// The iteration order only changes when the map is modified.
+/// Values are iterated in the same order as their associated keys,
+/// so iterating the [keys] and [values] in parallel
+/// will give matching key and value pairs.
 abstract class HashMap<K, V> implements Map<K, V> {
-  /**
-   * Creates an unordered hash-table based [Map].
-   *
-   * The created map is not ordered in any way. When iterating the keys or
-   * values, the iteration order is unspecified except that it will stay the
-   * same as long as the map isn't changed.
-   *
-   * If [equals] is provided, it is used to compare the keys in the table with
-   * new keys. If [equals] is omitted, the key's own [Object.==] is used
-   * instead.
-   *
-   * Similar, if [hashCode] is provided, it is used to produce a hash value
-   * for keys in order to place them in the hash table. If it is omitted, the
-   * key's own [Object.hashCode] is used.
-   *
-   * If using methods like [operator []], [remove] and [containsKey] together
-   * with a custom equality and hashcode, an extra `isValidKey` function
-   * can be supplied. This function is called before calling [equals] or
-   * [hashCode] with an argument that may not be a [K] instance, and if the
-   * call returns false, the key is assumed to not be in the set.
-   * The [isValidKey] function defaults to just testing if the object is a
-   * [K] instance.
-   *
-   * Example:
-   *
-   *     new HashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
-   *                          hashCode: (int e) => e % 5)
-   *
-   * This example map does not need an `isValidKey` function to be passed.
-   * The default function accepts only `int` values, which can safely be
-   * passed to both the `equals` and `hashCode` functions.
-   *
-   * If neither `equals`, `hashCode`, nor `isValidKey` is provided,
-   * the default `isValidKey` instead accepts all keys.
-   * The default equality and hashcode operations are assumed to work on all
-   * objects.
-   *
-   * Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
-   * and `isValidKey` is omitted, the resulting map is identity based,
-   * and the `isValidKey` defaults to accepting all keys.
-   * Such a map can be created directly using [HashMap.identity].
-   *
-   * The used `equals` and `hashCode` method should always be consistent,
-   * so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash
-   * of an object, or what it compares equal to, should not change while the
-   * object is a key in the map. If it does change, the result is unpredictable.
-   *
-   * If you supply one of [equals] and [hashCode],
-   * you should generally also to supply the other.
-   */
+  /// Creates an unordered hash-table based [Map].
+  ///
+  /// The created map is not ordered in any way. When iterating the keys or
+  /// values, the iteration order is unspecified except that it will stay the
+  /// same as long as the map isn't changed.
+  ///
+  /// If [equals] is provided, it is used to compare the keys in the table with
+  /// new keys. If [equals] is omitted, the key's own [Object.==] is used
+  /// instead.
+  ///
+  /// Similar, if [hashCode] is provided, it is used to produce a hash value
+  /// for keys in order to place them in the hash table. If it is omitted, the
+  /// key's own [Object.hashCode] is used.
+  ///
+  /// If using methods like [operator []], [remove] and [containsKey] together
+  /// with a custom equality and hashcode, an extra `isValidKey` function
+  /// can be supplied. This function is called before calling [equals] or
+  /// [hashCode] with an argument that may not be a [K] instance, and if the
+  /// call returns false, the key is assumed to not be in the set.
+  /// The [isValidKey] function defaults to just testing if the object is a
+  /// [K] instance.
+  ///
+  /// Example:
+  ///
+  ///     new HashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
+  ///                          hashCode: (int e) => e % 5)
+  ///
+  /// This example map does not need an `isValidKey` function to be passed.
+  /// The default function accepts only `int` values, which can safely be
+  /// passed to both the `equals` and `hashCode` functions.
+  ///
+  /// If neither `equals`, `hashCode`, nor `isValidKey` is provided,
+  /// the default `isValidKey` instead accepts all keys.
+  /// The default equality and hashcode operations are assumed to work on all
+  /// objects.
+  ///
+  /// Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
+  /// and `isValidKey` is omitted, the resulting map is identity based,
+  /// and the `isValidKey` defaults to accepting all keys.
+  /// Such a map can be created directly using [HashMap.identity].
+  ///
+  /// The used `equals` and `hashCode` method should always be consistent,
+  /// so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash
+  /// of an object, or what it compares equal to, should not change while the
+  /// object is a key in the map. If it does change, the result is
+  /// unpredictable.
+  ///
+  /// If you supply one of [equals] and [hashCode],
+  /// you should generally also to supply the other.
   external factory HashMap(
       {bool equals(K key1, K key2),
       int hashCode(K key),
       bool isValidKey(potentialKey)});
 
-  /**
-   * Creates an unordered identity-based map.
-   *
-   * Effectively a shorthand for:
-   *
-   *     new HashMap<K, V>(equals: identical,
-   *                       hashCode: identityHashCode)
-   */
+  /// Creates an unordered identity-based map.
+  ///
+  /// Effectively a shorthand for:
+  ///
+  ///     new HashMap<K, V>(equals: identical,
+  ///                       hashCode: identityHashCode)
   external factory HashMap.identity();
 
-  /**
-   * Creates a [HashMap] that contains all key/value pairs of [other].
-   *
-   * The keys must all be instances of [K] and the values of [V].
-   * The [other] map itself can have any type.
-   */
+  /// Creates a [HashMap] that contains all key/value pairs of [other].
+  ///
+  /// The keys must all be instances of [K] and the values of [V].
+  /// The [other] map itself can have any type.
   factory HashMap.from(Map other) {
-    Map<K, V> result = new HashMap<K, V>();
+    Map<K, V> result = HashMap<K, V>();
     other.forEach((k, v) {
       result[k] = v;
     });
     return result;
   }
 
-  /**
-   * Creates a [HashMap] that contains all key/value pairs of [other].
-   */
-  factory HashMap.of(Map<K, V> other) => new HashMap<K, V>()..addAll(other);
+  /// Creates a [HashMap] that contains all key/value pairs of [other].
+  factory HashMap.of(Map<K, V> other) => HashMap<K, V>()..addAll(other);
 
-  /**
-   * Creates a [HashMap] where the keys and values are computed from the
-   * [iterable].
-   *
-   * For each element of the [iterable] this constructor computes a key/value
-   * pair, by applying [key] and [value] respectively.
-   *
-   * The keys of the key/value pairs do not need to be unique. The last
-   * occurrence of a key will simply overwrite any previous value.
-   *
-   * If no values are specified for [key] and [value] the default is the
-   * identity function.
-   */
+  /// Creates a [HashMap] where the keys and values are computed from the
+  /// [iterable].
+  ///
+  /// For each element of the [iterable] this constructor computes a key/value
+  /// pair, by applying [key] and [value] respectively.
+  ///
+  /// The keys of the key/value pairs do not need to be unique. The last
+  /// occurrence of a key will simply overwrite any previous value.
+  ///
+  /// If no values are specified for [key] and [value] the default is the
+  /// identity function.
   factory HashMap.fromIterable(Iterable iterable,
       {K key(element), V value(element)}) {
-    Map<K, V> map = new HashMap<K, V>();
+    Map<K, V> map = HashMap<K, V>();
     MapBase._fillMapWithMappedIterable(map, iterable, key, value);
     return map;
   }
 
-  /**
-   * Creates a [HashMap] associating the given [keys] to [values].
-   *
-   * This constructor iterates over [keys] and [values] and maps each element of
-   * [keys] to the corresponding element of [values].
-   *
-   * If [keys] contains the same object multiple times, the last occurrence
-   * overwrites the previous value.
-   *
-   * It is an error if the two [Iterable]s don't have the same length.
-   */
+  /// Creates a [HashMap] associating the given [keys] to [values].
+  ///
+  /// This constructor iterates over [keys] and [values] and maps each element
+  /// of [keys] to the corresponding element of [values].
+  ///
+  /// If [keys] contains the same object multiple times, the last occurrence
+  /// overwrites the previous value.
+  ///
+  /// It is an error if the two [Iterable]s don't have the same length.
   factory HashMap.fromIterables(Iterable<K> keys, Iterable<V> values) {
-    Map<K, V> map = new HashMap<K, V>();
+    Map<K, V> map = HashMap<K, V>();
     MapBase._fillMapWithIterables(map, keys, values);
     return map;
   }
 
-  /**
-   * Creates a [HashMap] containing the entries of [entries].
-   *
-   * Returns a new `HashMap<K, V>` where all entries of [entries]
-   * have been added in iteration order.
-   *
-   * If multiple [entries] have the same key,
-   * later occurrences overwrite the earlier ones.
-   */
+  /// Creates a [HashMap] containing the entries of [entries].
+  ///
+  /// Returns a new `HashMap<K, V>` where all entries of [entries]
+  /// have been added in iteration order.
+  ///
+  /// If multiple [entries] have the same key,
+  /// later occurrences overwrite the earlier ones.
   @Since("2.1")
   factory HashMap.fromEntries(Iterable<MapEntry<K, V>> entries) =>
       HashMap<K, V>()..addEntries(entries);
diff --git a/sdk/lib/collection/hash_set.dart b/sdk/lib/collection/hash_set.dart
index d93e550..3fd00fe 100644
--- a/sdk/lib/collection/hash_set.dart
+++ b/sdk/lib/collection/hash_set.dart
@@ -4,125 +4,112 @@
 
 part of dart.collection;
 
-/**
- * An unordered hash-table based [Set] implementation.
- *
- * The elements of a `HashSet` must have consistent equality
- * and hashCode implementations. This means that the equals operation
- * must define a stable equivalence relation on the elements (reflexive,
- * symmetric, transitive, and consistent over time), and that the hashCode
- * must consistent with equality, so that the same for objects that are
- * considered equal.
- *
- * The set allows `null` as an element.
- *
- * Most simple operations on `HashSet` are done in (potentially amortized)
- * constant time: [add], [contains], [remove], and [length], provided the hash
- * codes of objects are well distributed.
- *
- * The iteration order of the set is not specified and depends on
- * the hashcodes of the provided elements. However, the order is stable:
- * multiple iterations over the same set produce the same order, as long as
- * the set is not modified.
- */
+/// An unordered hash-table based [Set] implementation.
+///
+/// The elements of a `HashSet` must have consistent equality
+/// and hashCode implementations. This means that the equals operation
+/// must define a stable equivalence relation on the elements (reflexive,
+/// symmetric, transitive, and consistent over time), and that the hashCode
+/// must consistent with equality, so that the same for objects that are
+/// considered equal.
+///
+/// The set allows `null` as an element.
+///
+/// Most simple operations on `HashSet` are done in (potentially amortized)
+/// constant time: [add], [contains], [remove], and [length], provided the hash
+/// codes of objects are well distributed.
+///
+/// The iteration order of the set is not specified and depends on
+/// the hashcodes of the provided elements. However, the order is stable:
+/// multiple iterations over the same set produce the same order, as long as
+/// the set is not modified.
 abstract class HashSet<E> implements Set<E> {
-  /**
-   * Create a hash set using the provided [equals] as equality.
-   *
-   * The provided [equals] must define a stable equivalence relation, and
-   * [hashCode] must be consistent with [equals]. If the [equals] or [hashCode]
-   * methods won't work on all objects, but only on some instances of E, the
-   * [isValidKey] predicate can be used to restrict the keys that the functions
-   * are applied to.
-   * Any key for which [isValidKey] returns false is automatically assumed
-   * to not be in the set when asking `contains`.
-   *
-   * If [equals] or [hashCode] are omitted, the set uses
-   * the elements' intrinsic [Object.==] and [Object.hashCode].
-   *
-   * If you supply one of [equals] and [hashCode],
-   * you should generally also to supply the other.
-   *
-   * If the supplied `equals` or `hashCode` functions won't work on all [E]
-   * objects, and the map will be used in a setting where a non-`E` object
-   * is passed to, e.g., `contains`, then the [isValidKey] function should
-   * also be supplied.
-   *
-   * If [isValidKey] is omitted, it defaults to testing if the object is an
-   * [E] instance. That means that:
-   *
-   *     new HashSet<int>(equals: (int e1, int e2) => (e1 - e2) % 5 == 0,
-   *                      hashCode: (int e) => e % 5)
-   *
-   * does not need an `isValidKey` argument, because it defaults to only
-   * accepting `int` values which are accepted by both `equals` and `hashCode`.
-   *
-   * If neither `equals`, `hashCode`, nor `isValidKey` is provided,
-   * the default `isValidKey` instead accepts all values.
-   * The default equality and hashcode operations are assumed to work on all
-   * objects.
-   *
-   * Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
-   * and `isValidKey` is omitted, the resulting set is identity based,
-   * and the `isValidKey` defaults to accepting all keys.
-   * Such a map can be created directly using [HashSet.identity].
-   */
+  /// Create a hash set using the provided [equals] as equality.
+  ///
+  /// The provided [equals] must define a stable equivalence relation, and
+  /// [hashCode] must be consistent with [equals]. If the [equals] or [hashCode]
+  /// methods won't work on all objects, but only on some instances of E, the
+  /// [isValidKey] predicate can be used to restrict the keys that the functions
+  /// are applied to.
+  /// Any key for which [isValidKey] returns false is automatically assumed
+  /// to not be in the set when asking `contains`.
+  ///
+  /// If [equals] or [hashCode] are omitted, the set uses
+  /// the elements' intrinsic [Object.==] and [Object.hashCode].
+  ///
+  /// If you supply one of [equals] and [hashCode],
+  /// you should generally also to supply the other.
+  ///
+  /// If the supplied `equals` or `hashCode` functions won't work on all [E]
+  /// objects, and the map will be used in a setting where a non-`E` object
+  /// is passed to, e.g., `contains`, then the [isValidKey] function should
+  /// also be supplied.
+  ///
+  /// If [isValidKey] is omitted, it defaults to testing if the object is an
+  /// [E] instance. That means that:
+  ///
+  ///     new HashSet<int>(equals: (int e1, int e2) => (e1 - e2) % 5 == 0,
+  ///                      hashCode: (int e) => e % 5)
+  ///
+  /// does not need an `isValidKey` argument, because it defaults to only
+  /// accepting `int` values which are accepted by both `equals` and `hashCode`.
+  ///
+  /// If neither `equals`, `hashCode`, nor `isValidKey` is provided,
+  /// the default `isValidKey` instead accepts all values.
+  /// The default equality and hashcode operations are assumed to work on all
+  /// objects.
+  ///
+  /// Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
+  /// and `isValidKey` is omitted, the resulting set is identity based,
+  /// and the `isValidKey` defaults to accepting all keys.
+  /// Such a map can be created directly using [HashSet.identity].
   external factory HashSet(
       {bool equals(E e1, E e2),
       int hashCode(E e),
       bool isValidKey(potentialKey)});
 
-  /**
-   * Creates an unordered identity-based set.
-   *
-   * Effectively a shorthand for:
-   *
-   *     new HashSet<E>(equals: identical,
-   *                    hashCode: identityHashCode)
-   */
+  /// Creates an unordered identity-based set.
+  ///
+  /// Effectively a shorthand for:
+  ///
+  ///     new HashSet<E>(equals: identical,
+  ///                    hashCode: identityHashCode)
   external factory HashSet.identity();
 
-  /**
-   * Create a hash set containing all [elements].
-   *
-   * Creates a hash set as by `new HashSet<E>()` and adds all given [elements]
-   * to the set. The elements are added in order. If [elements] contains
-   * two entries that are equal, but not identical, then the first one is
-   * the one in the resulting set.
-   *
-   * All the [elements] should be instances of [E].
-   * The `elements` iterable itself may have any element type, so this
-   * constructor can be used to down-cast a `Set`, for example as:
-   * ```dart
-   * Set<SuperType> superSet = ...;
-   * Set<SubType> subSet =
-   *     new HashSet<SubType>.from(superSet.whereType<SubType>());
-   * ```
-   */
+  /// Create a hash set containing all [elements].
+  ///
+  /// Creates a hash set as by `new HashSet<E>()` and adds all given [elements]
+  /// to the set. The elements are added in order. If [elements] contains
+  /// two entries that are equal, but not identical, then the first one is
+  /// the one in the resulting set.
+  ///
+  /// All the [elements] should be instances of [E].
+  /// The `elements` iterable itself may have any element type, so this
+  /// constructor can be used to down-cast a `Set`, for example as:
+  /// ```dart
+  /// Set<SuperType> superSet = ...;
+  /// Set<SubType> subSet =
+  ///     new HashSet<SubType>.from(superSet.whereType<SubType>());
+  /// ```
   factory HashSet.from(Iterable elements) {
-    HashSet<E> result = new HashSet<E>();
+    HashSet<E> result = HashSet<E>();
     for (final e in elements) {
       result.add(e);
     }
     return result;
   }
 
-  /**
-   * Create a hash set containing all [elements].
-   *
-   * Creates a hash set as by `new HashSet<E>()` and adds all given [elements]
-   * to the set. The elements are added in order. If [elements] contains
-   * two entries that are equal, but not identical, then the first one is
-   * the one in the resulting set.
-   */
-  factory HashSet.of(Iterable<E> elements) =>
-      new HashSet<E>()..addAll(elements);
+  /// Create a hash set containing all [elements].
+  ///
+  /// Creates a hash set as by `new HashSet<E>()` and adds all given [elements]
+  /// to the set. The elements are added in order. If [elements] contains
+  /// two entries that are equal, but not identical, then the first one is
+  /// the one in the resulting set.
+  factory HashSet.of(Iterable<E> elements) => HashSet<E>()..addAll(elements);
 
-  /**
-   * Provides an iterator that iterates over the elements of this set.
-   *
-   * The order of iteration is unspecified,
-   * but consistent between changes to the set.
-   */
+  /// Provides an iterator that iterates over the elements of this set.
+  ///
+  /// The order of iteration is unspecified,
+  /// but consistent between changes to the set.
   Iterator<E> get iterator;
 }
diff --git a/sdk/lib/collection/iterable.dart b/sdk/lib/collection/iterable.dart
index b7b5497..14e7226 100644
--- a/sdk/lib/collection/iterable.dart
+++ b/sdk/lib/collection/iterable.dart
@@ -4,11 +4,9 @@
 
 part of dart.collection;
 
-/**
- * This [Iterable] mixin implements all [Iterable] members except `iterator`.
- *
- * All other methods are implemented in terms of `iterator`.
- */
+/// This [Iterable] mixin implements all [Iterable] members except `iterator`.
+///
+/// All other methods are implemented in terms of `iterator`.
 abstract class IterableMixin<E> implements Iterable<E> {
   // This class has methods copied verbatim into:
   // - IterableBase
@@ -16,23 +14,23 @@
   // If changing a method here, also change the other copies.
 
   Iterable<R> cast<R>() => Iterable.castFrom<E, R>(this);
-  Iterable<T> map<T>(T f(E element)) => new MappedIterable<E, T>(this, f);
+  Iterable<T> map<T>(T f(E element)) => MappedIterable<E, T>(this, f);
 
-  Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f);
+  Iterable<E> where(bool f(E element)) => WhereIterable<E>(this, f);
 
-  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+  Iterable<T> whereType<T>() => WhereTypeIterable<T>(this);
 
   Iterable<T> expand<T>(Iterable<T> f(E element)) =>
-      new ExpandIterable<E, T>(this, f);
+      ExpandIterable<E, T>(this, f);
 
   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 FollowedByIterable<E>.firstEfficient(self, other);
     }
-    return new FollowedByIterable<E>(this, other);
+    return FollowedByIterable<E>(this, other);
   }
 
   bool contains(Object element) {
@@ -74,7 +72,7 @@
   String join([String separator = ""]) {
     Iterator<E> iterator = this.iterator;
     if (!iterator.moveNext()) return "";
-    StringBuffer buffer = new StringBuffer();
+    StringBuffer buffer = StringBuffer();
     if (separator == null || separator == "") {
       do {
         buffer.write("${iterator.current}");
@@ -96,10 +94,10 @@
     return false;
   }
 
-  List<E> toList({bool growable: true}) =>
-      new List<E>.from(this, growable: growable);
+  List<E> toList({bool growable = true}) =>
+      List<E>.from(this, growable: growable);
 
-  Set<E> toSet() => new Set<E>.from(this);
+  Set<E> toSet() => Set<E>.from(this);
 
   int get length {
     assert(this is! EfficientLengthIterable);
@@ -116,19 +114,19 @@
   bool get isNotEmpty => !isEmpty;
 
   Iterable<E> take(int count) {
-    return new TakeIterable<E>(this, count);
+    return TakeIterable<E>(this, count);
   }
 
   Iterable<E> takeWhile(bool test(E value)) {
-    return new TakeWhileIterable<E>(this, test);
+    return TakeWhileIterable<E>(this, test);
   }
 
   Iterable<E> skip(int count) {
-    return new SkipIterable<E>(this, count);
+    return SkipIterable<E>(this, count);
   }
 
   Iterable<E> skipWhile(bool test(E value)) {
-    return new SkipWhileIterable<E>(this, test);
+    return SkipWhileIterable<E>(this, test);
   }
 
   E get first {
@@ -206,29 +204,25 @@
       if (index == elementIndex) return element;
       elementIndex++;
     }
-    throw new RangeError.index(index, this, "index", null, elementIndex);
+    throw RangeError.index(index, this, "index", null, elementIndex);
   }
 
   String toString() => IterableBase.iterableToShortString(this, '(', ')');
 }
 
-/**
- * Base class for implementing [Iterable].
- *
- * This class implements all methods of [Iterable], except [Iterable.iterator],
- * in terms of `iterator`.
- */
+/// Base class for implementing [Iterable].
+///
+/// This class implements all methods of [Iterable], except [Iterable.iterator],
+/// in terms of `iterator`.
 abstract class IterableBase<E> extends Iterable<E> {
   const IterableBase();
 
-  /**
-   * Convert an `Iterable` to a string like [IterableBase.toString].
-   *
-   * Allows using other delimiters than '(' and ')'.
-   *
-   * Handles circular references where converting one of the elements
-   * to a string ends up converting [iterable] to a string again.
-   */
+  /// Convert an `Iterable` to a string like [IterableBase.toString].
+  ///
+  /// Allows using other delimiters than '(' and ')'.
+  ///
+  /// Handles circular references where converting one of the elements
+  /// to a string ends up converting [iterable] to a string again.
   static String iterableToShortString(Iterable iterable,
       [String leftDelimiter = '(', String rightDelimiter = ')']) {
     if (_isToStringVisiting(iterable)) {
@@ -246,30 +240,28 @@
       assert(identical(_toStringVisiting.last, iterable));
       _toStringVisiting.removeLast();
     }
-    return (new StringBuffer(leftDelimiter)
+    return (StringBuffer(leftDelimiter)
           ..writeAll(parts, ", ")
           ..write(rightDelimiter))
         .toString();
   }
 
-  /**
-   * Converts an `Iterable` to a string.
-   *
-   * Converts each elements to a string, and separates the results by ", ".
-   * Then wraps the result in [leftDelimiter] and [rightDelimiter].
-   *
-   * Unlike [iterableToShortString], this conversion doesn't omit any
-   * elements or puts any limit on the size of the result.
-   *
-   * Handles circular references where converting one of the elements
-   * to a string ends up converting [iterable] to a string again.
-   */
+  /// Converts an `Iterable` to a string.
+  ///
+  /// Converts each elements to a string, and separates the results by ", ".
+  /// Then wraps the result in [leftDelimiter] and [rightDelimiter].
+  ///
+  /// Unlike [iterableToShortString], this conversion doesn't omit any
+  /// elements or puts any limit on the size of the result.
+  ///
+  /// Handles circular references where converting one of the elements
+  /// to a string ends up converting [iterable] to a string again.
   static String iterableToFullString(Iterable iterable,
       [String leftDelimiter = '(', String rightDelimiter = ')']) {
     if (_isToStringVisiting(iterable)) {
       return "$leftDelimiter...$rightDelimiter";
     }
-    StringBuffer buffer = new StringBuffer(leftDelimiter);
+    StringBuffer buffer = StringBuffer(leftDelimiter);
     _toStringVisiting.add(iterable);
     try {
       buffer.writeAll(iterable, ", ");
@@ -282,10 +274,10 @@
   }
 }
 
-/** A collection used to identify cyclic lists during toString() calls. */
+/// A collection used to identify cyclic lists during toString() calls.
 final List _toStringVisiting = [];
 
-/** Check if we are currently visiting `o` in a toString call. */
+/// Check if we are currently visiting `o` in a toString call.
 bool _isToStringVisiting(Object o) {
   for (int i = 0; i < _toStringVisiting.length; i++) {
     if (identical(o, _toStringVisiting[i])) return true;
@@ -293,9 +285,7 @@
   return false;
 }
 
-/**
- * Convert elements of [iterable] to strings and store them in [parts].
- */
+/// Convert elements of [iterable] to strings and store them in [parts].
 void _iterablePartsToStrings(Iterable iterable, List<String> parts) {
   /*
    * This is the complicated part of [iterableToShortString].
diff --git a/sdk/lib/collection/iterator.dart b/sdk/lib/collection/iterator.dart
index f870711..671f0ee 100644
--- a/sdk/lib/collection/iterator.dart
+++ b/sdk/lib/collection/iterator.dart
@@ -4,12 +4,10 @@
 
 part of dart.collection;
 
-/**
- * The [HasNextIterator] class wraps an [Iterator] and provides methods to
- * iterate over an object using `hasNext` and `next`.
- *
- * An [HasNextIterator] does not implement the [Iterator] interface.
- */
+/// The [HasNextIterator] class wraps an [Iterator] and provides methods to
+/// iterate over an object using `hasNext` and `next`.
+///
+/// An [HasNextIterator] does not implement the [Iterator] interface.
 class HasNextIterator<E> {
   static const int _HAS_NEXT_AND_NEXT_IN_CURRENT = 0;
   static const int _NO_NEXT = 1;
@@ -28,7 +26,7 @@
   E next() {
     // Call to hasNext is necessary to make sure we are positioned at the first
     // element when we start iterating.
-    if (!hasNext) throw new StateError("No more elements");
+    if (!hasNext) throw StateError("No more elements");
     assert(_state == _HAS_NEXT_AND_NEXT_IN_CURRENT);
     E result = _iterator.current;
     _move();
diff --git a/sdk/lib/collection/linked_hash_map.dart b/sdk/lib/collection/linked_hash_map.dart
index 91f95ad..e3a650d 100644
--- a/sdk/lib/collection/linked_hash_map.dart
+++ b/sdk/lib/collection/linked_hash_map.dart
@@ -4,153 +4,137 @@
 
 part of dart.collection;
 
-/**
- * A hash-table based implementation of [Map].
- *
- * The insertion order of keys is remembered,
- * and keys are iterated in the order they were inserted into the map.
- * Values are iterated in their corresponding key's order.
- * Changing a key's value, when the key is already in the map,
- * does not change the iteration order,
- * but removing the key and adding it again
- * will make it be last in the iteration order.
- *
- * The keys of a `LinkedHashMap` must have consistent [Object.==]
- * and [Object.hashCode] implementations. This means that the `==` operator
- * must define a stable equivalence relation on the keys (reflexive,
- * symmetric, transitive, and consistent over time), and that `hashCode`
- * must be the same for objects that are considered equal by `==`.
- *
- * The map allows `null` as a key.
- */
+/// A hash-table based implementation of [Map].
+///
+/// The insertion order of keys is remembered,
+/// and keys are iterated in the order they were inserted into the map.
+/// Values are iterated in their corresponding key's order.
+/// Changing a key's value, when the key is already in the map,
+/// does not change the iteration order,
+/// but removing the key and adding it again
+/// will make it be last in the iteration order.
+///
+/// The keys of a `LinkedHashMap` must have consistent [Object.==]
+/// and [Object.hashCode] implementations. This means that the `==` operator
+/// must define a stable equivalence relation on the keys (reflexive,
+/// symmetric, transitive, and consistent over time), and that `hashCode`
+/// must be the same for objects that are considered equal by `==`.
+///
+/// The map allows `null` as a key.
 abstract class LinkedHashMap<K, V> implements Map<K, V> {
-  /**
-   * Creates an insertion-ordered hash-table based [Map].
-   *
-   * If [equals] is provided, it is used to compare the keys in the table with
-   * new keys. If [equals] is omitted, the key's own [Object.==] is used
-   * instead.
-   *
-   * Similar, if [hashCode] is provided, it is used to produce a hash value
-   * for keys in order to place them in the hash table. If it is omitted, the
-   * key's own [Object.hashCode] is used.
-   *
-   * If using methods like [operator []], [remove] and [containsKey] together
-   * with a custom equality and hashcode, an extra `isValidKey` function
-   * can be supplied. This function is called before calling [equals] or
-   * [hashCode] with an argument that may not be a [K] instance, and if the
-   * call returns false, the key is assumed to not be in the set.
-   * The [isValidKey] function defaults to just testing if the object is a
-   * [K] instance.
-   *
-   * Example:
-   *
-   *     new LinkedHashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
-   *                                hashCode: (int e) => e % 5)
-   *
-   * This example map does not need an `isValidKey` function to be passed.
-   * The default function accepts only `int` values, which can safely be
-   * passed to both the `equals` and `hashCode` functions.
-   *
-   * If neither `equals`, `hashCode`, nor `isValidKey` is provided,
-   * the default `isValidKey` instead accepts all keys.
-   * The default equality and hashcode operations are assumed to work on all
-   * objects.
-   *
-   * Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
-   * and `isValidKey` is omitted, the resulting map is identity based,
-   * and the `isValidKey` defaults to accepting all keys.
-   * Such a map can be created directly using [LinkedHashMap.identity].
-   *
-   * The used `equals` and `hashCode` method should always be consistent,
-   * so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash
-   * of an object, or what it compares equal to, should not change while the
-   * object is in the table. If it does change, the result is unpredictable.
-   *
-   * If you supply one of [equals] and [hashCode],
-   * you should generally also to supply the other.
-   */
+  /// Creates an insertion-ordered hash-table based [Map].
+  ///
+  /// If [equals] is provided, it is used to compare the keys in the table with
+  /// new keys. If [equals] is omitted, the key's own [Object.==] is used
+  /// instead.
+  ///
+  /// Similar, if [hashCode] is provided, it is used to produce a hash value
+  /// for keys in order to place them in the hash table. If it is omitted, the
+  /// key's own [Object.hashCode] is used.
+  ///
+  /// If using methods like [operator []], [remove] and [containsKey] together
+  /// with a custom equality and hashcode, an extra `isValidKey` function
+  /// can be supplied. This function is called before calling [equals] or
+  /// [hashCode] with an argument that may not be a [K] instance, and if the
+  /// call returns false, the key is assumed to not be in the set.
+  /// The [isValidKey] function defaults to just testing if the object is a
+  /// [K] instance.
+  ///
+  /// Example:
+  ///
+  ///     new LinkedHashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
+  ///                                hashCode: (int e) => e % 5)
+  ///
+  /// This example map does not need an `isValidKey` function to be passed.
+  /// The default function accepts only `int` values, which can safely be
+  /// passed to both the `equals` and `hashCode` functions.
+  ///
+  /// If neither `equals`, `hashCode`, nor `isValidKey` is provided,
+  /// the default `isValidKey` instead accepts all keys.
+  /// The default equality and hashcode operations are assumed to work on all
+  /// objects.
+  ///
+  /// Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
+  /// and `isValidKey` is omitted, the resulting map is identity based,
+  /// and the `isValidKey` defaults to accepting all keys.
+  /// Such a map can be created directly using [LinkedHashMap.identity].
+  ///
+  /// The used `equals` and `hashCode` method should always be consistent,
+  /// so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash
+  /// of an object, or what it compares equal to, should not change while the
+  /// object is in the table. If it does change, the result is unpredictable.
+  ///
+  /// If you supply one of [equals] and [hashCode],
+  /// you should generally also to supply the other.
   external factory LinkedHashMap(
       {bool equals(K key1, K key2),
       int hashCode(K key),
       bool isValidKey(potentialKey)});
 
-  /**
-   * Creates an insertion-ordered identity-based map.
-   *
-   * Effectively a shorthand for:
-   *
-   *     new LinkedHashMap<K, V>(equals: identical,
-   *                             hashCode: identityHashCode)
-   */
+  /// Creates an insertion-ordered identity-based map.
+  ///
+  /// Effectively a shorthand for:
+  ///
+  ///     new LinkedHashMap<K, V>(equals: identical,
+  ///                             hashCode: identityHashCode)
   external factory LinkedHashMap.identity();
 
-  /**
-   * Creates a [LinkedHashMap] that contains all key value pairs of [other].
-   *
-   * The keys must all be instances of [K] and the values to [V].
-   * The [other] map itself can have any type.
-   */
+  /// Creates a [LinkedHashMap] that contains all key value pairs of [other].
+  ///
+  /// The keys must all be instances of [K] and the values to [V].
+  /// The [other] map itself can have any type.
   factory LinkedHashMap.from(Map other) {
-    LinkedHashMap<K, V> result = new LinkedHashMap<K, V>();
+    LinkedHashMap<K, V> result = LinkedHashMap<K, V>();
     other.forEach((k, v) {
       result[k] = v;
     });
     return result;
   }
 
-  /**
-   * Creates a [LinkedHashMap] that contains all key value pairs of [other].
-   */
+  /// Creates a [LinkedHashMap] that contains all key value pairs of [other].
   factory LinkedHashMap.of(Map<K, V> other) =>
-      new LinkedHashMap<K, V>()..addAll(other);
+      LinkedHashMap<K, V>()..addAll(other);
 
-  /**
-   * Creates a [LinkedHashMap] where the keys and values are computed from the
-   * [iterable].
-   *
-   * For each element of the [iterable] this constructor computes a key/value
-   * pair, by applying [key] and [value] respectively.
-   *
-   * The keys of the key/value pairs do not need to be unique. The last
-   * occurrence of a key will simply overwrite any previous value.
-   *
-   * If no values are specified for [key] and [value] the default is the
-   * identity function.
-   */
+  /// Creates a [LinkedHashMap] where the keys and values are computed from the
+  /// [iterable].
+  ///
+  /// For each element of the [iterable] this constructor computes a key/value
+  /// pair, by applying [key] and [value] respectively.
+  ///
+  /// The keys of the key/value pairs do not need to be unique. The last
+  /// occurrence of a key will simply overwrite any previous value.
+  ///
+  /// If no values are specified for [key] and [value] the default is the
+  /// identity function.
   factory LinkedHashMap.fromIterable(Iterable iterable,
       {K key(element), V value(element)}) {
-    LinkedHashMap<K, V> map = new LinkedHashMap<K, V>();
+    LinkedHashMap<K, V> map = LinkedHashMap<K, V>();
     MapBase._fillMapWithMappedIterable(map, iterable, key, value);
     return map;
   }
 
-  /**
-   * Creates a [LinkedHashMap] associating the given [keys] to [values].
-   *
-   * This constructor iterates over [keys] and [values] and maps each element of
-   * [keys] to the corresponding element of [values].
-   *
-   * If [keys] contains the same object multiple times, the last occurrence
-   * overwrites the previous value.
-   *
-   * It is an error if the two [Iterable]s don't have the same length.
-   */
+  /// Creates a [LinkedHashMap] associating the given [keys] to [values].
+  ///
+  /// This constructor iterates over [keys] and [values] and maps each element of
+  /// [keys] to the corresponding element of [values].
+  ///
+  /// If [keys] contains the same object multiple times, the last occurrence
+  /// overwrites the previous value.
+  ///
+  /// It is an error if the two [Iterable]s don't have the same length.
   factory LinkedHashMap.fromIterables(Iterable<K> keys, Iterable<V> values) {
-    LinkedHashMap<K, V> map = new LinkedHashMap<K, V>();
+    LinkedHashMap<K, V> map = LinkedHashMap<K, V>();
     MapBase._fillMapWithIterables(map, keys, values);
     return map;
   }
 
-  /**
-   * Creates a [LinkedHashMap] containing the entries of [entries].
-   *
-   * Returns a new `LinkedHashMap<K, V>` where all entries of [entries]
-   * have been added in iteration order.
-   *
-   * If multiple [entries] have the same key,
-   * later occurrences overwrite the earlier ones.
-   */
+  /// Creates a [LinkedHashMap] containing the entries of [entries].
+  ///
+  /// Returns a new `LinkedHashMap<K, V>` where all entries of [entries]
+  /// have been added in iteration order.
+  ///
+  /// If multiple [entries] have the same key,
+  /// later occurrences overwrite the earlier ones.
   @Since("2.1")
   factory LinkedHashMap.fromEntries(Iterable<MapEntry<K, V>> entries) =>
       <K, V>{}..addEntries(entries);
diff --git a/sdk/lib/collection/linked_hash_set.dart b/sdk/lib/collection/linked_hash_set.dart
index 2fff2ec..a058b5e 100644
--- a/sdk/lib/collection/linked_hash_set.dart
+++ b/sdk/lib/collection/linked_hash_set.dart
@@ -4,131 +4,117 @@
 
 part of dart.collection;
 
-/**
- * A [LinkedHashSet] is a hash-table based [Set] implementation.
- *
- * The `LinkedHashSet` also keep track of the order that elements were inserted
- * in, and iteration happens in first-to-last insertion order.
- *
- * The elements of a `LinkedHashSet` must have consistent [Object.==]
- * and [Object.hashCode] implementations. This means that the `==` operator
- * must define a stable equivalence relation on the elements (reflexive,
- * symmetric, transitive, and consistent over time), and that `hashCode`
- * must be the same for objects that are considered equal by `==`.
- *
- * The set allows `null` as an element.
- *
- * Iteration of elements is done in element insertion order.
- * An element that was added after another will occur later in the iteration.
- * Adding an element that is already in the set
- * does not change its position in the iteration order,
- * but removing an element and adding it again,
- * will make it the last element of an iteration.
- *
- * Most simple operations on `HashSet` are done in (potentially amortized)
- * constant time: [add], [contains], [remove], and [length], provided the hash
- * codes of objects are well distributed..
- */
+/// A [LinkedHashSet] is a hash-table based [Set] implementation.
+///
+/// The `LinkedHashSet` also keep track of the order that elements were inserted
+/// in, and iteration happens in first-to-last insertion order.
+///
+/// The elements of a `LinkedHashSet` must have consistent [Object.==]
+/// and [Object.hashCode] implementations. This means that the `==` operator
+/// must define a stable equivalence relation on the elements (reflexive,
+/// symmetric, transitive, and consistent over time), and that `hashCode`
+/// must be the same for objects that are considered equal by `==`.
+///
+/// The set allows `null` as an element.
+///
+/// Iteration of elements is done in element insertion order.
+/// An element that was added after another will occur later in the iteration.
+/// Adding an element that is already in the set
+/// does not change its position in the iteration order,
+/// but removing an element and adding it again,
+/// will make it the last element of an iteration.
+///
+/// Most simple operations on `HashSet` are done in (potentially amortized)
+/// constant time: [add], [contains], [remove], and [length], provided the hash
+/// codes of objects are well distributed..
 abstract class LinkedHashSet<E> implements Set<E> {
-  /**
-   * Create an insertion-ordered hash set using the provided
-   * [equals] and [hashCode].
-   *
-   * The provided [equals] must define a stable equivalence relation, and
-   * [hashCode] must be consistent with [equals]. If the [equals] or [hashCode]
-   * methods won't work on all objects, but only on some instances of E, the
-   * [isValidKey] predicate can be used to restrict the keys that the functions
-   * are applied to.
-   * Any key for which [isValidKey] returns false is automatically assumed
-   * to not be in the set when asking `contains`.
-   *
-   * If [equals] or [hashCode] are omitted, the set uses
-   * the elements' intrinsic [Object.==] and [Object.hashCode],
-   * and [isValidKey] is ignored since these operations are assumed
-   * to work on all objects.
-   *
-   * If you supply one of [equals] and [hashCode],
-   * you should generally also to supply the other.
-   *
-   * If the supplied `equals` or `hashCode` functions won't work on all [E]
-   * objects, and the map will be used in a setting where a non-`E` object
-   * is passed to, e.g., `contains`, then the [isValidKey] function should
-   * also be supplied.
-   *
-   * If [isValidKey] is omitted, it defaults to testing if the object is an
-   * [E] instance. That means that:
-   *
-   *     new LinkedHashSet<int>(equals: (int e1, int e2) => (e1 - e2) % 5 == 0,
-   *                            hashCode: (int e) => e % 5)
-   *
-   * does not need an `isValidKey` argument, because it defaults to only
-   * accepting `int` values which are accepted by both `equals` and `hashCode`.
-   *
-   * If neither `equals`, `hashCode`, nor `isValidKey` is provided,
-   * the default `isValidKey` instead accepts all values.
-   * The default equality and hashcode operations are assumed to work on all
-   * objects.
-   *
-   * Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
-   * and `isValidKey` is omitted, the resulting set is identity based,
-   * and the `isValidKey` defaults to accepting all keys.
-   * Such a map can be created directly using [LinkedHashSet.identity].
-   */
+  /// Create an insertion-ordered hash set using the provided
+  /// [equals] and [hashCode].
+  ///
+  /// The provided [equals] must define a stable equivalence relation, and
+  /// [hashCode] must be consistent with [equals]. If the [equals] or [hashCode]
+  /// methods won't work on all objects, but only on some instances of E, the
+  /// [isValidKey] predicate can be used to restrict the keys that the functions
+  /// are applied to.
+  /// Any key for which [isValidKey] returns false is automatically assumed
+  /// to not be in the set when asking `contains`.
+  ///
+  /// If [equals] or [hashCode] are omitted, the set uses
+  /// the elements' intrinsic [Object.==] and [Object.hashCode],
+  /// and [isValidKey] is ignored since these operations are assumed
+  /// to work on all objects.
+  ///
+  /// If you supply one of [equals] and [hashCode],
+  /// you should generally also to supply the other.
+  ///
+  /// If the supplied `equals` or `hashCode` functions won't work on all [E]
+  /// objects, and the map will be used in a setting where a non-`E` object
+  /// is passed to, e.g., `contains`, then the [isValidKey] function should
+  /// also be supplied.
+  ///
+  /// If [isValidKey] is omitted, it defaults to testing if the object is an
+  /// [E] instance. That means that:
+  ///
+  ///     new LinkedHashSet<int>(equals: (int e1, int e2) => (e1 - e2) % 5 == 0,
+  ///                            hashCode: (int e) => e % 5)
+  ///
+  /// does not need an `isValidKey` argument, because it defaults to only
+  /// accepting `int` values which are accepted by both `equals` and `hashCode`.
+  ///
+  /// If neither `equals`, `hashCode`, nor `isValidKey` is provided,
+  /// the default `isValidKey` instead accepts all values.
+  /// The default equality and hashcode operations are assumed to work on all
+  /// objects.
+  ///
+  /// Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
+  /// and `isValidKey` is omitted, the resulting set is identity based,
+  /// and the `isValidKey` defaults to accepting all keys.
+  /// Such a map can be created directly using [LinkedHashSet.identity].
   external factory LinkedHashSet(
       {bool equals(E e1, E e2),
       int hashCode(E e),
       bool isValidKey(potentialKey)});
 
-  /**
-   * Creates an insertion-ordered identity-based set.
-   *
-   * Effectively a shorthand for:
-   *
-   *     new LinkedHashSet<E>(equals: identical,
-   *                          hashCode: identityHashCode)
-   */
+  /// Creates an insertion-ordered identity-based set.
+  ///
+  /// Effectively a shorthand for:
+  ///
+  ///     new LinkedHashSet<E>(equals: identical,
+  ///                          hashCode: identityHashCode)
   external factory LinkedHashSet.identity();
 
-  /**
-   * Create a linked hash set containing all [elements].
-   *
-   * Creates a linked hash set as by `new LinkedHashSet<E>()` and adds each
-   * element of `elements` to this set in the order they are iterated.
-   *
-   * All the [elements] should be instances of [E].
-   * The `elements` iterable itself may have any element type,
-   * so this constructor can be used to down-cast a `Set`, for example as:
-   *
-   *     Set<SuperType> superSet = ...;
-   *     Iterable<SuperType> tmp = superSet.where((e) => e is SubType);
-   *     Set<SubType> subSet = new LinkedHashSet<SubType>.from(tmp);
-   */
+  /// Create a linked hash set containing all [elements].
+  ///
+  /// Creates a linked hash set as by `new LinkedHashSet<E>()` and adds each
+  /// element of `elements` to this set in the order they are iterated.
+  ///
+  /// All the [elements] should be instances of [E].
+  /// The `elements` iterable itself may have any element type,
+  /// so this constructor can be used to down-cast a `Set`, for example as:
+  ///
+  ///     Set<SuperType> superSet = ...;
+  ///     Iterable<SuperType> tmp = superSet.where((e) => e is SubType);
+  ///     Set<SubType> subSet = new LinkedHashSet<SubType>.from(tmp);
   factory LinkedHashSet.from(Iterable elements) {
-    LinkedHashSet<E> result = new LinkedHashSet<E>();
+    LinkedHashSet<E> result = LinkedHashSet<E>();
     for (final element in elements) {
       result.add(element);
     }
     return result;
   }
 
-  /**
-   * Create a linked hash set from [elements].
-   *
-   * Creates a linked hash set as by `new LinkedHashSet<E>()` and adds each
-   * element of `elements` to this set in the order they are iterated.
-   */
+  /// Create a linked hash set from [elements].
+  ///
+  /// Creates a linked hash set as by `new LinkedHashSet<E>()` and adds each
+  /// element of `elements` to this set in the order they are iterated.
   factory LinkedHashSet.of(Iterable<E> elements) =>
-      new LinkedHashSet<E>()..addAll(elements);
+      LinkedHashSet<E>()..addAll(elements);
 
-  /**
-   * Executes a function on each element of the set.
-   *
-   * The elements are iterated in insertion order.
-   */
+  /// Executes a function on each element of the set.
+  ///
+  /// The elements are iterated in insertion order.
   void forEach(void action(E element));
 
-  /**
-   * Provides an iterator that iterates over the elements in insertion order.
-   */
+  /// Provides an iterator that iterates over the elements in insertion order.
   Iterator<E> get iterator;
 }
diff --git a/sdk/lib/collection/linked_list.dart b/sdk/lib/collection/linked_list.dart
index 4ba329c..91461cb 100644
--- a/sdk/lib/collection/linked_list.dart
+++ b/sdk/lib/collection/linked_list.dart
@@ -4,82 +4,68 @@
 
 part of dart.collection;
 
-/**
- * A specialized double-linked list of elements that extends [LinkedListEntry].
- *
- * This is not a generic data structure. It only accepts elements that extend
- * the [LinkedListEntry] class. See the [Queue] implementations for
- * generic collections that allow constant time adding and removing at the ends.
- *
- * This is not a [List] implementation. Despite its name, this class does not
- * implement the [List] interface. It does not allow constant time lookup by
- * index.
- *
- * Because the elements themselves contain the links of this linked list,
- * each element can be in only one list at a time. To add an element to another
- * list, it must first be removed from its current list (if any).
- *
- * In return, each element knows its own place in the linked list, as well as
- * which list it is in. This allows constant time [LinkedListEntry.insertAfter],
- * [LinkedListEntry.insertBefore] and [LinkedListEntry.unlink] operations
- * when all you have is the element.
- *
- * A `LinkedList` also allows constant time adding and removing at either end,
- * and a constant time length getter.
- */
+/// A specialized double-linked list of elements that extends [LinkedListEntry].
+///
+/// This is not a generic data structure. It only accepts elements that extend
+/// the [LinkedListEntry] class. See the [Queue] implementations for generic
+/// collections that allow constant time adding and removing at the ends.
+///
+/// This is not a [List] implementation. Despite its name, this class does not
+/// implement the [List] interface. It does not allow constant time lookup by
+/// index.
+///
+/// Because the elements themselves contain the links of this linked list,
+/// each element can be in only one list at a time. To add an element to another
+/// list, it must first be removed from its current list (if any).
+///
+/// In return, each element knows its own place in the linked list, as well as
+/// which list it is in. This allows constant time
+/// [LinkedListEntry.insertAfter], [LinkedListEntry.insertBefore] and
+/// [LinkedListEntry.unlink] operations when all you have is the element.
+///
+/// A `LinkedList` also allows constant time adding and removing at either end,
+/// and a constant time length getter.
 class LinkedList<E extends LinkedListEntry<E>> extends Iterable<E> {
   int _modificationCount = 0;
   int _length = 0;
   E _first;
 
-  /**
-   * Construct a new empty linked list.
-   */
+  /// Construct a new empty linked list.
   LinkedList();
 
-  /**
-   * Add [entry] to the beginning of the linked list.
-   */
+  /// Add [entry] to the beginning of the linked list.
   void addFirst(E entry) {
     _insertBefore(_first, entry, updateFirst: true);
     _first = entry;
   }
 
-  /**
-   * Add [entry] to the end of the linked list.
-   */
+  /// Add [entry] to the end of the linked list.
   void add(E entry) {
     _insertBefore(_first, entry, updateFirst: false);
   }
 
-  /**
-   * Add [entries] to the end of the linked list.
-   */
+  /// Add [entries] to the end of the linked list.
   void addAll(Iterable<E> entries) {
     entries.forEach(add);
   }
 
-  /**
-   * Remove [entry] from the linked list.
-   *
-   * Returns false and does nothing if [entry] is not in this linked list.
-   *
-   * This is equivalent to calling `entry.unlink()` if the entry is in this
-   * list.
-   */
+  /// Remove [entry] from the linked list.
+  ///
+  /// Returns false and does nothing if [entry] is not in this linked list.
+  ///
+  /// This is equivalent to calling `entry.unlink()` if the entry is in this
+  /// list.
   bool remove(E entry) {
     if (entry._list != this) return false;
     _unlink(entry); // Unlink will decrement length.
     return true;
   }
 
-  Iterator<E> get iterator => new _LinkedListIterator<E>(this);
+  Iterator<E> get iterator => _LinkedListIterator<E>(this);
 
   int get length => _length;
 
-  /**
-   * Remove all elements from this linked list.
-   */
+  /// Remove all elements from this linked list.
   void clear() {
     _modificationCount++;
     if (isEmpty) return;
@@ -97,33 +83,31 @@
 
   E get first {
     if (isEmpty) {
-      throw new StateError('No such element');
+      throw StateError('No such element');
     }
     return _first;
   }
 
   E get last {
     if (isEmpty) {
-      throw new StateError('No such element');
+      throw StateError('No such element');
     }
     return _first._previous;
   }
 
   E get single {
     if (isEmpty) {
-      throw new StateError('No such element');
+      throw StateError('No such element');
     }
     if (_length > 1) {
-      throw new StateError('Too many elements');
+      throw StateError('Too many elements');
     }
     return _first;
   }
 
-  /**
-   * Call [action] with each entry in this linked list.
-   *
-   * It's an error if [action] modify the linked list.
-   */
+  /// Call [action] with each entry in this linked list.
+  ///
+  /// It's an error if [action] modify the linked list.
   void forEach(void action(E entry)) {
     int modificationCount = _modificationCount;
     if (isEmpty) return;
@@ -132,7 +116,7 @@
     do {
       action(current);
       if (modificationCount != _modificationCount) {
-        throw new ConcurrentModificationError(this);
+        throw ConcurrentModificationError(this);
       }
       current = current._next;
     } while (!identical(current, _first));
@@ -146,7 +130,7 @@
   /// updates the [_first] field to point to the [newEntry] as first entry.
   void _insertBefore(E entry, E newEntry, {bool updateFirst}) {
     if (newEntry.list != null) {
-      throw new StateError('LinkedListEntry is already in a LinkedList');
+      throw StateError('LinkedListEntry is already in a LinkedList');
     }
     _modificationCount++;
 
@@ -201,7 +185,7 @@
 
   bool moveNext() {
     if (_modificationCount != _list._modificationCount) {
-      throw new ConcurrentModificationError(this);
+      throw ConcurrentModificationError(this);
     }
     if (_list.isEmpty || (_visitedFirst && identical(_next, _list.first))) {
       _current = null;
@@ -214,79 +198,65 @@
   }
 }
 
-/**
- * An object that can be an element in a [LinkedList].
- *
- * All elements of a `LinkedList` must extend this class.
- * The class provides the internal links that link elements together
- * in the `LinkedList`, and a reference to the linked list itself
- * that an element is currently part of.
- *
- * An entry can be in at most one linked list at a time.
- * While an entry is in a linked list, the [list] property points to that
- * linked list, and otherwise the `list` property is `null`.
- *
- * When created, an entry is not in any linked list.
- */
+/// An object that can be an element in a [LinkedList].
+///
+/// All elements of a `LinkedList` must extend this class.
+/// The class provides the internal links that link elements together
+/// in the `LinkedList`, and a reference to the linked list itself
+/// that an element is currently part of.
+///
+/// An entry can be in at most one linked list at a time.
+/// While an entry is in a linked list, the [list] property points to that
+/// linked list, and otherwise the `list` property is `null`.
+///
+/// When created, an entry is not in any linked list.
 abstract class LinkedListEntry<E extends LinkedListEntry<E>> {
   LinkedList<E> _list;
   E _next;
   E _previous;
 
-  /**
-   * Get the linked list containing this element.
-   *
-   * Returns `null` if this entry is not currently in any list.
-   */
+  /// Get the linked list containing this element.
+  ///
+  /// Returns `null` if this entry is not currently in any list.
   LinkedList<E> get list => _list;
 
-  /**
-   * Unlink the element from its linked list.
-   *
-   * The entry must currently be in a linked list when this method is called.
-   */
+  /// Unlink the element from its linked list.
+  ///
+  /// The entry must currently be in a linked list when this method is called.
   void unlink() {
     _list._unlink(this);
   }
 
-  /**
-   * Return the successor of this element in its linked list.
-   *
-   * Returns `null` if there is no successor in the linked list, or if this
-   * entry is not currently in any list.
-   */
+  /// Return the successor of this element in its linked list.
+  ///
+  /// Returns `null` if there is no successor in the linked list, or if this
+  /// entry is not currently in any list.
   E get next {
     if (_list == null || identical(_list.first, _next)) return null;
     return _next;
   }
 
-  /**
-   * Return the predecessor of this element in its linked list.
-   *
-   * Returns `null` if there is no predecessor in the linked list, or if this
-   * entry is not currently in any list.
-   */
+  /// Return the predecessor of this element in its linked list.
+  ///
+  /// Returns `null` if there is no predecessor in the linked list, or if this
+  /// entry is not currently in any list.
   E get previous {
     if (_list == null || identical(this, _list.first)) return null;
     return _previous;
   }
 
-  /**
-   * Insert an element after this element in this element's linked list.
-   *
-   * This entry must be in a linked list when this method is called.
-   * The [entry] must not be in a linked list.
-   */
+  /// Insert an element after this element in this element's linked list.
+  ///
+  /// This entry must be in a linked list when this method is called.
+  /// The [entry] must not be in a linked list.
   void insertAfter(E entry) {
     _list._insertBefore(_next, entry, updateFirst: false);
   }
 
-  /**
-   * Insert an element before this element in this element's linked list.
-   *
-   * This entry must be in a linked list when this method is called.
-   * The [entry] must not be in a linked list.
-   */
+  /// Insert an element before this element in this element's linked list.
+  ///
+  /// This entry must be in a linked list when this method is called.
+  /// The [entry] must not be in a linked list.
   void insertBefore(E entry) {
     _list._insertBefore(this, entry, updateFirst: true);
   }
diff --git a/sdk/lib/collection/list.dart b/sdk/lib/collection/list.dart
index 0c01350..77ce66a 100644
--- a/sdk/lib/collection/list.dart
+++ b/sdk/lib/collection/list.dart
@@ -4,70 +4,65 @@
 
 part of dart.collection;
 
-/**
- * Abstract implementation of a list.
- *
- * `ListBase` can be used as a base class for implementing the `List` interface.
- *
- * All operations are defined in terms of `length`, `operator[]`,
- * `operator[]=` and `length=`, which need to be implemented.
- *
- * *NOTICE*: Forwarding just these four operations to a normal growable [List]
- * (as created by `new List()`) will give very bad performance for `add` and
- * `addAll` operations of `ListBase`. These operations are implemented by
- * increasing the length of the list by one for each `add` operation, and
- * repeatedly increasing the length of a growable list is not efficient.
- * To avoid this, either override 'add' and 'addAll' to also forward directly
- * to the growable list, or, preferably, use `DelegatingList` from
- * "package:collection/wrappers.dart" instead.
- */
+/// Abstract implementation of a list.
+///
+/// `ListBase` can be used as a base class for implementing the `List`
+/// interface.
+///
+/// All operations are defined in terms of `length`, `operator[]`,
+/// `operator[]=` and `length=`, which need to be implemented.
+///
+/// *NOTICE*: Forwarding just these four operations to a normal growable [List]
+/// (as created by `new List()`) will give very bad performance for `add` and
+/// `addAll` operations of `ListBase`. These operations are implemented by
+/// increasing the length of the list by one for each `add` operation, and
+/// repeatedly increasing the length of a growable list is not efficient.
+/// To avoid this, either override 'add' and 'addAll' to also forward directly
+/// to the growable list, or, preferably, use `DelegatingList` from
+/// "package:collection/wrappers.dart" instead.
 abstract class ListBase<E> extends Object with ListMixin<E> {
-  /**
-   * Convert a `List` to a string as `[each, element, as, string]`.
-   *
-   * Handles circular references where converting one of the elements
-   * to a string ends up converting [list] to a string again.
-   */
+  /// Convert a `List` to a string as `[each, element, as, string]`.
+  ///
+  /// Handles circular references where converting one of the elements
+  /// to a string ends up converting [list] to a string again.
   static String listToString(List list) =>
       IterableBase.iterableToFullString(list, '[', ']');
 }
 
-/**
- * Base implementation of a [List] class.
- *
- * `ListMixin` can be used as a mixin to make a class implement
- * the `List` interface.
- *
- * This implements all read operations using only the `length` and
- * `operator[]` members. It implements write operations using those and
- * `length=` and `operator[]=`
- *
- * *NOTICE*: Forwarding just these four operations to a normal growable [List]
- * (as created by `new List()`) will give very bad performance for `add` and
- * `addAll` operations of `ListBase`. These operations are implemented by
- * increasing the length of the list by one for each `add` operation, and
- * repeatedly increasing the length of a growable list is not efficient.
- * To avoid this, either override 'add' and 'addAll' to also forward directly
- * to the growable list, or, if possible, use `DelegatingList` from
- * "package:collection/wrappers.dart" instead.
- */
+/// Base implementation of a [List] class.
+///
+/// `ListMixin` can be used as a mixin to make a class implement
+/// the `List` interface.
+///
+/// This implements all read operations using only the `length` and
+/// `operator[]` members. It implements write operations using those and
+/// `length=` and `operator[]=`
+///
+/// *NOTICE*: Forwarding just these four operations to a normal growable [List]
+/// (as created by `new List()`) will give very bad performance for `add` and
+/// `addAll` operations of `ListBase`. These operations are implemented by
+/// increasing the length of the list by one for each `add` operation, and
+/// repeatedly increasing the length of a growable list is not efficient.
+/// To avoid this, either override 'add' and 'addAll' to also forward directly
+/// to the growable list, or, if possible, use `DelegatingList` from
+/// "package:collection/wrappers.dart" instead.
 abstract class ListMixin<E> implements List<E> {
   // Iterable interface.
   // TODO(lrn): When we get composable mixins, reuse IterableMixin instead
   // of redaclating everything.
-  Iterator<E> get iterator => new ListIterator<E>(this);
+  Iterator<E> get iterator => ListIterator<E>(this);
 
   E elementAt(int index) => this[index];
 
   Iterable<E> followedBy(Iterable<E> other) =>
-      new FollowedByIterable<E>.firstEfficient(this, other);
+      FollowedByIterable<E>.firstEfficient(this, other);
 
   void forEach(void action(E element)) {
     int length = this.length;
     for (int i = 0; i < length; i++) {
       action(this[i]);
       if (length != this.length) {
-        throw new ConcurrentModificationError(this);
+        throw ConcurrentModificationError(this);
       }
     }
   }
@@ -107,7 +102,7 @@
     for (int i = 0; i < length; i++) {
       if (this[i] == element) return true;
       if (length != this.length) {
-        throw new ConcurrentModificationError(this);
+        throw ConcurrentModificationError(this);
       }
     }
     return false;
@@ -118,7 +113,7 @@
     for (int i = 0; i < length; i++) {
       if (!test(this[i])) return false;
       if (length != this.length) {
-        throw new ConcurrentModificationError(this);
+        throw ConcurrentModificationError(this);
       }
     }
     return true;
@@ -129,7 +124,7 @@
     for (int i = 0; i < length; i++) {
       if (test(this[i])) return true;
       if (length != this.length) {
-        throw new ConcurrentModificationError(this);
+        throw ConcurrentModificationError(this);
       }
     }
     return false;
@@ -141,7 +136,7 @@
       E element = this[i];
       if (test(element)) return element;
       if (length != this.length) {
-        throw new ConcurrentModificationError(this);
+        throw ConcurrentModificationError(this);
       }
     }
     if (orElse != null) return orElse();
@@ -154,7 +149,7 @@
       E element = this[i];
       if (test(element)) return element;
       if (length != this.length) {
-        throw new ConcurrentModificationError(this);
+        throw ConcurrentModificationError(this);
       }
     }
     if (orElse != null) return orElse();
@@ -175,7 +170,7 @@
         match = element;
       }
       if (length != this.length) {
-        throw new ConcurrentModificationError(this);
+        throw ConcurrentModificationError(this);
       }
     }
     if (matchFound) return match;
@@ -185,18 +180,18 @@
 
   String join([String separator = ""]) {
     if (length == 0) return "";
-    StringBuffer buffer = new StringBuffer()..writeAll(this, separator);
+    StringBuffer buffer = StringBuffer()..writeAll(this, separator);
     return buffer.toString();
   }
 
-  Iterable<E> where(bool test(E element)) => new WhereIterable<E>(this, test);
+  Iterable<E> where(bool test(E element)) => WhereIterable<E>(this, test);
 
-  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+  Iterable<T> whereType<T>() => WhereTypeIterable<T>(this);
 
-  Iterable<T> map<T>(T f(E element)) => new MappedListIterable<E, T>(this, f);
+  Iterable<T> map<T>(T f(E element)) => MappedListIterable<E, T>(this, f);
 
   Iterable<T> expand<T>(Iterable<T> f(E element)) =>
-      new ExpandIterable<E, T>(this, f);
+      ExpandIterable<E, T>(this, f);
 
   E reduce(E combine(E previousValue, E element)) {
     int length = this.length;
@@ -205,7 +200,7 @@
     for (int i = 1; i < length; i++) {
       value = combine(value, this[i]);
       if (length != this.length) {
-        throw new ConcurrentModificationError(this);
+        throw ConcurrentModificationError(this);
       }
     }
     return value;
@@ -217,30 +212,30 @@
     for (int i = 0; i < length; i++) {
       value = combine(value, this[i]);
       if (length != this.length) {
-        throw new ConcurrentModificationError(this);
+        throw ConcurrentModificationError(this);
       }
     }
     return value;
   }
 
-  Iterable<E> skip(int count) => new SubListIterable<E>(this, count, null);
+  Iterable<E> skip(int count) => SubListIterable<E>(this, count, null);
 
   Iterable<E> skipWhile(bool test(E element)) {
-    return new SkipWhileIterable<E>(this, test);
+    return SkipWhileIterable<E>(this, test);
   }
 
-  Iterable<E> take(int count) => new SubListIterable<E>(this, 0, count);
+  Iterable<E> take(int count) => SubListIterable<E>(this, 0, count);
 
   Iterable<E> takeWhile(bool test(E element)) {
-    return new TakeWhileIterable<E>(this, test);
+    return TakeWhileIterable<E>(this, test);
   }
 
-  List<E> toList({bool growable: true}) {
+  List<E> toList({bool growable = true}) {
     List<E> result;
     if (growable) {
       result = <E>[]..length = length;
     } else {
-      result = new List<E>(length);
+      result = List<E>(length);
     }
     for (int i = 0; i < length; i++) {
       result[i] = this[i];
@@ -249,7 +244,7 @@
   }
 
   Set<E> toSet() {
-    Set<E> result = new Set<E>();
+    Set<E> result = Set<E>();
     for (int i = 0; i < length; i++) {
       result.add(this[i]);
     }
@@ -264,7 +259,7 @@
   void addAll(Iterable<E> iterable) {
     int i = this.length;
     for (E element in iterable) {
-      assert(this.length == i || (throw new ConcurrentModificationError(this)));
+      assert(this.length == i || (throw ConcurrentModificationError(this)));
       this.length = i + 1;
       this[i] = element;
       i++;
@@ -312,7 +307,7 @@
         retained.add(element);
       }
       if (length != this.length) {
-        throw new ConcurrentModificationError(this);
+        throw ConcurrentModificationError(this);
       }
     }
     if (retained.length != this.length) {
@@ -346,7 +341,7 @@
   }
 
   void shuffle([Random random]) {
-    random ??= new Random();
+    random ??= Random();
     int length = this.length;
     while (length > 1) {
       int pos = random.nextInt(length);
@@ -358,7 +353,7 @@
   }
 
   Map<int, E> asMap() {
-    return new ListMapView<E>(this);
+    return ListMapView<E>(this);
   }
 
   List<E> operator +(List<E> other) {
@@ -382,7 +377,7 @@
 
   Iterable<E> getRange(int start, int end) {
     RangeError.checkValidRange(start, end, this.length);
-    return new SubListIterable<E>(this, start, end);
+    return SubListIterable<E>(this, start, end);
   }
 
   void removeRange(int start, int end) {
@@ -517,7 +512,7 @@
       // If the iterable's length is linked to this list's length somehow,
       // we can't insert one in the other.
       this.length -= insertionLength;
-      throw new ConcurrentModificationError(iterable);
+      throw ConcurrentModificationError(iterable);
     }
     setRange(index + insertionLength, this.length, this, index);
     setAll(index, iterable);
@@ -533,7 +528,7 @@
     }
   }
 
-  Iterable<E> get reversed => new ReversedListIterable<E>(this);
+  Iterable<E> get reversed => ReversedListIterable<E>(this);
 
   String toString() => IterableBase.iterableToFullString(this, '[', ']');
 }
diff --git a/sdk/lib/collection/maps.dart b/sdk/lib/collection/maps.dart
index f54404f..8159342 100644
--- a/sdk/lib/collection/maps.dart
+++ b/sdk/lib/collection/maps.dart
@@ -4,22 +4,20 @@
 
 part of dart.collection;
 
-/**
- * Base class for implementing a [Map].
- *
- * This class has a basic implementation of all but five of the members of
- * [Map].
- * A basic `Map` class can be implemented by extending this class and
- * implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`.
- * The remaining operations are implemented in terms of these five.
- *
- * The `keys` iterable should have efficient [Iterable.length] and
- * [Iterable.contains] operations, and it should catch concurrent modifications
- * of the keys while iterating.
- *
- * A more efficient implementation is usually possible by overriding
- * some of the other members as well.
- */
+/// Base class for implementing a [Map].
+///
+/// This class has a basic implementation of all but five of the members of
+/// [Map].
+/// A basic `Map` class can be implemented by extending this class and
+/// implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`.
+/// The remaining operations are implemented in terms of these five.
+///
+/// The `keys` iterable should have efficient [Iterable.length] and
+/// [Iterable.contains] operations, and it should catch concurrent modifications
+/// of the keys while iterating.
+///
+/// A more efficient implementation is usually possible by overriding
+/// some of the other members as well.
 abstract class MapBase<K, V> extends MapMixin<K, V> {
   static String mapToString(Map m) {
     // Reuses the list in IterableBase for detecting toString cycles.
@@ -27,7 +25,7 @@
       return '{...}';
     }
 
-    var result = new StringBuffer();
+    var result = StringBuffer();
     try {
       _toStringVisiting.add(m);
       result.write('{');
@@ -52,12 +50,10 @@
 
   static _id(x) => x;
 
-  /**
-   * Fills a [Map] with key/value pairs computed from [iterable].
-   *
-   * This method is used by [Map] classes in the named constructor
-   * `fromIterable`.
-   */
+  /// Fills a [Map] with key/value pairs computed from [iterable].
+  ///
+  /// This method is used by [Map] classes in the named constructor
+  /// `fromIterable`.
   static void _fillMapWithMappedIterable(
       Map map, Iterable iterable, key(element), value(element)) {
     key ??= _id;
@@ -68,12 +64,10 @@
     }
   }
 
-  /**
-   * Fills a map by associating the [keys] to [values].
-   *
-   * This method is used by [Map] classes in the named constructor
-   * `fromIterables`.
-   */
+  /// Fills a map by associating the [keys] to [values].
+  ///
+  /// This method is used by [Map] classes in the named constructor
+  /// `fromIterables`.
   static void _fillMapWithIterables(Map map, Iterable keys, Iterable values) {
     Iterator keyIterator = keys.iterator;
     Iterator valueIterator = values.iterator;
@@ -88,27 +82,25 @@
     }
 
     if (hasNextKey || hasNextValue) {
-      throw new ArgumentError("Iterables do not have same length.");
+      throw ArgumentError("Iterables do not have same length.");
     }
   }
 }
 
-/**
- * Mixin implementing a [Map].
- *
- * This mixin has a basic implementation of all but five of the members of
- * [Map].
- * A basic `Map` class can be implemented by mixin in this class and
- * implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`.
- * The remaining operations are implemented in terms of these five.
- *
- * The `keys` iterable should have efficient [Iterable.length] and
- * [Iterable.contains] operations, and it should catch concurrent modifications
- * of the keys while iterating.
- *
- * A more efficient implementation is usually possible by overriding
- * some of the other members as well.
- */
+/// Mixin implementing a [Map].
+///
+/// This mixin has a basic implementation of all but five of the members of
+/// [Map].
+/// A basic `Map` class can be implemented by mixin in this class and
+/// implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`.
+/// The remaining operations are implemented in terms of these five.
+///
+/// The `keys` iterable should have efficient [Iterable.length] and
+/// [Iterable.contains] operations, and it should catch concurrent modifications
+/// of the keys while iterating.
+///
+/// A more efficient implementation is usually possible by overriding
+/// some of the other members as well.
 abstract class MapMixin<K, V> implements Map<K, V> {
   Iterable<K> get keys;
   V operator [](Object key);
@@ -152,7 +144,7 @@
     if (ifAbsent != null) {
       return this[key] = ifAbsent();
     }
-    throw new ArgumentError.value(key, "key", "Key not in map.");
+    throw ArgumentError.value(key, "key", "Key not in map.");
   }
 
   void updateAll(V update(K key, V value)) {
@@ -162,7 +154,7 @@
   }
 
   Iterable<MapEntry<K, V>> get entries {
-    return keys.map((K key) => new MapEntry<K, V>(key, this[key]));
+    return keys.map((K key) => MapEntry<K, V>(key, this[key]));
   }
 
   Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> transform(K key, V value)) {
@@ -194,39 +186,35 @@
   int get length => keys.length;
   bool get isEmpty => keys.isEmpty;
   bool get isNotEmpty => keys.isNotEmpty;
-  Iterable<V> get values => new _MapBaseValueIterable<K, V>(this);
+  Iterable<V> get values => _MapBaseValueIterable<K, V>(this);
   String toString() => MapBase.mapToString(this);
 }
 
-/**
- * Basic implementation of an unmodifiable [Map].
- *
- * This class has a basic implementation of all but two of the members of
- * an umodifiable [Map].
- * A simple unmodifiable `Map` class can be implemented by extending this
- * class and implementing `keys` and `operator[]`.
- *
- * Modifying operations throw when used.
- * The remaining non-modifying operations are implemented in terms of `keys`
- * and `operator[]`.
- *
- * The `keys` iterable should have efficient [Iterable.length] and
- * [Iterable.contains] operations, and it should catch concurrent modifications
- * of the keys while iterating.
- *
- * A more efficient implementation is usually possible by overriding
- * some of the other members as well.
- */
+/// Basic implementation of an unmodifiable [Map].
+///
+/// This class has a basic implementation of all but two of the members of
+/// an umodifiable [Map].
+/// A simple unmodifiable `Map` class can be implemented by extending this
+/// class and implementing `keys` and `operator[]`.
+///
+/// Modifying operations throw when used.
+/// The remaining non-modifying operations are implemented in terms of `keys`
+/// and `operator[]`.
+///
+/// The `keys` iterable should have efficient [Iterable.length] and
+/// [Iterable.contains] operations, and it should catch concurrent modifications
+/// of the keys while iterating.
+///
+/// A more efficient implementation is usually possible by overriding
+/// some of the other members as well.
 abstract class UnmodifiableMapBase<K, V> = MapBase<K, V>
     with _UnmodifiableMapMixin<K, V>;
 
-/**
- * Implementation of [Map.values] based on the map and its [Map.keys] iterable.
- *
- * Iterable that iterates over the values of a `Map`.
- * It accesses the values by iterating over the keys of the map, and using the
- * map's `operator[]` to lookup the keys.
- */
+/// Implementation of [Map.values] based on the map and its [Map.keys] iterable.
+///
+/// Iterable that iterates over the values of a `Map`.
+/// It accesses the values by iterating over the keys of the map, and using the
+/// map's `operator[]` to lookup the keys.
 class _MapBaseValueIterable<K, V> extends EfficientLengthIterable<V> {
   final Map<K, V> _map;
   _MapBaseValueIterable(this._map);
@@ -238,15 +226,13 @@
   V get single => _map[_map.keys.single];
   V get last => _map[_map.keys.last];
 
-  Iterator<V> get iterator => new _MapBaseValueIterator<K, V>(_map);
+  Iterator<V> get iterator => _MapBaseValueIterator<K, V>(_map);
 }
 
-/**
- * Iterator created by [_MapBaseValueIterable].
- *
- * Iterates over the values of a map by iterating its keys and lookup up the
- * values.
- */
+/// Iterator created by [_MapBaseValueIterable].
+///
+/// Iterates over the values of a map by iterating its keys and lookup up the
+/// values.
 class _MapBaseValueIterator<K, V> implements Iterator<V> {
   final Iterator<K> _keys;
   final Map<K, V> _map;
@@ -268,64 +254,62 @@
   V get current => _current;
 }
 
-/**
- * Mixin that overrides mutating map operations with implementations that throw.
- */
+/// Mixin that overrides mutating map operations with implementations that
+/// throw.
 abstract class _UnmodifiableMapMixin<K, V> implements Map<K, V> {
-  /** This operation is not supported by an unmodifiable map. */
+  /// This operation is not supported by an unmodifiable map.
   void operator []=(K key, V value) {
-    throw new UnsupportedError("Cannot modify unmodifiable map");
+    throw UnsupportedError("Cannot modify unmodifiable map");
   }
 
-  /** This operation is not supported by an unmodifiable map. */
+  /// This operation is not supported by an unmodifiable map.
   void addAll(Map<K, V> other) {
-    throw new UnsupportedError("Cannot modify unmodifiable map");
+    throw UnsupportedError("Cannot modify unmodifiable map");
   }
 
-  /** This operation is not supported by an unmodifiable map. */
+  /// This operation is not supported by an unmodifiable map.
   void addEntries(Iterable<MapEntry<K, V>> entries) {
-    throw new UnsupportedError("Cannot modify unmodifiable map");
+    throw UnsupportedError("Cannot modify unmodifiable map");
   }
 
-  /** This operation is not supported by an unmodifiable map. */
+  /// This operation is not supported by an unmodifiable map.
   void clear() {
-    throw new UnsupportedError("Cannot modify unmodifiable map");
+    throw UnsupportedError("Cannot modify unmodifiable map");
   }
 
-  /** This operation is not supported by an unmodifiable map. */
+  /// This operation is not supported by an unmodifiable map.
   V remove(Object key) {
-    throw new UnsupportedError("Cannot modify unmodifiable map");
+    throw UnsupportedError("Cannot modify unmodifiable map");
   }
 
-  /** This operation is not supported by an unmodifiable map. */
+  /// This operation is not supported by an unmodifiable map.
   void removeWhere(bool test(K key, V value)) {
-    throw new UnsupportedError("Cannot modify unmodifiable map");
+    throw UnsupportedError("Cannot modify unmodifiable map");
   }
 
-  /** This operation is not supported by an unmodifiable map. */
+  /// This operation is not supported by an unmodifiable map.
   V putIfAbsent(K key, V ifAbsent()) {
-    throw new UnsupportedError("Cannot modify unmodifiable map");
+    throw UnsupportedError("Cannot modify unmodifiable map");
   }
 
-  /** This operation is not supported by an unmodifiable map. */
+  /// This operation is not supported by an unmodifiable map.
   V update(K key, V update(V value), {V ifAbsent()}) {
-    throw new UnsupportedError("Cannot modify unmodifiable map");
+    throw UnsupportedError("Cannot modify unmodifiable map");
   }
 
-  /** This operation is not supported by an unmodifiable map. */
+  /// This operation is not supported by an unmodifiable map.
   void updateAll(V update(K key, V value)) {
-    throw new UnsupportedError("Cannot modify unmodifiable map");
+    throw UnsupportedError("Cannot modify unmodifiable map");
   }
 }
 
-/**
- * Wrapper around a class that implements [Map] that only exposes `Map` members.
- *
- * A simple wrapper that delegates all `Map` members to the map provided in the
- * constructor.
- *
- * Base for delegating map implementations like [UnmodifiableMapView].
- */
+/// Wrapper around a class that implements [Map] that only exposes `Map`
+/// members.
+///
+/// A simple wrapper that delegates all `Map` members to the map provided in the
+/// constructor.
+///
+/// Base for delegating map implementations like [UnmodifiableMapView].
 class MapView<K, V> implements Map<K, V> {
   final Map<K, V> _map;
   const MapView(Map<K, V> map) : _map = map;
@@ -380,17 +364,15 @@
   }
 }
 
-/**
- * View of a [Map] that disallow modifying the map.
- *
- * A wrapper around a `Map` that forwards all members to the map provided in
- * the constructor, except for operations that modify the map.
- * Modifying operations throw instead.
- */
+/// View of a [Map] that disallow modifying the map.
+///
+/// A wrapper around a `Map` that forwards all members to the map provided in
+/// the constructor, except for operations that modify the map.
+/// Modifying operations throw instead.
 class UnmodifiableMapView<K, V> extends MapView<K, V>
     with _UnmodifiableMapMixin<K, V> {
   UnmodifiableMapView(Map<K, V> map) : super(map);
 
   Map<RK, RV> cast<RK, RV>() =>
-      new UnmodifiableMapView<RK, RV>(_map.cast<RK, RV>());
+      UnmodifiableMapView<RK, RV>(_map.cast<RK, RV>());
 }
diff --git a/sdk/lib/collection/queue.dart b/sdk/lib/collection/queue.dart
index 7f82357..62994b9 100644
--- a/sdk/lib/collection/queue.dart
+++ b/sdk/lib/collection/queue.dart
@@ -4,140 +4,108 @@
 
 part of dart.collection;
 
-/**
- * A [Queue] is a collection that can be manipulated at both ends. One
- * can iterate over the elements of a queue through [forEach] or with
- * an [Iterator].
- *
- * It is generally not allowed to modify the queue (add or remove entries) while
- * an operation on the queue is being performed, for example during a call to
- * [forEach].
- * Modifying the queue while it is being iterated will most likely break the
- * iteration.
- * This goes both for using the [iterator] directly, or for iterating an
- * `Iterable` returned by a method like [map] or [where].
- */
+/// A [Queue] is a collection that can be manipulated at both ends. One
+/// can iterate over the elements of a queue through [forEach] or with
+/// an [Iterator].
+///
+/// It is generally not allowed to modify the queue (add or remove entries)
+/// while an operation on the queue is being performed, for example during a
+/// call to [forEach].
+/// Modifying the queue while it is being iterated will most likely break the
+/// iteration.
+/// This goes both for using the [iterator] directly, or for iterating an
+/// `Iterable` returned by a method like [map] or [where].
 abstract class Queue<E> implements EfficientLengthIterable<E> {
-  /**
-   * Creates a queue.
-   */
+  /// Creates a queue.
   factory Queue() = ListQueue<E>;
 
-  /**
-   * Creates a queue containing all [elements].
-   *
-   * The element order in the queue is as if the elements were added using
-   * [addLast] in the order provided by [elements.iterator].
-   *
-   * All the [elements] should be instances of [E].
-   * The `elements` iterable itself may have any element type, so this
-   * constructor can be used to down-cast a `Queue`, for example as:
-   * ```dart
-   * Queue<SuperType> superQueue = ...;
-   * Queue<SubType> subQueue =
-   *     new Queue<SubType>.from(superSet.whereType<SubType>());
-   * ```
-   */
+  /// Creates a queue containing all [elements].
+  ///
+  /// The element order in the queue is as if the elements were added using
+  /// [addLast] in the order provided by [elements.iterator].
+  ///
+  /// All the [elements] should be instances of [E].
+  /// The `elements` iterable itself may have any element type, so this
+  /// constructor can be used to down-cast a `Queue`, for example as:
+  /// ```dart
+  /// Queue<SuperType> superQueue = ...;
+  /// Queue<SubType> subQueue =
+  ///     new Queue<SubType>.from(superSet.whereType<SubType>());
+  /// ```
   factory Queue.from(Iterable elements) = ListQueue<E>.from;
 
-  /**
-   * Creates a queue from [elements].
-   *
-   * The element order in the queue is as if the elements were added using
-   * [addLast] in the order provided by [elements.iterator].
-   */
+  /// Creates a queue from [elements].
+  ///
+  /// The element order in the queue is as if the elements were added using
+  /// [addLast] in the order provided by [elements.iterator].
   factory Queue.of(Iterable<E> elements) = ListQueue<E>.of;
 
-  /**
-   * Adapts [source] to be a `Queue<T>`.
-   *
-   * Any time the queue would produce an element that is not a [T],
-   * the element access will throw.
-   *
-   * Any time a [T] value is attempted stored into the adapted queue,
-   * the store will throw unless the value is also an instance of [S].
-   *
-   * If all accessed elements of [source] are actually instances of [T],
-   * and if all elements stored into the returned queue are actually instance
-   * of [S],
-   * then the returned queue can be used as a `Queue<T>`.
-   */
-  static Queue<T> castFrom<S, T>(Queue<S> source) =>
-      new CastQueue<S, T>(source);
+  /// Adapts [source] to be a `Queue<T>`.
+  ///
+  /// Any time the queue would produce an element that is not a [T],
+  /// the element access will throw.
+  ///
+  /// Any time a [T] value is attempted stored into the adapted queue,
+  /// the store will throw unless the value is also an instance of [S].
+  ///
+  /// If all accessed elements of [source] are actually instances of [T],
+  /// and if all elements stored into the returned queue are actually instance
+  /// of [S],
+  /// then the returned queue can be used as a `Queue<T>`.
+  static Queue<T> castFrom<S, T>(Queue<S> source) => CastQueue<S, T>(source);
 
-  /**
-   * Provides a view of this queue as a queue of [R] instances, if necessary.
-   *
-   * If this queue contains only instances of [R], all read operations
-   * will work correctly. If any operation tries to access an element
-   * that is not an instance of [R], the access will throw instead.
-   *
-   * Elements added to the queue (e.g., by using [addFirst] or [addAll])
-   * must be instance of [R] to be valid arguments to the adding function,
-   * and they must be instances of [E] as well to be accepted by
-   * this queue as well.
-   */
+  /// Provides a view of this queue as a queue of [R] instances, if necessary.
+  ///
+  /// If this queue contains only instances of [R], all read operations
+  /// will work correctly. If any operation tries to access an element
+  /// that is not an instance of [R], the access will throw instead.
+  ///
+  /// Elements added to the queue (e.g., by using [addFirst] or [addAll])
+  /// must be instance of [R] to be valid arguments to the adding function,
+  /// and they must be instances of [E] as well to be accepted by
+  /// this queue as well.
   Queue<R> cast<R>();
-  /**
-   * Removes and returns the first element of this queue.
-   *
-   * The queue must not be empty when this method is called.
-   */
+
+  /// Removes and returns the first element of this queue.
+  ///
+  /// The queue must not be empty when this method is called.
   E removeFirst();
 
-  /**
-   * Removes and returns the last element of the queue.
-   *
-   * The queue must not be empty when this method is called.
-   */
+  /// Removes and returns the last element of the queue.
+  ///
+  /// The queue must not be empty when this method is called.
   E removeLast();
 
-  /**
-   * Adds [value] at the beginning of the queue.
-   */
+  /// Adds [value] at the beginning of the queue.
   void addFirst(E value);
 
-  /**
-   * Adds [value] at the end of the queue.
-   */
+  /// Adds [value] at the end of the queue.
   void addLast(E value);
 
-  /**
-   * Adds [value] at the end of the queue.
-   */
+  /// Adds [value] at the end of the queue.
   void add(E value);
 
-  /**
-   * Remove a single instance of [value] from the queue.
-   *
-   * Returns `true` if a value was removed, or `false` if the queue
-   * contained no element equal to [value].
-   */
+  /// Remove a single instance of [value] from the queue.
+  ///
+  /// Returns `true` if a value was removed, or `false` if the queue
+  /// contained no element equal to [value].
   bool remove(Object value);
 
-  /**
-   * Adds all elements of [iterable] at the end of the queue. The
-   * length of the queue is extended by the length of [iterable].
-   */
+  /// Adds all elements of [iterable] at the end of the queue. The
+  /// length of the queue is extended by the length of [iterable].
   void addAll(Iterable<E> iterable);
 
-  /**
-   * Removes all elements matched by [test] from the queue.
-   *
-   * The `test` function must not throw or modify the queue.
-   */
+  /// Removes all elements matched by [test] from the queue.
+  ///
+  /// The `test` function must not throw or modify the queue.
   void removeWhere(bool test(E element));
 
-  /**
-   * Removes all elements not matched by [test] from the queue.
-   *
-   * The `test` function must not throw or modify the queue.
-   */
+  /// Removes all elements not matched by [test] from the queue.
+  ///
+  /// The `test` function must not throw or modify the queue.
   void retainWhere(bool test(E element));
 
-  /**
-   * Removes all elements in the queue. The size of the queue becomes zero.
-   */
+  /// Removes all elements in the queue. The size of the queue becomes zero.
   void clear();
 }
 
@@ -160,10 +128,8 @@
   }
 }
 
-/**
- * An entry in a doubly linked list. It contains a pointer to the next
- * entry, the previous entry, and the boxed element.
- */
+/// An entry in a doubly linked list. It contains a pointer to the next
+/// entry, the previous entry, and the boxed element.
 class DoubleLinkedQueueEntry<E> extends _DoubleLink<DoubleLinkedQueueEntry<E>> {
   /// The element in the queue.
   E element;
@@ -172,12 +138,12 @@
 
   /// Appends the given [e] as entry just after this entry.
   void append(E e) {
-    new DoubleLinkedQueueEntry<E>(e)._link(this, _nextLink);
+    DoubleLinkedQueueEntry<E>(e)._link(this, _nextLink);
   }
 
   /// Prepends the given [e] as entry just before this entry.
   void prepend(E e) {
-    new DoubleLinkedQueueEntry<E>(e)._link(_previousLink, this);
+    DoubleLinkedQueueEntry<E>(e)._link(_previousLink, this);
   }
 
   E remove() {
@@ -192,14 +158,12 @@
   DoubleLinkedQueueEntry<E> nextEntry() => _nextLink;
 }
 
-/**
- * Interface for the link classes used by [DoubleLinkedQueue].
- *
- * Both the [_DoubleLinkedQueueElement] and [_DoubleLinkedQueueSentinel]
- * implement this interface.
- * The entry contains a link back to the queue, so calling `append`
- * or `prepend` can correctly update the element count.
- */
+/// Interface for the link classes used by [DoubleLinkedQueue].
+///
+/// Both the [_DoubleLinkedQueueElement] and [_DoubleLinkedQueueSentinel]
+/// implement this interface.
+/// The entry contains a link back to the queue, so calling `append`
+/// or `prepend` can correctly update the element count.
 abstract class _DoubleLinkedQueueEntry<E> extends DoubleLinkedQueueEntry<E> {
   DoubleLinkedQueue<E> _queue;
   _DoubleLinkedQueueEntry(E element, this._queue) : super(element);
@@ -207,11 +171,11 @@
   DoubleLinkedQueueEntry<E> _asNonSentinelEntry();
 
   void _append(E e) {
-    new _DoubleLinkedQueueElement<E>(e, _queue)._link(this, _nextLink);
+    _DoubleLinkedQueueElement<E>(e, _queue)._link(this, _nextLink);
   }
 
   void _prepend(E e) {
-    new _DoubleLinkedQueueElement<E>(e, _queue)._link(_previousLink, this);
+    _DoubleLinkedQueueElement<E>(e, _queue)._link(_previousLink, this);
   }
 
   E _remove();
@@ -229,12 +193,10 @@
   }
 }
 
-/**
- * The actual entry type used by the [DoubleLinkedQueue].
- *
- * The entry contains a reference to the queue, allowing
- * [append]/[prepend] to update the list length.
- */
+/// The actual entry type used by the [DoubleLinkedQueue].
+///
+/// The entry contains a reference to the queue, allowing
+/// [append]/[prepend] to update the list length.
 class _DoubleLinkedQueueElement<E> extends _DoubleLinkedQueueEntry<E> {
   _DoubleLinkedQueueElement(E element, DoubleLinkedQueue<E> queue)
       : super(element, queue);
@@ -265,14 +227,12 @@
   }
 }
 
-/**
- * A sentinel in a double linked list is used to manipulate the list
- * at both ends.
- * A double linked list has exactly one sentinel,
- * which is the only entry when the list is constructed.
- * Initially, a sentinel has its next and previous entry point to itself.
- * A sentinel does not box any user element.
- */
+/// A sentinel in a double linked list is used to manipulate the list
+/// at both ends.
+/// A double linked list has exactly one sentinel,
+/// which is the only entry when the list is constructed.
+/// Initially, a sentinel has its next and previous entry point to itself.
+/// A sentinel does not box any user element.
 class _DoubleLinkedQueueSentinel<E> extends _DoubleLinkedQueueEntry<E> {
   _DoubleLinkedQueueSentinel(DoubleLinkedQueue<E> queue) : super(null, queue) {
     _previousLink = this;
@@ -283,61 +243,55 @@
     return null;
   }
 
-  /** Hit by, e.g., [DoubleLinkedQueue.removeFirst] if the queue is empty. */
+  /// Hit by, e.g., [DoubleLinkedQueue.removeFirst] if the queue is empty.
   E _remove() {
     throw IterableElementError.noElement();
   }
 
-  /** Hit by, e.g., [DoubleLinkedQueue.first] if the queue is empty. */
+  /// Hit by, e.g., [DoubleLinkedQueue.first] if the queue is empty.
   E get _element {
     throw IterableElementError.noElement();
   }
 }
 
-/**
- * A [Queue] implementation based on a double-linked list.
- *
- * Allows constant time add, remove-at-ends and peek operations.
- */
+/// A [Queue] implementation based on a double-linked list.
+///
+/// Allows constant time add, remove-at-ends and peek operations.
 class DoubleLinkedQueue<E> extends Iterable<E> implements Queue<E> {
   _DoubleLinkedQueueSentinel<E> _sentinel;
   int _elementCount = 0;
 
   DoubleLinkedQueue() {
-    _sentinel = new _DoubleLinkedQueueSentinel<E>(this);
+    _sentinel = _DoubleLinkedQueueSentinel<E>(this);
   }
 
-  /**
-   * Creates a double-linked queue containing all [elements].
-   *
-   * The element order in the queue is as if the elements were added using
-   * [addLast] in the order provided by [elements.iterator].
-   *
-   * All the [elements] should be instances of [E].
-   * The `elements` iterable itself may have any element type, so this
-   * constructor can be used to down-cast a `Queue`, for example as:
-   * ```dart
-   * Queue<SuperType> superQueue = ...;
-   * Queue<SubType> subQueue =
-   *     new DoubleLinkedQueue<SubType>.from(superQueue.whereType<SubType>());
-   * ```
-   */
+  /// Creates a double-linked queue containing all [elements].
+  ///
+  /// The element order in the queue is as if the elements were added using
+  /// [addLast] in the order provided by [elements.iterator].
+  ///
+  /// All the [elements] should be instances of [E].
+  /// The `elements` iterable itself may have any element type, so this
+  /// constructor can be used to down-cast a `Queue`, for example as:
+  /// ```dart
+  /// Queue<SuperType> superQueue = ...;
+  /// Queue<SubType> subQueue =
+  ///     new DoubleLinkedQueue<SubType>.from(superQueue.whereType<SubType>());
+  /// ```
   factory DoubleLinkedQueue.from(Iterable elements) {
-    Queue<E> list = new DoubleLinkedQueue<E>();
+    Queue<E> list = DoubleLinkedQueue<E>();
     for (final e in elements) {
       list.addLast(e);
     }
     return list;
   }
 
-  /**
-   * Creates a double-linked queue from [elements].
-   *
-   * The element order in the queue is as if the elements were added using
-   * [addLast] in the order provided by [elements.iterator].
-   */
+  /// Creates a double-linked queue from [elements].
+  ///
+  /// The element order in the queue is as if the elements were added using
+  /// [addLast] in the order provided by [elements.iterator].
   factory DoubleLinkedQueue.of(Iterable<E> elements) =>
-      new DoubleLinkedQueue<E>()..addAll(elements);
+      DoubleLinkedQueue<E>()..addAll(elements);
 
   Queue<R> cast<R>() => Queue.castFrom<E, R>(this);
   int get length => _elementCount;
@@ -384,7 +338,7 @@
       bool equals = (entry._element == o);
       if (!identical(this, entry._queue)) {
         // Entry must still be in the queue.
-        throw new ConcurrentModificationError(this);
+        throw ConcurrentModificationError(this);
       }
       if (equals) {
         entry._remove();
@@ -402,7 +356,7 @@
       bool matches = test(entry._element);
       if (!identical(this, entry._queue)) {
         // Entry must still be in the queue.
-        throw new ConcurrentModificationError(this);
+        throw ConcurrentModificationError(this);
       }
       _DoubleLinkedQueueEntry<E> next = entry._nextLink; // Cannot be null.
       if (identical(removeMatching, matches)) {
@@ -441,30 +395,26 @@
     throw IterableElementError.tooMany();
   }
 
-  /**
-   * The entry object of the first element in the queue.
-   *
-   * Each element of the queue has an associated [DoubleLinkedQueueEntry].
-   * Returns the entry object corresponding to the first element of the queue.
-   *
-   * The entry objects can also be accessed using [lastEntry],
-   * and they can be iterated using [DoubleLinkedQueueEntry.nextEntry()] and
-   * [DoubleLinkedQueueEntry.previousEntry()].
-   */
+  /// The entry object of the first element in the queue.
+  ///
+  /// Each element of the queue has an associated [DoubleLinkedQueueEntry].
+  /// Returns the entry object corresponding to the first element of the queue.
+  ///
+  /// The entry objects can also be accessed using [lastEntry],
+  /// and they can be iterated using [DoubleLinkedQueueEntry.nextEntry()] and
+  /// [DoubleLinkedQueueEntry.previousEntry()].
   DoubleLinkedQueueEntry<E> firstEntry() {
     return _sentinel.nextEntry();
   }
 
-  /**
-   * The entry object of the last element in the queue.
-   *
-   * Each element of the queue has an associated [DoubleLinkedQueueEntry].
-   * Returns the entry object corresponding to the last element of the queue.
-   *
-   * The entry objects can also be accessed using [firstEntry],
-   * and they can be iterated using [DoubleLinkedQueueEntry.nextEntry()] and
-   * [DoubleLinkedQueueEntry.previousEntry()].
-   */
+  /// The entry object of the last element in the queue.
+  ///
+  /// Each element of the queue has an associated [DoubleLinkedQueueEntry].
+  /// Returns the entry object corresponding to the last element of the queue.
+  ///
+  /// The entry objects can also be accessed using [firstEntry],
+  /// and they can be iterated using [DoubleLinkedQueueEntry.nextEntry()] and
+  /// [DoubleLinkedQueueEntry.previousEntry()].
   DoubleLinkedQueueEntry<E> lastEntry() {
     return _sentinel.previousEntry();
   }
@@ -479,24 +429,22 @@
     _elementCount = 0;
   }
 
-  /**
-   * Calls [action] for each entry object of this double-linked queue.
-   *
-   * Each element of the queue has an associated [DoubleLinkedQueueEntry].
-   * This method iterates the entry objects from first to last and calls
-   * [action] with each object in turn.
-   *
-   * The entry objects can also be accessed using [firstEntry] and [lastEntry],
-   * and iterated using [DoubleLinkedQueueEntry.nextEntry()] and
-   * [DoubleLinkedQueueEntry.previousEntry()].
-   *
-   * The [action] function can use methods on [DoubleLinkedQueueEntry] to remove
-   * the entry or it can insert elements before or after then entry.
-   * If the current entry is removed, iteration continues with the entry that
-   * was following the current entry when [action] was called. Any elements
-   * inserted after the current element before it is removed will not be
-   * visited by the iteration.
-   */
+  /// Calls [action] for each entry object of this double-linked queue.
+  ///
+  /// Each element of the queue has an associated [DoubleLinkedQueueEntry].
+  /// This method iterates the entry objects from first to last and calls
+  /// [action] with each object in turn.
+  ///
+  /// The entry objects can also be accessed using [firstEntry] and [lastEntry],
+  /// and iterated using [DoubleLinkedQueueEntry.nextEntry()] and
+  /// [DoubleLinkedQueueEntry.previousEntry()].
+  ///
+  /// The [action] function can use methods on [DoubleLinkedQueueEntry] to
+  /// remove the entry or it can insert elements before or after then entry.
+  /// If the current entry is removed, iteration continues with the entry that
+  /// was following the current entry when [action] was called. Any elements
+  /// inserted after the current element before it is removed will not be
+  /// visited by the iteration.
   void forEachEntry(void action(DoubleLinkedQueueEntry<E> element)) {
     _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink;
     while (!identical(entry, _sentinel)) {
@@ -510,14 +458,14 @@
       if (identical(this, entry._queue)) {
         next = entry._nextLink;
       } else if (!identical(this, next._queue)) {
-        throw new ConcurrentModificationError(this);
+        throw ConcurrentModificationError(this);
       }
       entry = next;
     }
   }
 
   _DoubleLinkedQueueIterator<E> get iterator {
-    return new _DoubleLinkedQueueIterator<E>(_sentinel);
+    return _DoubleLinkedQueueIterator<E>(_sentinel);
   }
 
   String toString() => IterableBase.iterableToFullString(this, '{', '}');
@@ -541,7 +489,7 @@
     }
     _DoubleLinkedQueueElement<E> elementEntry = _nextEntry;
     if (!identical(_sentinel._queue, elementEntry._queue)) {
-      throw new ConcurrentModificationError(_sentinel._queue);
+      throw ConcurrentModificationError(_sentinel._queue);
     }
     _current = elementEntry._element;
     _nextEntry = elementEntry._nextLink;
@@ -551,15 +499,13 @@
   E get current => _current;
 }
 
-/**
- * List based [Queue].
- *
- * Keeps a cyclic buffer of elements, and grows to a larger buffer when
- * it fills up. This guarantees constant time peek and remove operations, and
- * amortized constant time add operations.
- *
- * The structure is efficient for any queue or stack usage.
- */
+/// List based [Queue].
+///
+/// Keeps a cyclic buffer of elements, and grows to a larger buffer when
+/// it fills up. This guarantees constant time peek and remove operations, and
+/// amortized constant time add operations.
+///
+/// The structure is efficient for any queue or stack usage.
 class ListQueue<E> extends ListIterable<E> implements Queue<E> {
   static const int _INITIAL_CAPACITY = 8;
   List<E> _table;
@@ -567,12 +513,10 @@
   int _tail;
   int _modificationCount = 0;
 
-  /**
-   * Create an empty queue.
-   *
-   * If [initialCapacity] is given, prepare the queue for at least that many
-   * elements.
-   */
+  /// Create an empty queue.
+  ///
+  /// If [initialCapacity] is given, prepare the queue for at least that many
+  /// elements.
   ListQueue([int initialCapacity])
       : _head = 0,
         _tail = 0 {
@@ -582,28 +526,26 @@
       initialCapacity = _nextPowerOf2(initialCapacity);
     }
     assert(_isPowerOf2(initialCapacity));
-    _table = new List<E>(initialCapacity);
+    _table = List<E>(initialCapacity);
   }
 
-  /**
-   * Create a `ListQueue` containing all [elements].
-   *
-   * The elements are added to the queue, as by [addLast], in the order given by
-   * `elements.iterator`.
-   *
-   * All the [elements] should be instances of [E].
-   * The `elements` iterable itself may have any element type, so this
-   * constructor can be used to down-cast a `Queue`, for example as:
-   * ```dart
-   * Queue<SuperType> superQueue = ...;
-   * Queue<SubType> subQueue =
-   *     new ListQueue<SubType>.from(superQueue.whereType<SubType>());
-   * ```
-   */
+  /// Create a `ListQueue` containing all [elements].
+  ///
+  /// The elements are added to the queue, as by [addLast], in the order given
+  /// by `elements.iterator`.
+  ///
+  /// All the [elements] should be instances of [E].
+  /// The `elements` iterable itself may have any element type, so this
+  /// constructor can be used to down-cast a `Queue`, for example as:
+  /// ```dart
+  /// Queue<SuperType> superQueue = ...;
+  /// Queue<SubType> subQueue =
+  ///     new ListQueue<SubType>.from(superQueue.whereType<SubType>());
+  /// ```
   factory ListQueue.from(Iterable elements) {
     if (elements is List) {
       int length = elements.length;
-      ListQueue<E> queue = new ListQueue<E>(length + 1);
+      ListQueue<E> queue = ListQueue<E>(length + 1);
       assert(queue._table.length > length);
       for (int i = 0; i < length; i++) {
         queue._table[i] = elements[i];
@@ -615,7 +557,7 @@
       if (elements is EfficientLengthIterable) {
         capacity = elements.length;
       }
-      ListQueue<E> result = new ListQueue<E>(capacity);
+      ListQueue<E> result = ListQueue<E>(capacity);
       for (final element in elements) {
         result.addLast(element);
       }
@@ -623,19 +565,17 @@
     }
   }
 
-  /**
-   * Create a `ListQueue` from [elements].
-   *
-   * The elements are added to the queue, as by [addLast], in the order given by
-   * `elements.iterator`.
-   */
+  /// Create a `ListQueue` from [elements].
+  ///
+  /// The elements are added to the queue, as by [addLast], in the order given
+  /// by `elements.iterator`.
   factory ListQueue.of(Iterable<E> elements) =>
-      new ListQueue<E>()..addAll(elements);
+      ListQueue<E>()..addAll(elements);
 
   // Iterable interface.
 
   Queue<R> cast<R>() => Queue.castFrom<E, R>(this);
-  Iterator<E> get iterator => new _ListQueueIterator<E>(this);
+  Iterator<E> get iterator => _ListQueueIterator<E>(this);
 
   void forEach(void f(E element)) {
     int modificationCount = _modificationCount;
@@ -670,12 +610,12 @@
     return _table[(_head + index) & (_table.length - 1)];
   }
 
-  List<E> toList({bool growable: true}) {
+  List<E> toList({bool growable = true}) {
     List<E> list;
     if (growable) {
       list = <E>[]..length = length;
     } else {
-      list = new List<E>(length);
+      list = List<E>(length);
     }
     _writeToList(list);
     return list;
@@ -744,22 +684,18 @@
     }
   }
 
-  /**
-   * Remove all elements matched by [test].
-   *
-   * This method is inefficient since it works by repeatedly removing single
-   * elements, each of which can take linear time.
-   */
+  /// Remove all elements matched by [test].
+  ///
+  /// This method is inefficient since it works by repeatedly removing single
+  /// elements, each of which can take linear time.
   void removeWhere(bool test(E element)) {
     _filterWhere(test, true);
   }
 
-  /**
-   * Remove all elements not matched by [test].
-   *
-   * This method is inefficient since it works by repeatedly removing single
-   * elements, each of which can take linear time.
-   */
+  /// Remove all elements not matched by [test].
+  ///
+  /// This method is inefficient since it works by repeatedly removing single
+  /// elements, each of which can take linear time.
   void retainWhere(bool test(E element)) {
     _filterWhere(test, false);
   }
@@ -809,20 +745,16 @@
 
   // Internal helper functions.
 
-  /**
-   * Whether [number] is a power of two.
-   *
-   * Only works for positive numbers.
-   */
+  /// Whether [number] is a power of two.
+  ///
+  /// Only works for positive numbers.
   static bool _isPowerOf2(int number) => (number & (number - 1)) == 0;
 
-  /**
-   * Rounds [number] up to the nearest power of 2.
-   *
-   * If [number] is a power of 2 already, it is returned.
-   *
-   * Only works for positive numbers.
-   */
+  /// Rounds [number] up to the nearest power of 2.
+  ///
+  /// If [number] is a power of 2 already, it is returned.
+  ///
+  /// Only works for positive numbers.
   static int _nextPowerOf2(int number) {
     assert(number > 0);
     number = (number << 1) - 1;
@@ -833,14 +765,14 @@
     }
   }
 
-  /** Check if the queue has been modified during iteration. */
+  /// Check if the queue has been modified during iteration.
   void _checkModification(int expectedModificationCount) {
     if (expectedModificationCount != _modificationCount) {
-      throw new ConcurrentModificationError(this);
+      throw ConcurrentModificationError(this);
     }
   }
 
-  /** Adds element at end of queue. Used by both [add] and [addAll]. */
+  /// Adds element at end of queue. Used by both [add] and [addAll].
   void _add(E element) {
     _table[_tail] = element;
     _tail = (_tail + 1) & (_table.length - 1);
@@ -848,16 +780,14 @@
     _modificationCount++;
   }
 
-  /**
-   * Removes the element at [offset] into [_table].
-   *
-   * Removal is performed by linearly moving elements either before or after
-   * [offset] by one position.
-   *
-   * Returns the new offset of the following element. This may be the same
-   * offset or the following offset depending on how elements are moved
-   * to fill the hole.
-   */
+  /// Removes the element at [offset] into [_table].
+  ///
+  /// Removal is performed by linearly moving elements either before or after
+  /// [offset] by one position.
+  ///
+  /// Returns the new offset of the following element. This may be the same
+  /// offset or the following offset depending on how elements are moved
+  /// to fill the hole.
   int _remove(int offset) {
     int mask = _table.length - 1;
     int startDistance = (offset - _head) & mask;
@@ -886,11 +816,9 @@
     }
   }
 
-  /**
-   * Grow the table when full.
-   */
+  /// Grow the table when full.
   void _grow() {
-    List<E> newTable = new List<E>(_table.length * 2);
+    List<E> newTable = List<E>(_table.length * 2);
     int split = _table.length - _head;
     newTable.setRange(0, split, _table, _head);
     newTable.setRange(split, split + _head, _table, 0);
@@ -913,7 +841,7 @@
     }
   }
 
-  /** Grows the table even if it is not full. */
+  /// Grows the table even if it is not full.
   void _preGrow(int newElementCount) {
     assert(newElementCount >= length);
 
@@ -921,18 +849,16 @@
     // expansion.
     newElementCount += newElementCount >> 1;
     int newCapacity = _nextPowerOf2(newElementCount);
-    List<E> newTable = new List<E>(newCapacity);
+    List<E> newTable = List<E>(newCapacity);
     _tail = _writeToList(newTable);
     _table = newTable;
     _head = 0;
   }
 }
 
-/**
- * Iterator for a [ListQueue].
- *
- * Considers any add or remove operation a concurrent modification.
- */
+/// Iterator for a [ListQueue].
+///
+/// Considers any add or remove operation a concurrent modification.
 class _ListQueueIterator<E> implements Iterator<E> {
   final ListQueue<E> _queue;
   final int _end;
diff --git a/sdk/lib/collection/set.dart b/sdk/lib/collection/set.dart
index 4f21b77..7508b23 100644
--- a/sdk/lib/collection/set.dart
+++ b/sdk/lib/collection/set.dart
@@ -2,28 +2,24 @@
 // 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.
 
-/**
- * Base implementations of [Set].
- */
+/// Base implementations of [Set].
 part of dart.collection;
 
-/**
- * Mixin implementation of [Set].
- *
- * This class provides a base implementation of a `Set` that depends only
- * on the abstract members: [add], [contains], [lookup], [remove],
- * [iterator], [length] and [toSet].
- *
- * Some of the methods assume that `toSet` creates a modifiable set.
- * If using this mixin for an unmodifiable set,
- * where `toSet` should return an unmodifiable set,
- * it's necessary to reimplement
- * [retainAll], [union], [intersection] and [difference].
- *
- * Implementations of `Set` using this mixin should consider also implementing
- * `clear` in constant time. The default implementation works by removing every
- * element.
- */
+/// Mixin implementation of [Set].
+///
+/// This class provides a base implementation of a `Set` that depends only
+/// on the abstract members: [add], [contains], [lookup], [remove],
+/// [iterator], [length] and [toSet].
+///
+/// Some of the methods assume that `toSet` creates a modifiable set.
+/// If using this mixin for an unmodifiable set,
+/// where `toSet` should return an unmodifiable set,
+/// it's necessary to reimplement
+/// [retainAll], [union], [intersection] and [difference].
+///
+/// Implementations of `Set` using this mixin should consider also implementing
+/// `clear` in constant time. The default implementation works by removing every
+/// element.
 abstract class SetMixin<E> implements Set<E> {
   // This class reimplements all of [IterableMixin].
   // If/when Dart mixins get more powerful, we should just create a single
@@ -49,9 +45,9 @@
 
   Set<R> cast<R>() => Set.castFrom<E, R>(this);
   Iterable<E> followedBy(Iterable<E> other) =>
-      new FollowedByIterable<E>.firstEfficient(this, other);
+      FollowedByIterable<E>.firstEfficient(this, other);
 
-  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+  Iterable<T> whereType<T>() => WhereTypeIterable<T>(this);
 
   void clear() {
     removeAll(toList());
@@ -118,15 +114,15 @@
     return result;
   }
 
-  List<E> toList({bool growable: true}) {
-    List<E> result = growable ? (<E>[]..length = length) : new List<E>(length);
+  List<E> toList({bool growable = true}) {
+    List<E> result = growable ? (<E>[]..length = length) : List<E>(length);
     int i = 0;
     for (E element in this) result[i++] = element;
     return result;
   }
 
   Iterable<T> map<T>(T f(E element)) =>
-      new EfficientLengthMappedIterable<E, T>(this, f);
+      EfficientLengthMappedIterable<E, T>(this, f);
 
   E get single {
     if (length > 1) throw IterableElementError.tooMany();
@@ -141,10 +137,10 @@
   // Copied from IterableMixin.
   // Should be inherited if we had multi-level mixins.
 
-  Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f);
+  Iterable<E> where(bool f(E element)) => WhereIterable<E>(this, f);
 
   Iterable<T> expand<T>(Iterable<T> f(E element)) =>
-      new ExpandIterable<E, T>(this, f);
+      ExpandIterable<E, T>(this, f);
 
   void forEach(void f(E element)) {
     for (E element in this) f(element);
@@ -178,7 +174,7 @@
   String join([String separator = ""]) {
     Iterator<E> iterator = this.iterator;
     if (!iterator.moveNext()) return "";
-    StringBuffer buffer = new StringBuffer();
+    StringBuffer buffer = StringBuffer();
     if (separator == null || separator == "") {
       do {
         buffer.write(iterator.current);
@@ -201,19 +197,19 @@
   }
 
   Iterable<E> take(int n) {
-    return new TakeIterable<E>(this, n);
+    return TakeIterable<E>(this, n);
   }
 
   Iterable<E> takeWhile(bool test(E value)) {
-    return new TakeWhileIterable<E>(this, test);
+    return TakeWhileIterable<E>(this, test);
   }
 
   Iterable<E> skip(int n) {
-    return new SkipIterable<E>(this, n);
+    return SkipIterable<E>(this, n);
   }
 
   Iterable<E> skipWhile(bool test(E value)) {
-    return new SkipWhileIterable<E>(this, test);
+    return SkipWhileIterable<E>(this, test);
   }
 
   E get first {
@@ -283,39 +279,35 @@
       if (index == elementIndex) return element;
       elementIndex++;
     }
-    throw new RangeError.index(index, this, "index", null, elementIndex);
+    throw RangeError.index(index, this, "index", null, elementIndex);
   }
 }
 
-/**
- * Base implementation of [Set].
- *
- * This class provides a base implementation of a `Set` that depends only
- * on the abstract members: [add], [contains], [lookup], [remove],
- * [iterator], [length] and [toSet].
- *
- * Some of the methods assume that `toSet` creates a modifiable set.
- * If using this base class for an unmodifiable set,
- * where `toSet` should return an unmodifiable set,
- * it's necessary to reimplement
- * [retainAll], [union], [intersection] and [difference].
- *
- * Implementations of `Set` using this base should consider also implementing
- * `clear` in constant time. The default implementation works by removing every
- * element.
- */
+/// Base implementation of [Set].
+///
+/// This class provides a base implementation of a `Set` that depends only
+/// on the abstract members: [add], [contains], [lookup], [remove],
+/// [iterator], [length] and [toSet].
+///
+/// Some of the methods assume that `toSet` creates a modifiable set.
+/// If using this base class for an unmodifiable set,
+/// where `toSet` should return an unmodifiable set,
+/// it's necessary to reimplement
+/// [retainAll], [union], [intersection] and [difference].
+///
+/// Implementations of `Set` using this base should consider also implementing
+/// `clear` in constant time. The default implementation works by removing every
+/// element.
 abstract class SetBase<E> extends Object with SetMixin<E> {
-  /**
-   * Convert a `Set` to a string as `{each, element, as, string}`.
-   *
-   * Handles circular references where converting one of the elements
-   * to a string ends up converting [set] to a string again.
-   */
+  /// Convert a `Set` to a string as `{each, element, as, string}`.
+  ///
+  /// Handles circular references where converting one of the elements
+  /// to a string ends up converting [set] to a string again.
   static String setToString(Set set) =>
       IterableBase.iterableToFullString(set, '{', '}');
 }
 
-/** Common internal implementation of some [Set] methods. */
+/// Common internal implementation of some [Set] methods.
 // TODO(35548): Make this mix-in SetMixin, by adding `with SetMixin<E>`
 // and removing the copied members below,
 // when analyzer supports const constructors for mixin applications.
@@ -358,9 +350,9 @@
   bool get isNotEmpty => length != 0;
 
   Iterable<E> followedBy(Iterable<E> other) =>
-      new FollowedByIterable<E>.firstEfficient(this, other);
+      FollowedByIterable<E>.firstEfficient(this, other);
 
-  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+  Iterable<T> whereType<T>() => WhereTypeIterable<T>(this);
 
   void clear() {
     removeAll(toList());
@@ -411,15 +403,15 @@
     return toSet()..addAll(other);
   }
 
-  List<E> toList({bool growable: true}) {
-    List<E> result = growable ? (<E>[]..length = length) : new List<E>(length);
+  List<E> toList({bool growable = true}) {
+    List<E> result = growable ? (<E>[]..length = length) : List<E>(length);
     int i = 0;
     for (E element in this) result[i++] = element;
     return result;
   }
 
   Iterable<T> map<T>(T f(E element)) =>
-      new EfficientLengthMappedIterable<E, T>(this, f);
+      EfficientLengthMappedIterable<E, T>(this, f);
 
   E get single {
     if (length > 1) throw IterableElementError.tooMany();
@@ -431,10 +423,10 @@
 
   String toString() => IterableBase.iterableToFullString(this, '{', '}');
 
-  Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f);
+  Iterable<E> where(bool f(E element)) => WhereIterable<E>(this, f);
 
   Iterable<T> expand<T>(Iterable<T> f(E element)) =>
-      new ExpandIterable<E, T>(this, f);
+      ExpandIterable<E, T>(this, f);
 
   void forEach(void f(E element)) {
     for (E element in this) f(element);
@@ -468,7 +460,7 @@
   String join([String separator = ""]) {
     Iterator<E> iterator = this.iterator;
     if (!iterator.moveNext()) return "";
-    StringBuffer buffer = new StringBuffer();
+    StringBuffer buffer = StringBuffer();
     if (separator == null || separator == "") {
       do {
         buffer.write(iterator.current);
@@ -491,19 +483,19 @@
   }
 
   Iterable<E> take(int n) {
-    return new TakeIterable<E>(this, n);
+    return TakeIterable<E>(this, n);
   }
 
   Iterable<E> takeWhile(bool test(E value)) {
-    return new TakeWhileIterable<E>(this, test);
+    return TakeWhileIterable<E>(this, test);
   }
 
   Iterable<E> skip(int n) {
-    return new SkipIterable<E>(this, n);
+    return SkipIterable<E>(this, n);
   }
 
   Iterable<E> skipWhile(bool test(E value)) {
-    return new SkipWhileIterable<E>(this, test);
+    return SkipWhileIterable<E>(this, test);
   }
 
   E get first {
@@ -573,11 +565,11 @@
       if (index == elementIndex) return element;
       elementIndex++;
     }
-    throw new RangeError.index(index, this, "index", null, elementIndex);
+    throw RangeError.index(index, this, "index", null, elementIndex);
   }
 }
 
-/** Class used to implement const sets. */
+/// Class used to implement const sets.
 class _UnmodifiableSet<E> extends _SetBase<E> {
   final Map<E, Null> _map;
 
diff --git a/sdk/lib/collection/splay_tree.dart b/sdk/lib/collection/splay_tree.dart
index 9856d55..5f71934 100644
--- a/sdk/lib/collection/splay_tree.dart
+++ b/sdk/lib/collection/splay_tree.dart
@@ -4,12 +4,10 @@
 
 part of dart.collection;
 
-typedef bool _Predicate<T>(T value);
+typedef _Predicate<T> = bool Function(T value);
 
-/**
- * A node in a splay tree. It holds the sorting key and the left
- * and right children in the tree.
- */
+/// A node in a splay tree. It holds the sorting key and the left
+/// and right children in the tree.
 class _SplayTreeNode<K> {
   final K key;
   _SplayTreeNode<K> left;
@@ -18,24 +16,20 @@
   _SplayTreeNode(this.key);
 }
 
-/**
- * A node in a splay tree based map.
- *
- * A [_SplayTreeNode] that also contains a value
- */
+/// A node in a splay tree based map.
+///
+/// A [_SplayTreeNode] that also contains a value
 class _SplayTreeMapNode<K, V> extends _SplayTreeNode<K> {
   V value;
   _SplayTreeMapNode(K key, this.value) : super(key);
 }
 
-/**
- * A splay tree is a self-balancing binary search tree.
- *
- * It has the additional property that recently accessed elements
- * are quick to access again.
- * It performs basic operations such as insertion, look-up and
- * removal, in O(log(n)) amortized time.
- */
+/// A splay tree is a self-balancing binary search tree.
+///
+/// It has the additional property that recently accessed elements
+/// are quick to access again.
+/// It performs basic operations such as insertion, look-up and
+/// removal, in O(log(n)) amortized time.
 abstract class _SplayTree<K, Node extends _SplayTreeNode<K>> {
   // The root node of the splay tree. It will contain either the last
   // element inserted or the last element looked up.
@@ -49,40 +43,34 @@
   // Number of elements in the splay tree.
   int _count = 0;
 
-  /**
-   * Counter incremented whenever the keys in the map changes.
-   *
-   * Used to detect concurrent modifications.
-   */
+  /// Counter incremented whenever the keys in the map changes.
+  ///
+  /// Used to detect concurrent modifications.
   int _modificationCount = 0;
 
-  /**
-   * Counter incremented whenever the tree structure changes.
-   *
-   * Used to detect that an in-place traversal cannot use
-   * cached information that relies on the tree structure.
-   */
+  /// Counter incremented whenever the tree structure changes.
+  ///
+  /// Used to detect that an in-place traversal cannot use
+  /// cached information that relies on the tree structure.
   int _splayCount = 0;
 
-  /** The comparator that is used for this splay tree. */
+  /// The comparator that is used for this splay tree.
   Comparator<K> get _comparator;
 
-  /** The predicate to determine that a given object is a valid key. */
+  /// The predicate to determine that a given object is a valid key.
   _Predicate get _validKey;
 
-  /** Comparison used to compare keys. */
+  /// Comparison used to compare keys.
   int _compare(K key1, K key2);
 
-  /**
-   * Perform the splay operation for the given key. Moves the node with
-   * the given key to the top of the tree.  If no node has the given
-   * key, the last node on the search path is moved to the top of the
-   * tree. This is the simplified top-down splaying algorithm from:
-   * "Self-adjusting Binary Search Trees" by Sleator and Tarjan.
-   *
-   * Returns the result of comparing the new root of the tree to [key].
-   * Returns -1 if the table is empty.
-   */
+  /// Perform the splay operation for the given key. Moves the node with
+  /// the given key to the top of the tree.  If no node has the given
+  /// key, the last node on the search path is moved to the top of the
+  /// tree. This is the simplified top-down splaying algorithm from:
+  /// "Self-adjusting Binary Search Trees" by Sleator and Tarjan.
+  ///
+  /// Returns the result of comparing the new root of the tree to [key].
+  /// Returns -1 if the table is empty.
   int _splay(K key) {
     if (_root == null) return -1;
 
@@ -177,12 +165,10 @@
     return result;
   }
 
-  /**
-   * Adds a new root node with the given [key] or [value].
-   *
-   * The [comp] value is the result of comparing the existing root's key
-   * with key.
-   */
+  /// Adds a new root node with the given [key] or [value].
+  ///
+  /// The [comp] value is the result of comparing the existing root's key
+  /// with key.
   void _addNewRoot(Node node, int comp) {
     _count++;
     _modificationCount++;
@@ -239,34 +225,31 @@
   return _dynamicCompare;
 }
 
-/**
- * A [Map] of objects that can be ordered relative to each other.
- *
- * The map is based on a self-balancing binary tree. It allows most operations
- * in amortized logarithmic time.
- *
- * Keys of the map are compared using the `compare` function passed in
- * the constructor, both for ordering and for equality.
- * If the map contains only the key `a`, then `map.containsKey(b)`
- * will return `true` if and only if `compare(a, b) == 0`,
- * and the value of `a == b` is not even checked.
- * If the compare function is omitted, the objects are assumed to be
- * [Comparable], and are compared using their [Comparable.compareTo] method.
- * Non-comparable objects (including `null`) will not work as keys
- * in that case.
- *
- * To allow calling [operator []], [remove] or [containsKey] with objects
- * that are not supported by the `compare` function, an extra `isValidKey`
- * predicate function can be supplied. This function is tested before
- * using the `compare` function on an argument value that may not be a [K]
- * value. If omitted, the `isValidKey` function defaults to testing if the
- * value is a [K].
- */
+/// A [Map] of objects that can be ordered relative to each other.
+///
+/// The map is based on a self-balancing binary tree. It allows most operations
+/// in amortized logarithmic time.
+///
+/// Keys of the map are compared using the `compare` function passed in
+/// the constructor, both for ordering and for equality.
+/// If the map contains only the key `a`, then `map.containsKey(b)`
+/// will return `true` if and only if `compare(a, b) == 0`,
+/// and the value of `a == b` is not even checked.
+/// If the compare function is omitted, the objects are assumed to be
+/// [Comparable], and are compared using their [Comparable.compareTo] method.
+/// Non-comparable objects (including `null`) will not work as keys
+/// in that case.
+///
+/// To allow calling [operator []], [remove] or [containsKey] with objects
+/// that are not supported by the `compare` function, an extra `isValidKey`
+/// predicate function can be supplied. This function is tested before
+/// using the `compare` function on an argument value that may not be a [K]
+/// value. If omitted, the `isValidKey` function defaults to testing if the
+/// value is a [K].
 class SplayTreeMap<K, V> extends _SplayTree<K, _SplayTreeMapNode<K, V>>
     with MapMixin<K, V> {
   _SplayTreeMapNode<K, V> _root;
-  final _SplayTreeMapNode<K, V> _dummy =
-      new _SplayTreeMapNode<K, V>(null, null);
+  final _SplayTreeMapNode<K, V> _dummy = _SplayTreeMapNode<K, V>(null, null);
 
   Comparator<K> _comparator;
   _Predicate _validKey;
@@ -275,65 +258,57 @@
       : _comparator = compare ?? _defaultCompare<K>(),
         _validKey = isValidKey ?? ((v) => v is K);
 
-  /**
-   * Creates a [SplayTreeMap] that contains all key/value pairs of [other].
-   *
-   * The keys must all be instances of [K] and the values of [V].
-   * The [other] map itself can have any type.
-   */
+  /// Creates a [SplayTreeMap] that contains all key/value pairs of [other].
+  ///
+  /// The keys must all be instances of [K] and the values of [V].
+  /// The [other] map itself can have any type.
   factory SplayTreeMap.from(Map other,
       [int compare(K key1, K key2), bool isValidKey(potentialKey)]) {
-    SplayTreeMap<K, V> result = new SplayTreeMap<K, V>(compare, isValidKey);
+    SplayTreeMap<K, V> result = SplayTreeMap<K, V>(compare, isValidKey);
     other.forEach((k, v) {
       result[k] = v;
     });
     return result;
   }
 
-  /**
-   * Creates a [SplayTreeMap] that contains all key/value pairs of [other].
-   */
+  /// Creates a [SplayTreeMap] that contains all key/value pairs of [other].
   factory SplayTreeMap.of(Map<K, V> other,
           [int compare(K key1, K key2), bool isValidKey(potentialKey)]) =>
-      new SplayTreeMap<K, V>(compare, isValidKey)..addAll(other);
+      SplayTreeMap<K, V>(compare, isValidKey)..addAll(other);
 
-  /**
-   * Creates a [SplayTreeMap] where the keys and values are computed from the
-   * [iterable].
-   *
-   * For each element of the [iterable] this constructor computes a key/value
-   * pair, by applying [key] and [value] respectively.
-   *
-   * The keys of the key/value pairs do not need to be unique. The last
-   * occurrence of a key will simply overwrite any previous value.
-   *
-   * If no functions are specified for [key] and [value] the default is to
-   * use the iterable value itself.
-   */
+  /// Creates a [SplayTreeMap] where the keys and values are computed from the
+  /// [iterable].
+  ///
+  /// For each element of the [iterable] this constructor computes a key/value
+  /// pair, by applying [key] and [value] respectively.
+  ///
+  /// The keys of the key/value pairs do not need to be unique. The last
+  /// occurrence of a key will simply overwrite any previous value.
+  ///
+  /// If no functions are specified for [key] and [value] the default is to
+  /// use the iterable value itself.
   factory SplayTreeMap.fromIterable(Iterable iterable,
       {K key(element),
       V value(element),
       int compare(K key1, K key2),
       bool isValidKey(potentialKey)}) {
-    SplayTreeMap<K, V> map = new SplayTreeMap<K, V>(compare, isValidKey);
+    SplayTreeMap<K, V> map = SplayTreeMap<K, V>(compare, isValidKey);
     MapBase._fillMapWithMappedIterable(map, iterable, key, value);
     return map;
   }
 
-  /**
-   * Creates a [SplayTreeMap] associating the given [keys] to [values].
-   *
-   * This constructor iterates over [keys] and [values] and maps each element of
-   * [keys] to the corresponding element of [values].
-   *
-   * If [keys] contains the same object multiple times, the last occurrence
-   * overwrites the previous value.
-   *
-   * It is an error if the two [Iterable]s don't have the same length.
-   */
+  /// Creates a [SplayTreeMap] associating the given [keys] to [values].
+  ///
+  /// This constructor iterates over [keys] and [values] and maps each element
+  /// of [keys] to the corresponding element of [values].
+  ///
+  /// If [keys] contains the same object multiple times, the last occurrence
+  /// overwrites the previous value.
+  ///
+  /// It is an error if the two [Iterable]s don't have the same length.
   factory SplayTreeMap.fromIterables(Iterable<K> keys, Iterable<V> values,
       [int compare(K key1, K key2), bool isValidKey(potentialKey)]) {
-    SplayTreeMap<K, V> map = new SplayTreeMap<K, V>(compare, isValidKey);
+    SplayTreeMap<K, V> map = SplayTreeMap<K, V>(compare, isValidKey);
     MapBase._fillMapWithIterables(map, keys, values);
     return map;
   }
@@ -361,7 +336,7 @@
   }
 
   void operator []=(K key, V value) {
-    if (key == null) throw new ArgumentError(key);
+    if (key == null) throw ArgumentError(key);
     // Splay on the key to move the last node on the search path for
     // the key to the root of the tree.
     int comp = _splay(key);
@@ -369,11 +344,11 @@
       _root.value = value;
       return;
     }
-    _addNewRoot(new _SplayTreeMapNode(key, value), comp);
+    _addNewRoot(_SplayTreeMapNode(key, value), comp);
   }
 
   V putIfAbsent(K key, V ifAbsent()) {
-    if (key == null) throw new ArgumentError(key);
+    if (key == null) throw ArgumentError(key);
     int comp = _splay(key);
     if (comp == 0) {
       return _root.value;
@@ -382,14 +357,14 @@
     int splayCount = _splayCount;
     V value = ifAbsent();
     if (modificationCount != _modificationCount) {
-      throw new ConcurrentModificationError(this);
+      throw ConcurrentModificationError(this);
     }
     if (splayCount != _splayCount) {
       comp = _splay(key);
       // Key is still not there, otherwise _modificationCount would be changed.
       assert(comp != 0);
     }
-    _addNewRoot(new _SplayTreeMapNode(key, value), comp);
+    _addNewRoot(_SplayTreeMapNode(key, value), comp);
     return value;
   }
 
@@ -406,7 +381,7 @@
   bool get isNotEmpty => !isEmpty;
 
   void forEach(void f(K key, V value)) {
-    Iterator<_SplayTreeNode<K>> nodes = new _SplayTreeNodeIterator<K>(this);
+    Iterator<_SplayTreeNode<K>> nodes = _SplayTreeNodeIterator<K>(this);
     while (nodes.moveNext()) {
       _SplayTreeMapNode<K, V> node = nodes.current;
       f(node.key, node.value);
@@ -431,7 +406,7 @@
       while (node != null) {
         if (node.value == value) return true;
         if (initialSplayCount != _splayCount) {
-          throw new ConcurrentModificationError(this);
+          throw ConcurrentModificationError(this);
         }
         if (node.right != null && visit(node.right)) return true;
         node = node.left;
@@ -442,32 +417,26 @@
     return visit(_root);
   }
 
-  Iterable<K> get keys => new _SplayTreeKeyIterable<K>(this);
+  Iterable<K> get keys => _SplayTreeKeyIterable<K>(this);
 
-  Iterable<V> get values => new _SplayTreeValueIterable<K, V>(this);
+  Iterable<V> get values => _SplayTreeValueIterable<K, V>(this);
 
-  /**
-   * Get the first key in the map. Returns [:null:] if the map is empty.
-   */
+  /// Get the first key in the map. Returns [:null:] if the map is empty.
   K firstKey() {
     if (_root == null) return null;
     return _first.key;
   }
 
-  /**
-   * Get the last key in the map. Returns [:null:] if the map is empty.
-   */
+  /// Get the last key in the map. Returns [:null:] if the map is empty.
   K lastKey() {
     if (_root == null) return null;
     return _last.key;
   }
 
-  /**
-   * Get the last key in the map that is strictly smaller than [key]. Returns
-   * [:null:] if no key was not found.
-   */
+  /// Get the last key in the map that is strictly smaller than [key]. Returns
+  /// [:null:] if no key was not found.
   K lastKeyBefore(K key) {
-    if (key == null) throw new ArgumentError(key);
+    if (key == null) throw ArgumentError(key);
     if (_root == null) return null;
     int comp = _splay(key);
     if (comp < 0) return _root.key;
@@ -479,12 +448,10 @@
     return node.key;
   }
 
-  /**
-   * Get the first key in the map that is strictly larger than [key]. Returns
-   * [:null:] if no key was not found.
-   */
+  /// Get the first key in the map that is strictly larger than [key]. Returns
+  /// [:null:] if no key was not found.
   K firstKeyAfter(K key) {
-    if (key == null) throw new ArgumentError(key);
+    if (key == null) throw ArgumentError(key);
     if (_root == null) return null;
     int comp = _splay(key);
     if (comp > 0) return _root.key;
@@ -499,37 +466,32 @@
 
 abstract class _SplayTreeIterator<K, T> implements Iterator<T> {
   final _SplayTree<K, _SplayTreeNode<K>> _tree;
-  /**
-   * Worklist of nodes to visit.
-   *
-   * These nodes have been passed over on the way down in a
-   * depth-first left-to-right traversal. Visiting each node,
-   * and their right subtrees will visit the remainder of
-   * the nodes of a full traversal.
-   *
-   * Only valid as long as the original tree isn't reordered.
-   */
+
+  /// Worklist of nodes to visit.
+  ///
+  /// These nodes have been passed over on the way down in a
+  /// depth-first left-to-right traversal. Visiting each node,
+  /// and their right subtrees will visit the remainder of
+  /// the nodes of a full traversal.
+  ///
+  /// Only valid as long as the original tree isn't reordered.
   final List<_SplayTreeNode<K>> _workList = <_SplayTreeNode<K>>[];
 
-  /**
-   * Original modification counter of [_tree].
-   *
-   * Incremented on [_tree] when a key is added or removed.
-   * If it changes, iteration is aborted.
-   *
-   * Not final because some iterators may modify the tree knowingly,
-   * and they update the modification count in that case.
-   */
+  /// Original modification counter of [_tree].
+  ///
+  /// Incremented on [_tree] when a key is added or removed.
+  /// If it changes, iteration is aborted.
+  ///
+  /// Not final because some iterators may modify the tree knowingly,
+  /// and they update the modification count in that case.
   int _modificationCount;
 
-  /**
-   * Count of splay operations on [_tree] when [_workList] was built.
-   *
-   * If the splay count on [_tree] increases, [_workList] becomes invalid.
-   */
+  /// Count of splay operations on [_tree] when [_workList] was built.
+  ///
+  /// If the splay count on [_tree] increases, [_workList] becomes invalid.
   int _splayCount;
 
-  /** Current node. */
+  /// Current node.
   _SplayTreeNode<K> _currentNode;
 
   _SplayTreeIterator(_SplayTree<K, _SplayTreeNode<K>> tree)
@@ -565,14 +527,12 @@
     }
   }
 
-  /**
-   * Called when the tree structure of the tree has changed.
-   *
-   * This can be caused by a splay operation.
-   * If the key-set changes, iteration is aborted before getting
-   * here, so we know that the keys are the same as before, it's
-   * only the tree that has been reordered.
-   */
+  /// Called when the tree structure of the tree has changed.
+  ///
+  /// This can be caused by a splay operation.
+  /// If the key-set changes, iteration is aborted before getting
+  /// here, so we know that the keys are the same as before, it's
+  /// only the tree that has been reordered.
   void _rebuildWorkList(_SplayTreeNode<K> currentNode) {
     assert(_workList.isNotEmpty);
     _workList.clear();
@@ -587,7 +547,7 @@
 
   bool moveNext() {
     if (_modificationCount != _tree._modificationCount) {
-      throw new ConcurrentModificationError(_tree);
+      throw ConcurrentModificationError(_tree);
     }
     // Picks the next element in the worklist as current.
     // Updates the worklist with the left-most path of the current node's
@@ -614,11 +574,10 @@
   _SplayTreeKeyIterable(this._tree);
   int get length => _tree._count;
   bool get isEmpty => _tree._count == 0;
-  Iterator<K> get iterator => new _SplayTreeKeyIterator<K>(_tree);
+  Iterator<K> get iterator => _SplayTreeKeyIterator<K>(_tree);
 
   Set<K> toSet() {
-    SplayTreeSet<K> set =
-        new SplayTreeSet<K>(_tree._comparator, _tree._validKey);
+    SplayTreeSet<K> set = SplayTreeSet<K>(_tree._comparator, _tree._validKey);
     set._count = _tree._count;
     set._root = set._copyNode(_tree._root);
     return set;
@@ -630,7 +589,7 @@
   _SplayTreeValueIterable(this._map);
   int get length => _map._count;
   bool get isEmpty => _map._count == 0;
-  Iterator<V> get iterator => new _SplayTreeValueIterator<K, V>(_map);
+  Iterator<V> get iterator => _SplayTreeValueIterator<K, V>(_map);
 }
 
 class _SplayTreeKeyIterator<K> extends _SplayTreeIterator<K, K> {
@@ -655,76 +614,70 @@
   _SplayTreeNode<K> _getValue(_SplayTreeNode<K> node) => node;
 }
 
-/**
- * A [Set] of objects that can be ordered relative to each other.
- *
- * The set is based on a self-balancing binary tree. It allows most operations
- * in amortized logarithmic time.
- *
- * Elements of the set are compared using the `compare` function passed in
- * the constructor, both for ordering and for equality.
- * If the set contains only an object `a`, then `set.contains(b)`
- * will return `true` if and only if `compare(a, b) == 0`,
- * and the value of `a == b` is not even checked.
- * If the compare function is omitted, the objects are assumed to be
- * [Comparable], and are compared using their [Comparable.compareTo] method.
- * Non-comparable objects (including `null`) will not work as an element
- * in that case.
- */
+/// A [Set] of objects that can be ordered relative to each other.
+///
+/// The set is based on a self-balancing binary tree. It allows most operations
+/// in amortized logarithmic time.
+///
+/// Elements of the set are compared using the `compare` function passed in
+/// the constructor, both for ordering and for equality.
+/// If the set contains only an object `a`, then `set.contains(b)`
+/// will return `true` if and only if `compare(a, b) == 0`,
+/// and the value of `a == b` is not even checked.
+/// If the compare function is omitted, the objects are assumed to be
+/// [Comparable], and are compared using their [Comparable.compareTo] method.
+/// Non-comparable objects (including `null`) will not work as an element
+/// in that case.
 class SplayTreeSet<E> extends _SplayTree<E, _SplayTreeNode<E>>
     with IterableMixin<E>, SetMixin<E> {
   _SplayTreeNode<E> _root;
-  final _SplayTreeNode<E> _dummy = new _SplayTreeNode<E>(null);
+  final _SplayTreeNode<E> _dummy = _SplayTreeNode<E>(null);
 
   Comparator<E> _comparator;
   _Predicate _validKey;
 
-  /**
-   * Create a new [SplayTreeSet] with the given compare function.
-   *
-   * If the [compare] function is omitted, it defaults to [Comparable.compare],
-   * and the elements must be comparable.
-   *
-   * A provided `compare` function may not work on all objects. It may not even
-   * work on all `E` instances.
-   *
-   * For operations that add elements to the set, the user is supposed to not
-   * pass in objects that doesn't work with the compare function.
-   *
-   * The methods [contains], [remove], [lookup], [removeAll] or [retainAll]
-   * are typed to accept any object(s), and the [isValidKey] test can used to
-   * filter those objects before handing them to the `compare` function.
-   *
-   * If [isValidKey] is provided, only values satisfying `isValidKey(other)`
-   * are compared using the `compare` method in the methods mentioned above.
-   * If the `isValidKey` function returns false for an object, it is assumed to
-   * not be in the set.
-   *
-   * If omitted, the `isValidKey` function defaults to checking against the
-   * type parameter: `other is E`.
-   */
+  /// Create a new [SplayTreeSet] with the given compare function.
+  ///
+  /// If the [compare] function is omitted, it defaults to [Comparable.compare],
+  /// and the elements must be comparable.
+  ///
+  /// A provided `compare` function may not work on all objects. It may not even
+  /// work on all `E` instances.
+  ///
+  /// For operations that add elements to the set, the user is supposed to not
+  /// pass in objects that doesn't work with the compare function.
+  ///
+  /// The methods [contains], [remove], [lookup], [removeAll] or [retainAll]
+  /// are typed to accept any object(s), and the [isValidKey] test can used to
+  /// filter those objects before handing them to the `compare` function.
+  ///
+  /// If [isValidKey] is provided, only values satisfying `isValidKey(other)`
+  /// are compared using the `compare` method in the methods mentioned above.
+  /// If the `isValidKey` function returns false for an object, it is assumed to
+  /// not be in the set.
+  ///
+  /// If omitted, the `isValidKey` function defaults to checking against the
+  /// type parameter: `other is E`.
   SplayTreeSet([int compare(E key1, E key2), bool isValidKey(potentialKey)])
       : _comparator = compare ?? _defaultCompare<E>(),
         _validKey = isValidKey ?? ((v) => v is E);
 
-  /**
-   * Creates a [SplayTreeSet] that contains all [elements].
-   *
-   * The set works as if created by `new SplayTreeSet<E>(compare, isValidKey)`.
-   *
-   * All the [elements] should be instances of [E] and valid arguments to
-   * [compare].
-   * The `elements` iterable itself may have any element type, so this
-   * constructor can be used to down-cast a `Set`, for example as:
-   * ```dart
-   * Set<SuperType> superSet = ...;
-   * Set<SubType> subSet =
-   *     new SplayTreeSet<SubType>.from(superSet.whereType<SubType>());
-   * ```
-   */
+  /// Creates a [SplayTreeSet] that contains all [elements].
+  ///
+  /// The set works as if created by `new SplayTreeSet<E>(compare, isValidKey)`.
+  ///
+  /// All the [elements] should be instances of [E] and valid arguments to
+  /// [compare].
+  /// The `elements` iterable itself may have any element type, so this
+  /// constructor can be used to down-cast a `Set`, for example as:
+  /// ```dart
+  /// Set<SuperType> superSet = ...;
+  /// Set<SubType> subSet =
+  ///     new SplayTreeSet<SubType>.from(superSet.whereType<SubType>());
+  /// ```
   factory SplayTreeSet.from(Iterable elements,
       [int compare(E key1, E key2), bool isValidKey(potentialKey)]) {
-    SplayTreeSet<E> result = new SplayTreeSet<E>(compare, isValidKey);
+    SplayTreeSet<E> result = SplayTreeSet<E>(compare, isValidKey);
     for (final element in elements) {
       E e = element;
       result.add(e);
@@ -732,26 +685,24 @@
     return result;
   }
 
-  /**
-   * Creates a [SplayTreeSet] from [elements].
-   *
-   * The set works as if created by `new SplayTreeSet<E>(compare, isValidKey)`.
-   *
-   * All the [elements] should be valid as arguments to the [compare] function.
-   */
+  /// Creates a [SplayTreeSet] from [elements].
+  ///
+  /// The set works as if created by `new SplayTreeSet<E>(compare, isValidKey)`.
+  ///
+  /// All the [elements] should be valid as arguments to the [compare] function.
   factory SplayTreeSet.of(Iterable<E> elements,
           [int compare(E key1, E key2), bool isValidKey(potentialKey)]) =>
-      new SplayTreeSet(compare, isValidKey)..addAll(elements);
+      SplayTreeSet(compare, isValidKey)..addAll(elements);
 
   Set<T> _newSet<T>() =>
-      new SplayTreeSet<T>((T a, T b) => _comparator(a as E, b as E), _validKey);
+      SplayTreeSet<T>((T a, T b) => _comparator(a as E, b as E), _validKey);
 
   Set<R> cast<R>() => Set.castFrom<E, R>(this, newSet: _newSet);
   int _compare(E e1, E e2) => _comparator(e1, e2);
 
   // From Iterable.
 
-  Iterator<E> get iterator => new _SplayTreeKeyIterator<E>(this);
+  Iterator<E> get iterator => _SplayTreeKeyIterator<E>(this);
 
   int get length => _count;
   bool get isEmpty => _root == null;
@@ -781,7 +732,7 @@
   bool add(E element) {
     int compare = _splay(element);
     if (compare == 0) return false;
-    _addNewRoot(new _SplayTreeNode(element), compare);
+    _addNewRoot(_SplayTreeNode(element), compare);
     return true;
   }
 
@@ -794,7 +745,7 @@
     for (E element in elements) {
       int compare = _splay(element);
       if (compare != 0) {
-        _addNewRoot(new _SplayTreeNode(element), compare);
+        _addNewRoot(_SplayTreeNode(element), compare);
       }
     }
   }
@@ -807,12 +758,12 @@
 
   void retainAll(Iterable<Object> elements) {
     // Build a set with the same sense of equality as this set.
-    SplayTreeSet<E> retainSet = new SplayTreeSet<E>(_comparator, _validKey);
+    SplayTreeSet<E> retainSet = SplayTreeSet<E>(_comparator, _validKey);
     int modificationCount = _modificationCount;
     for (Object object in elements) {
       if (modificationCount != _modificationCount) {
         // The iterator should not have side effects.
-        throw new ConcurrentModificationError(this);
+        throw ConcurrentModificationError(this);
       }
       // Equivalent to this.contains(object).
       if (_validKey(object) && _splay(object) == 0) {
@@ -835,7 +786,7 @@
   }
 
   Set<E> intersection(Set<Object> other) {
-    Set<E> result = new SplayTreeSet<E>(_comparator, _validKey);
+    Set<E> result = SplayTreeSet<E>(_comparator, _validKey);
     for (E element in this) {
       if (other.contains(element)) result.add(element);
     }
@@ -843,7 +794,7 @@
   }
 
   Set<E> difference(Set<Object> other) {
-    Set<E> result = new SplayTreeSet<E>(_comparator, _validKey);
+    Set<E> result = SplayTreeSet<E>(_comparator, _validKey);
     for (E element in this) {
       if (!other.contains(element)) result.add(element);
     }
@@ -855,7 +806,7 @@
   }
 
   SplayTreeSet<E> _clone() {
-    var set = new SplayTreeSet<E>(_comparator, _validKey);
+    var set = SplayTreeSet<E>(_comparator, _validKey);
     set._count = _count;
     set._root = _copyNode(_root);
     return set;
@@ -865,7 +816,7 @@
   // Works on _SplayTreeMapNode as well, but only copies the keys,
   _SplayTreeNode<E> _copyNode(_SplayTreeNode<E> node) {
     if (node == null) return null;
-    return new _SplayTreeNode<E>(node.key)
+    return _SplayTreeNode<E>(node.key)
       ..left = _copyNode(node.left)
       ..right = _copyNode(node.right);
   }
diff --git a/sdk/lib/core/num.dart b/sdk/lib/core/num.dart
index afad926..33b8177 100644
--- a/sdk/lib/core/num.dart
+++ b/sdk/lib/core/num.dart
@@ -100,6 +100,7 @@
    * print(double.infinity < double.nan);  // => false
    * print(double.nan < double.infinity);  // => false
    * print(double.nan == double.infinity);  // => false
+   * ```
    */
   int compareTo(num other);
 
diff --git a/sdk/lib/developer/developer.dart b/sdk/lib/developer/developer.dart
index 6c3fa82..c446fdf 100644
--- a/sdk/lib/developer/developer.dart
+++ b/sdk/lib/developer/developer.dart
@@ -30,7 +30,7 @@
 /// Returns the value of [when]. Some debuggers may display [message].
 ///
 /// NOTE: When invoked, the isolate will not return until a debugger
-/// continues execution. When running in the Dart VM the behaviour is the same
+/// continues execution. When running in the Dart VM, the behaviour is the same
 /// regardless of whether or not a debugger is connected. When compiled to
 /// JavaScript, this uses the "debugger" statement, and behaves exactly as
 /// that does.
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index 6e43fb7..6a737fe 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -40,7 +40,7 @@
  *
  * An `Isolate` object is a reference to an isolate, usually different from
  * the current isolate.
- * It represents, and can be used control, the other isolate.
+ * It represents, and can be used to control, the other isolate.
  *
  * When spawning a new isolate, the spawning isolate receives an `Isolate`
  * object representing the new isolate when the spawn operation succeeds.
diff --git a/sdk/lib/vmservice/running_isolates.dart b/sdk/lib/vmservice/running_isolates.dart
index 5e7b6dd..24b155c 100644
--- a/sdk/lib/vmservice/running_isolates.dart
+++ b/sdk/lib/vmservice/running_isolates.dart
@@ -185,6 +185,7 @@
       Map<String, dynamic> params = _setupParams();
       params['isolateId'] = _message.params['isolateId'];
       params['kernelBytes'] = kernelBase64;
+      params['disableBreakpoints'] = _message.params['disableBreakpoints'];
       Map runParams = {
         'method': '_evaluateCompiledExpression',
         'id': _message.serial,
diff --git a/tests/co19_2/co19_2-dart2js.status b/tests/co19_2/co19_2-dart2js.status
index a4d8adc..25a153a 100644
--- a/tests/co19_2/co19_2-dart2js.status
+++ b/tests/co19_2/co19_2-dart2js.status
@@ -4,9 +4,13 @@
 
 [ $compiler == dart2js ]
 Language/Expressions/Spawning_an_Isolate/new_isolate_t01: SkipByDesign
+LanguageFeatures/Control-flow-collections/*: Skip
 LibTest/io/*: SkipByDesign # dart:io not supported.
 LibTest/isolate/*: SkipByDesign # dart:isolate not supported.
 
+[ $compiler == dartdevk ]
+LanguageFeatures/Control-flow-collections/*: Skip
+
 [ $builder_tag != run_webgl_tests && $compiler == dart2js ]
 LayoutTests/fast/canvas/webgl*: Skip # Only run WebGL on special builders, issue 29961
 
diff --git a/tests/co19_2/co19_2-kernel.status b/tests/co19_2/co19_2-kernel.status
index 3339868..f732f93 100644
--- a/tests/co19_2/co19_2-kernel.status
+++ b/tests/co19_2/co19_2-kernel.status
@@ -3,19 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == dartk ]
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A02_t01: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t01: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t02: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A04_t01: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t01: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t02: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t01: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t02: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A04_t01: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A02_t01: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_t01: DartkCrash
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_t02: DartkCrash, CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A04_t01: DartkCrash
+LanguageFeatures/Control-flow-collections/*: Skip
 LanguageFeatures/Set-literals/semantics_A05_t02: RuntimeError
 LanguageFeatures/Set-literals/syntax_compatibility_A01_t02: RuntimeError
 LanguageFeatures/Spread-collections/ConstSpreads_A01_t01: CompileTimeError
@@ -65,6 +53,7 @@
 LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t04: RuntimeError
 LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t05/none: RuntimeError
 LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t06/none: RuntimeError
+LanguageFeatures/Control-flow-collections/*: Skip
 LanguageFeatures/Set-literals/semantics_A05_t02: RuntimeError
 LanguageFeatures/Set-literals/syntax_compatibility_A01_t02: RuntimeError
 LanguageFeatures/Spread-collections/ConstSpreads_A01_t01: DartkCrash
@@ -137,9 +126,88 @@
 Language/Statements/For/syntax_t13: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
 Language/Statements/For/syntax_t20: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
 LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t03: Crash
-LanguageFeatures/Spread-collections/Ambiguity_A01_t05/01: MissingCompileTimeError
-LanguageFeatures/Spread-collections/Ambiguity_A01_t05/02: MissingCompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A03_t02/12: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A02_t03: CompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A02_t04: CompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/01: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/03: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/04: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/05: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/06: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/07: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/08: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/09: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/10: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/11: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/12: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A03_t02/14: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A04_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A05_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A06_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A07_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/const_collections_A07_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A02_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A04_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A04_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A04_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A04_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A02_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A04_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A04_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/scoping_A01_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/scoping_A02_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A01_t01/01: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A01_t01/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A01_t01/03: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A02_t01/01: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A02_t01/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A02_t01/03: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A03_t01/01: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A03_t01/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A03_t01/03: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A04_t01/01: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A04_t01/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A04_t01/03: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A04_t01/04: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/01: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/05: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/06: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/09: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/10: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/11: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/12: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/17: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/18: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/19: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/20: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/21: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/22: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/23: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/24: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/syntax_A01_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/syntax_A01_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/syntax_A01_t03: CompileTimeError
+LanguageFeatures/Control-flow-collections/syntax_A02_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/syntax_A02_t02: CompileTimeError
+LanguageFeatures/Control-flow-collections/syntax_A03_t01/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/type_inference_A01_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/type_inference_A04_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/type_inference_A05_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/type_inference_A06_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/type_inference_A08_t01: CompileTimeError
+LanguageFeatures/Spread-collections/Ambiguity_A02_t02/01: MissingCompileTimeError
+LanguageFeatures/Spread-collections/Ambiguity_A02_t03: CompileTimeError
 LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/01: MissingCompileTimeError
 LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/02: MissingCompileTimeError
 LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/03: MissingCompileTimeError
@@ -148,18 +216,17 @@
 LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/06: MissingCompileTimeError
 LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/07: MissingCompileTimeError
 LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/08: MissingCompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Map_A01_t01: CompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Map_A02_t02: CompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Map_A02_t03: CompileTimeError
+LanguageFeatures/Spread-collections/DynamicSemantics_Map_A02_t01: CompileTimeError
 LanguageFeatures/Spread-collections/NullAware_A01_t01: CompileTimeError
 LanguageFeatures/Spread-collections/NullAware_A01_t02: CompileTimeError
 LanguageFeatures/Spread-collections/NullAware_A01_t03: CompileTimeError
 LanguageFeatures/Spread-collections/NullAware_A01_t04: CompileTimeError
+LanguageFeatures/Spread-collections/NullAware_A01_t05: CompileTimeError
+LanguageFeatures/Spread-collections/NullAware_A01_t06: CompileTimeError
 LanguageFeatures/Spread-collections/StaticSemantic_A04_t01/04: MissingCompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A06_t01/01: MissingCompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A06_t01/02: MissingCompileTimeError
+LanguageFeatures/Spread-collections/StaticSemantic_A04_t02/04: MissingCompileTimeError
 LanguageFeatures/Spread-collections/StaticSemantic_A06_t01/04: MissingCompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A06_t01/05: MissingCompileTimeError
+LanguageFeatures/Spread-collections/StaticSemantic_A08_t01/02: MissingCompileTimeError
 
 [ $runtime == vm ]
 LibTest/collection/ListBase/ListBase_class_A01_t02: Pass, Slow # Does many calls
@@ -243,12 +310,17 @@
 Language/Expressions/Shift/syntax_t01: CompileTimeError
 Language/Expressions/Unary_Expressions/syntax_t10: CompileTimeError
 Language/Expressions/Unary_Expressions/syntax_t27: CompileTimeError
-Language/Generics/class_A01_t02/none: CompileTimeError
-Language/Generics/syntax_t21: CompileTimeError
+Language/Generics/syntax_t20: CompileTimeError
+Language/Generics/syntax_t22: CompileTimeError
 Language/Generics/syntax_t23: CompileTimeError
 Language/Generics/syntax_t24: CompileTimeError
 Language/Generics/syntax_t25: CompileTimeError
-Language/Generics/syntax_t26: CompileTimeError
+Language/Generics/syntax_t27/none: CompileTimeError
+Language/Generics/typedef_A01_t01: CompileTimeError
+Language/Generics/typedef_A01_t06/none: CompileTimeError
+Language/Generics/typedef_A01_t07: CompileTimeError
+Language/Generics/typedef_A01_t08: CompileTimeError
+Language/Generics/typedef_A01_t10: CompileTimeError
 Language/Libraries_and_Scripts/Imports/library_name_t01: MissingCompileTimeError # Expects an error, but this is a warning in Dart 2
 Language/Mixins/Mixin_Application/abstract_t09: Crash
 Language/Mixins/Mixin_Application/abstract_t10: Crash
@@ -265,7 +337,14 @@
 Language/Mixins/Mixin_Application/interfaces_t07: Crash
 Language/Mixins/Mixin_Application/static_warning_t01: MissingCompileTimeError # Mixin super equirement
 Language/Mixins/Mixin_Application/superclass_t03: Crash
-Language/Mixins/Mixin_Application/superinterfaces_t07: MissingCompileTimeError
+Language/Mixins/Mixin_Application/superclass_t04: Crash
+Language/Mixins/Mixin_Application/superinterfaces_t10: Crash
+Language/Mixins/Mixin_Application/superinterfaces_t11: Crash
+Language/Mixins/Mixin_Application/superinterfaces_t12: CompileTimeError
+Language/Mixins/Mixin_Application/superinterfaces_t13: Crash
+Language/Mixins/Mixin_Application/superinterfaces_t14: Crash
+Language/Mixins/Mixin_Application/syntax_t26: Crash
+Language/Mixins/Mixin_Application/warning_t04: Crash
 Language/Mixins/declaring_constructor_t05: MissingCompileTimeError # Mixin constructor
 Language/Mixins/declaring_constructor_t06: MissingCompileTimeError # Mixin constructor
 Language/Overview/Privacy/private_and_public_t11: CompileTimeError
@@ -292,6 +371,41 @@
 Language/Types/Type_Aliases/syntax_t02: CompileTimeError
 Language/Types/Type_Aliases/syntax_t03: CompileTimeError
 Language/Types/Type_Aliases/syntax_t04: CompileTimeError
+Language/Types/Type_Aliases/syntax_t20: CompileTimeError
+Language/Types/Type_Aliases/syntax_t21: CompileTimeError
+LanguageFeatures/Constant-update-2018/CastOperator_A01_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/CastOperator_A02_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/CastOperator_A02_t02: CompileTimeError
+LanguageFeatures/Constant-update-2018/CastOperator_A04_t02/none: CompileTimeError
+LanguageFeatures/Constant-update-2018/EqualityOperator_A01_t09: MissingCompileTimeError
+LanguageFeatures/Constant-update-2018/EqualityOperator_A01_t10: MissingCompileTimeError
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/NewOperators_A01_t02: CompileTimeError
+LanguageFeatures/Constant-update-2018/NewOperators_A02_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/NewOperators_A02_t02: CompileTimeError
+LanguageFeatures/Constant-update-2018/NewOperators_A02_t05: CompileTimeError
+LanguageFeatures/Constant-update-2018/NewOperators_A02_t06: CompileTimeError
+LanguageFeatures/Constant-update-2018/NewOperators_A02_t09: CompileTimeError
+LanguageFeatures/Constant-update-2018/NewOperators_A02_t10: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A01_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A01_t07: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A02_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A02_t08: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A03_t01: Crash
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A03_t02: Crash
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A03_t05: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A03_t06: CompileTimeError
+
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A04_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A04_t02: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A04_t03: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A04_t05: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A04_t06: CompileTimeError
+LanguageFeatures/Constant-update-2018/ShortCircuitOperators_A04_t07: CompileTimeError
+LanguageFeatures/Constant-update-2018/TypeTestOperator_A01_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/TypeTestOperator_A01_t02: CompileTimeError
+LanguageFeatures/Constant-update-2018/TypeTestOperator_A02_t01: CompileTimeError
+LanguageFeatures/Constant-update-2018/TypeTestOperator_A02_t02: CompileTimeError
 LanguageFeatures/Constant_update2018/CastOperator_A01_t01: CompileTimeError
 LanguageFeatures/Constant_update2018/CastOperator_A02_t01: CompileTimeError
 LanguageFeatures/Constant_update2018/CastOperator_A02_t02: CompileTimeError
@@ -343,54 +457,6 @@
 LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t04/none: CompileTimeError
 LanguageFeatures/Constant_update2018/TypeTestOperator_A04_t01/none: CompileTimeError
 LanguageFeatures/Constant_update2018/TypeTestOperator_A04_t02/none: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A01_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A02_t03: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A02_t04: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A04_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A05_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A06_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A07_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A07_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/const_collections_A07_t03: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A01_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A04_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A01_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A04_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A01_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A04_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/scoping_A01_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/scoping_A02_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A01_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A02_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A03_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A04_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A05_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A06_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A07_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A08_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A09_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A10_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_errors_A11_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_semantics_A01_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_semantics_A01_t02: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_semantics_A02_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/static_semantics_A02_t02: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/syntax_A01_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/syntax_A01_t02: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/syntax_A01_t03: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/syntax_A02_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/syntax_A02_t02: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/syntax_A03_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_inference_A01_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_inference_A02_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_inference_A03_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_inference_A04_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_inference_A05_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_inference_A06_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_inference_A07_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_inference_A08_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_promotion_A01_t01: CompileTimeError, Crash, Pass # This feature is not implemented yet
-LanguageFeatures/Control-flow-collections/type_promotion_A01_t02: CompileTimeError, Crash, Pass # This feature is not implemented yet
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t01: Crash
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t02: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t03: Crash
@@ -659,58 +725,14 @@
 LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t04/01: MissingCompileTimeError
 LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t04/02: MissingCompileTimeError
 LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t10: CompileTimeError
-LanguageFeatures/Spread-collections/Ambiguity_A01_t01: CompileTimeError
-LanguageFeatures/Spread-collections/Ambiguity_A01_t03: CompileTimeError
-LanguageFeatures/Spread-collections/Ambiguity_A01_t05: MissingCompileTimeError
-LanguageFeatures/Spread-collections/Ambiguity_A01_t06: MissingCompileTimeError
-LanguageFeatures/Spread-collections/Ambiguity_A01_t07: CompileTimeError
 LanguageFeatures/Spread-collections/Ambiguity_A02_t01/01: MissingCompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A01_t02: CompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A03_t02/12: MissingCompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/01: MissingCompileTimeError
 LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/02: MissingCompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/03: MissingCompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/04: MissingCompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/05: MissingCompileTimeError
 LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/06: MissingCompileTimeError
 LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/07: MissingCompileTimeError
 LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/08: MissingCompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A06_t02: CompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A06_t03: CompileTimeError
-LanguageFeatures/Spread-collections/ConstSpreads_A07_t03: CompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Set_A02_t01: CompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Set_A02_t02: CompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Set_A02_t03: CompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Set_A02_t05: CompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Set_A02_t07: CompileTimeError
-LanguageFeatures/Spread-collections/DynamicSemantics_Set_A02_t08: CompileTimeError
-LanguageFeatures/Spread-collections/NullAware_A02_t02: CompileTimeError
-LanguageFeatures/Spread-collections/NullAware_A02_t03: CompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A01_t01: CompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A01_t03: CompileTimeError
 LanguageFeatures/Spread-collections/StaticSemantic_A01_t05: CompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A01_t06: MissingCompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A02_t02: CompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A05_t01/none: CompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A05_t02/none: CompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A06_t01/01: MissingCompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A06_t01/02: MissingCompileTimeError
 LanguageFeatures/Spread-collections/StaticSemantic_A06_t01/04: MissingCompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A06_t01/05: MissingCompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A07_t01/none: CompileTimeError
-LanguageFeatures/Spread-collections/StaticSemantic_A08_t01/none: CompileTimeError
-LanguageFeatures/Spread-collections/Syntax_A01_t03: CompileTimeError
-LanguageFeatures/Spread-collections/Syntax_A02_t01: CompileTimeError
-LanguageFeatures/Spread-collections/Syntax_A02_t02: CompileTimeError
-LanguageFeatures/Spread-collections/Syntax_A02_t04: CompileTimeError
-LanguageFeatures/Spread-collections/Syntax_A02_t06: CompileTimeError
 LanguageFeatures/Spread-collections/Syntax_A02_t08: CompileTimeError
-LanguageFeatures/Spread-collections/Syntax_A02_t09: CompileTimeError
-LanguageFeatures/Spread-collections/Syntax_A02_t10: CompileTimeError
-LanguageFeatures/Spread-collections/TypeInference_A01_t01: CompileTimeError
-LanguageFeatures/Spread-collections/TypeInference_A01_t02: CompileTimeError
-LanguageFeatures/Spread-collections/TypeInference_A02_t01: CompileTimeError
-LanguageFeatures/Spread-collections/TypeInference_A03_t01: CompileTimeError
 LanguageFeatures/Super-mixins/covariance_t03: MissingCompileTimeError # Issue 35111
 LanguageFeatures/Super-mixins/covariance_t06: MissingCompileTimeError # Issue 35111
 LanguageFeatures/Super-mixins/covariance_t07: MissingCompileTimeError # Issue 35111
@@ -727,18 +749,6 @@
 LanguageFeatures/Constant_update2018/NewOperators_A02_t02: Pass
 LanguageFeatures/Constant_update2018/NewOperators_A02_t04: Pass
 LanguageFeatures/Constant_update2018/NewOperators_A02_t05: Pass
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A02_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A04_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A04_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A02_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A04_t01: CompileTimeError
 LibTest/collection/ListBase/ListBase_class_A01_t02: Crash # Issue http://dartbug.com/35242
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Crash # Issue http://dartbug.com/35242
 LibTest/core/List/List_class_A01_t02: Crash # Issue http://dartbug.com/35242
@@ -819,34 +829,6 @@
 LibTest/isolate/Isolate/ping_A03_t02: RuntimeError, Pass
 LibTest/isolate/Isolate/removeErrorListener_A02_t01: Crash, Pass
 
-[ $arch != simdbc64 && $compiler == dartk ]
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/01: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/02: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/03: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/04: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/05: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/06: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/07: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/08: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/09: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/10: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/11: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/12: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/13: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/14: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/15: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/16: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/21: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/22: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/23: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/24: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/25: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/26: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/27: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/28: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/29: DartkCrash
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/30: DartkCrash
-
 [ $compiler != dart2js && $runtime != vm && $fasta ]
 Language/Classes/Constructors/Constant_Constructors/invalid_constant_initializer_t02: MissingCompileTimeError # Issue 34192
 Language/Expressions/Constants/exception_t01: MissingCompileTimeError # Issue 31936
@@ -887,49 +869,6 @@
 LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t01: Crash
 LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t02: Crash
 LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t03: Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/01: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/02: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/03: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/04: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/05: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/06: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/07: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/08: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/09: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/10: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/11: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/12: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/13: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/14: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/15: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/16: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/17: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/18: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/19: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/20: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/21: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/22: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/23: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/24: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/25: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/26: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/27: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/28: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/29: Crash, Pass
-LanguageFeatures/Control-flow-collections/const_collections_A08_t01/30: Crash, Pass
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A02_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A04_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A04_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A02_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A04_t01: CompileTimeError
 
 [ $runtime == vm && $system == linux && ($compiler == dartk || $compiler == dartkb) ]
 LibTest/io/Link/stat_A01_t01: RuntimeError
diff --git a/tests/compiler/dart2js/analyses/analysis_helper.dart b/tests/compiler/dart2js/analyses/analysis_helper.dart
index 715352e..6505445 100644
--- a/tests/compiler/dart2js/analyses/analysis_helper.dart
+++ b/tests/compiler/dart2js/analyses/analysis_helper.dart
@@ -69,6 +69,7 @@
 }
 
 class StaticTypeVisitorBase extends StaticTypeVisitor {
+  @override
   VariableScopeModel variableScopeModel;
 
   StaticTypeVisitorBase(
@@ -95,7 +96,7 @@
       // Skip synthetic .dill members.
       return;
     }
-    variableScopeModel = ScopeModel.computeScopeModel(node)?.variableScopeModel;
+    variableScopeModel = new ScopeModel.from(node).variableScopeModel;
     super.visitProcedure(node);
     variableScopeModel = null;
   }
@@ -106,7 +107,7 @@
       // Skip synthetic .dill members.
       return;
     }
-    variableScopeModel = ScopeModel.computeScopeModel(node)?.variableScopeModel;
+    variableScopeModel = new ScopeModel.from(node).variableScopeModel;
     super.visitField(node);
     variableScopeModel = null;
   }
@@ -117,7 +118,7 @@
       // Skip synthetic .dill members.
       return;
     }
-    variableScopeModel = ScopeModel.computeScopeModel(node)?.variableScopeModel;
+    variableScopeModel = new ScopeModel.from(node).variableScopeModel;
     super.visitConstructor(node);
     variableScopeModel = null;
   }
@@ -291,6 +292,7 @@
     }
   }
 
+  @override
   ir.DartType visitNode(ir.Node node) {
     ir.DartType staticType = node?.accept(this);
     assert(
diff --git a/tests/compiler/dart2js/analyses/api_allowed.json b/tests/compiler/dart2js/analyses/api_allowed.json
index 3139ef5..a7a08a3 100644
--- a/tests/compiler/dart2js/analyses/api_allowed.json
+++ b/tests/compiler/dart2js/analyses/api_allowed.json
@@ -28,8 +28,8 @@
     "Dynamic invocation of '_js_helper::_execGlobal'.": 1,
     "Dynamic access of 'start'.": 1,
     "Dynamic access of 'end'.": 1,
-    "Dynamic access of 'length'.": 4,
-    "Dynamic invocation of '[]'.": 2,
+    "Dynamic access of 'length'.": 3,
+    "Dynamic invocation of '[]'.": 1,
     "Dynamic invocation of 'call'.": 13,
     "Dynamic invocation of 'codeUnitAt'.": 2,
     "Dynamic access of 'iterator'.": 2,
@@ -244,4 +244,4 @@
     "Dynamic access of 'port'.": 1,
     "Dynamic invocation of 'dart._http::_toJSON'.": 1
   }
-}
\ No newline at end of file
+}
diff --git a/tests/compiler/dart2js/analyses/dart2js_allowed.json b/tests/compiler/dart2js/analyses/dart2js_allowed.json
index a095c40..de743f0 100644
--- a/tests/compiler/dart2js/analyses/dart2js_allowed.json
+++ b/tests/compiler/dart2js/analyses/dart2js_allowed.json
@@ -270,12 +270,6 @@
   "pkg/compiler/lib/src/ssa/value_set.dart": {
     "Dynamic invocation of 'add'.": 2
   },
-  "pkg/compiler/lib/src/inferrer/node_tracer.dart": {
-    "Dynamic access of 'receiver'.": 1,
-    "Dynamic access of 'selector'.": 3,
-    "Dynamic access of 'isIndex'.": 1,
-    "Dynamic access of 'name'.": 2
-  },
   "pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart": {
     "Dynamic access of 'keys'.": 1,
     "Dynamic invocation of 'toSet'.": 1,
diff --git a/tests/compiler/dart2js/analysis_options.yaml b/tests/compiler/dart2js/analysis_options.yaml
index 40dc4a9..efa1621 100644
--- a/tests/compiler/dart2js/analysis_options.yaml
+++ b/tests/compiler/dart2js/analysis_options.yaml
@@ -3,13 +3,15 @@
 # BSD-style license that can be found in the LICENSE file.
 
 analyzer:
-  language:
-    enableSuperMixins: false
-
   errors:
     todo: ignore
     deprecated_member_use: ignore
 
   exclude:
-    - data/*
-    - sourcemaps/data/*
+    - '**/data/*'
+    - '**/model_data/*'
+    - 'deferred_loading/libs/*'
+
+linter:
+  rules:
+    - annotate_overrides
diff --git a/tests/compiler/dart2js/closure/closure_test.dart b/tests/compiler/dart2js/closure/closure_test.dart
index 26d0d92..da6b882 100644
--- a/tests/compiler/dart2js/closure/closure_test.dart
+++ b/tests/compiler/dart2js/closure/closure_test.dart
@@ -95,6 +95,7 @@
           ? closureRepresentationInfoStack.head
           : null;
 
+  @override
   visitFunctionExpression(ir.FunctionExpression node) {
     ClosureRepresentationInfo info = closureDataLookup.getClosureInfo(node);
     pushMember(info.callMethod);
@@ -104,6 +105,7 @@
     popMember();
   }
 
+  @override
   visitFunctionDeclaration(ir.FunctionDeclaration node) {
     ClosureRepresentationInfo info = closureDataLookup.getClosureInfo(node);
     pushMember(info.callMethod);
@@ -113,18 +115,21 @@
     popMember();
   }
 
+  @override
   visitForStatement(ir.ForStatement node) {
     pushLoopNode(node);
     super.visitForStatement(node);
     popLoop();
   }
 
+  @override
   visitWhileStatement(ir.WhileStatement node) {
     pushLoopNode(node);
     super.visitWhileStatement(node);
     popLoop();
   }
 
+  @override
   visitForInStatement(ir.ForInStatement node) {
     pushLoopNode(node);
     super.visitForInStatement(node);
diff --git a/tests/compiler/dart2js/codegen/model_data/capture.dart b/tests/compiler/dart2js/codegen/model_data/capture.dart
index ca9279e..5e44fb0 100644
--- a/tests/compiler/dart2js/codegen/model_data/capture.dart
+++ b/tests/compiler/dart2js/codegen/model_data/capture.dart
@@ -4,7 +4,7 @@
 
 /*element: method1:params=0*/
 @pragma('dart2js:noInline')
-method1([a]) => /*params=0*/ () => a;
+method1([a]) => /*access=[a],params=0*/ () => a;
 
 class Class {
   /*element: Class.f:emitted*/
@@ -13,14 +13,14 @@
 
   /*element: Class.capture:params=0*/
   @pragma('dart2js:noInline')
-  Class.capture([a]) : f = (/*params=0*/ () => a);
+  Class.capture([a]) : f = (/*access=[a],params=0*/ () => a);
 
   // TODO(johnniwinther): Remove the redundant assignment of elided boxed
   // parameters.
   /*element: Class.box:assign=[a,a],params=0*/
   @pragma('dart2js:noInline')
   Class.box([a])
-      : f = (/*assign=[a],params=0*/ () {
+      : f = (/*access=[_box_0],assign=[a],params=0*/ () {
           a = 42;
         });
 
@@ -30,12 +30,12 @@
 class Subclass extends Class {
   /*element: Subclass.capture:params=0*/
   @pragma('dart2js:noInline')
-  Subclass.capture([a]) : super.internal(/*params=0*/ () => a);
+  Subclass.capture([a]) : super.internal(/*access=[a],params=0*/ () => a);
 
   /*element: Subclass.box:assign=[a,a],params=0*/
   @pragma('dart2js:noInline')
   Subclass.box([a])
-      : super.internal(/*assign=[a],params=0*/ () {
+      : super.internal(/*access=[_box_0],assign=[a],params=0*/ () {
           a = 42;
         });
 }
diff --git a/tests/compiler/dart2js/codegen/model_data/regress_36222.dart b/tests/compiler/dart2js/codegen/model_data/regress_36222.dart
new file mode 100644
index 0000000..8ab6ea3
--- /dev/null
+++ b/tests/compiler/dart2js/codegen/model_data/regress_36222.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, 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.
+
+typedef int BinaryFunc(int x, int y);
+
+class A {
+  const A({this.foo = A.defaultFoo});
+
+  /*element: A.defaultFoo:params=2*/
+  static int defaultFoo(int x, int y) {
+    return x + y;
+  }
+
+  /*element: A.foo:elided,stubCalls=[foo$2:call$2(arg0,arg1),foo$2:main_A_defaultFoo$closure(0)]*/
+  final BinaryFunc foo;
+}
+
+/*element: test:calls=[foo$2(2)],params=1*/
+@pragma('dart2js:assumeDynamic')
+@pragma('dart2js:noInline')
+test(dynamic a) => a.foo(1, 2);
+
+/*element: main:calls=[test(1)],params=0*/
+main() {
+  test(new A());
+}
diff --git a/tests/compiler/dart2js/codegen/model_test.dart b/tests/compiler/dart2js/codegen/model_test.dart
index 84cda3f..af0b3c8 100644
--- a/tests/compiler/dart2js/codegen/model_test.dart
+++ b/tests/compiler/dart2js/codegen/model_test.dart
@@ -59,6 +59,8 @@
   static const String parameterCount = 'params';
   static const String call = 'calls';
   static const String parameterStub = 'stubs';
+  static const String callStubCall = 'stubCalls';
+  static const String callStubAccesses = 'stubAccesses';
   static const String isEmitted = 'emitted';
   static const String isElided = 'elided';
   static const String assignment = 'assign';
@@ -83,6 +85,75 @@
       : _programLookup = new ProgramLookup(compiler),
         super(reporter, actualMap);
 
+  void registerCalls(Features features, String tag, js.Node node,
+      {String prefix = '', Set<js.PropertyAccess> handledAccesses}) {
+    forEachNode(node, onCall: (js.Call node) {
+      js.Node target = node.target;
+      if (target is js.PropertyAccess) {
+        js.Node selector = target.selector;
+        bool fixedNameCall = false;
+        String name;
+        if (selector is js.Name) {
+          name = selector.key;
+          fixedNameCall = selector is StringBackedName;
+        } else if (selector is js.LiteralString) {
+          /// Call to fixed backend name, so we include the argument
+          /// values to test encoding of optional parameters in native
+          /// methods.
+          name = selector.value.substring(1, selector.value.length - 1);
+          fixedNameCall = true;
+        }
+        if (name != null) {
+          if (fixedNameCall) {
+            String arguments = node.arguments.map(js.nodeToString).join(',');
+            features.addElement(tag, '${prefix}${name}(${arguments})');
+          } else {
+            features.addElement(
+                tag, '${prefix}${name}(${node.arguments.length})');
+          }
+          handledAccesses?.add(target);
+        }
+      }
+    });
+  }
+
+  void registerAccesses(Features features, String tag, js.Node code,
+      {String prefix = '', Set<js.PropertyAccess> handledAccesses}) {
+    forEachNode(code, onPropertyAccess: (js.PropertyAccess node) {
+      if (handledAccesses?.contains(node) ?? false) {
+        return;
+      }
+
+      js.Node receiver = node.receiver;
+      String receiverName;
+      if (receiver is js.VariableUse) {
+        receiverName = receiver.name;
+        if (receiverName == receiverName.toUpperCase() &&
+            receiverName != r'$') {
+          // Skip holder access.
+          receiverName = null;
+        }
+      } else if (receiver is js.This) {
+        receiverName = 'this';
+      }
+
+      js.Node selector = node.selector;
+      String name;
+      if (selector is js.Name) {
+        name = selector.key;
+      } else if (selector is js.LiteralString) {
+        /// Call to fixed backend name, so we include the argument
+        /// values to test encoding of optional parameters in native
+        /// methods.
+        name = selector.value.substring(1, selector.value.length - 1);
+      }
+
+      if (receiverName != null && name != null) {
+        features.addElement(tag, '${prefix}${name}');
+      }
+    });
+  }
+
   Features getMemberValue(MemberEntity member) {
     if (member is FieldEntity) {
       Field field = _programLookup.getField(member);
@@ -115,6 +186,16 @@
         registerFlags(Tags.getterFlags, field.getterFlags);
         registerFlags(Tags.setterFlags, field.setterFlags);
 
+        Class cls = _programLookup.getClass(member.enclosingClass);
+        for (StubMethod stub in cls.callStubs) {
+          if (stub.element == member) {
+            registerCalls(features, Tags.callStubCall, stub.code,
+                prefix: '${stub.name.key}:');
+            registerAccesses(features, Tags.callStubAccesses, stub.code,
+                prefix: '${stub.name.key}:');
+          }
+        }
+
         return features;
       }
       StaticField staticField = _programLookup.getStaticField(member);
@@ -137,42 +218,12 @@
 
         Set<js.PropertyAccess> handledAccesses = new Set();
 
-        void registerCalls(String tag, js.Node node, [String prefix = '']) {
-          forEachNode(node, onCall: (js.Call node) {
-            js.Node target = node.target;
-            if (target is js.PropertyAccess) {
-              js.Node selector = target.selector;
-              bool fixedNameCall = false;
-              String name;
-              if (selector is js.Name) {
-                name = selector.key;
-                fixedNameCall = selector is StringBackedName;
-              } else if (selector is js.LiteralString) {
-                /// Call to fixed backend name, so we include the argument
-                /// values to test encoding of optional parameters in native
-                /// methods.
-                name = selector.value.substring(1, selector.value.length - 1);
-                fixedNameCall = true;
-              }
-              if (name != null) {
-                if (fixedNameCall) {
-                  String arguments =
-                      node.arguments.map(js.nodeToString).join(',');
-                  features.addElement(tag, '${prefix}${name}(${arguments})');
-                } else {
-                  features.addElement(
-                      tag, '${prefix}${name}(${node.arguments.length})');
-                }
-                handledAccesses.add(target);
-              }
-            }
-          });
-        }
-
-        registerCalls(Tags.call, code);
+        registerCalls(features, Tags.call, code,
+            handledAccesses: handledAccesses);
         if (method is DartMethod) {
           for (ParameterStubMethod stub in method.parameterStubs) {
-            registerCalls(Tags.parameterStub, stub.code, '${stub.name.key}:');
+            registerCalls(features, Tags.parameterStub, stub.code,
+                prefix: '${stub.name.key}:', handledAccesses: handledAccesses);
           }
         }
 
@@ -193,37 +244,8 @@
           }
         });
 
-        forEachNode(code, onPropertyAccess: (js.PropertyAccess node) {
-          if (handledAccesses.contains(node)) {
-            return;
-          }
-
-          js.Node receiver = node.receiver;
-          String receiverName;
-          if (receiver is js.VariableUse) {
-            receiverName = receiver.name;
-            if (receiverName == receiverName.toUpperCase() &&
-                receiverName != r'$') {
-              // Skip holder access.
-              receiverName = null;
-            }
-          }
-
-          js.Node selector = node.selector;
-          String name;
-          if (selector is js.Name) {
-            name = selector.key;
-          } else if (selector is js.LiteralString) {
-            /// Call to fixed backend name, so we include the argument
-            /// values to test encoding of optional parameters in native
-            /// methods.
-            name = selector.value.substring(1, selector.value.length - 1);
-          }
-
-          if (receiverName != null && name != null) {
-            features.addElement(Tags.propertyAccess, '${name}');
-          }
-        });
+        registerAccesses(features, Tags.propertyAccess, code,
+            handledAccesses: handledAccesses);
 
         forEachNode(code, onSwitch: (js.Switch node) {
           features.add(Tags.switchCase);
diff --git a/tests/compiler/dart2js/end_to_end/bad_output_io_test.dart b/tests/compiler/dart2js/end_to_end/bad_output_io_test.dart
index b386ea1..ba55341 100644
--- a/tests/compiler/dart2js/end_to_end/bad_output_io_test.dart
+++ b/tests/compiler/dart2js/end_to_end/bad_output_io_test.dart
@@ -29,21 +29,33 @@
 
 class CollectingFormattingDiagnosticHandler
     implements FormattingDiagnosticHandler {
+  @override
   final provider = null;
+  @override
   bool showWarnings = true;
+  @override
   bool showHints = true;
+  @override
   bool verbose = true;
+  @override
   bool isAborting = false;
+  @override
   bool enableColors = false;
+  @override
   bool throwOnError = false;
+  @override
   bool autoReadFileUri = false;
+  @override
   var lastKind = null;
 
+  @override
   final int FATAL = 0;
+  @override
   final int INFO = 1;
 
   final messages = [];
 
+  @override
   void info(var message, [kind = Diagnostic.VERBOSE_INFO]) {
     messages.add([message, kind]);
   }
@@ -58,12 +70,15 @@
     report(null, uri, begin, end, message, kind);
   }
 
+  @override
   String prefixMessage(String message, Diagnostic kind) {
     return message;
   }
 
+  @override
   int fatalCount;
 
+  @override
   int throwOnErrorCount;
 }
 
diff --git a/tests/compiler/dart2js/end_to_end/exit_code_test.dart b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
index c891f34..aea5404 100644
--- a/tests/compiler/dart2js/end_to_end/exit_code_test.dart
+++ b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
@@ -32,6 +32,7 @@
   final String testMarker;
   final String testType;
   final Function onTest;
+  @override
   TestDiagnosticReporter reporter;
 
   TestCompiler(
@@ -54,6 +55,7 @@
     return new TestBackend(this);
   }
 
+  @override
   Future<bool> run(Uri uri) {
     test('Compiler.run');
     return super.run(uri);
@@ -98,6 +100,7 @@
 }
 
 class TestBackend extends JavaScriptBackend {
+  @override
   final TestCompiler compiler;
   TestBackend(TestCompiler compiler)
       : this.compiler = compiler,
@@ -116,6 +119,7 @@
 
 class TestDiagnosticReporter extends DiagnosticReporterWrapper {
   TestCompiler compiler;
+  @override
   DiagnosticReporter reporter;
 
   @override
diff --git a/tests/compiler/dart2js/end_to_end/library_env_test.dart b/tests/compiler/dart2js/end_to_end/library_env_test.dart
index e215c89..45421c4 100644
--- a/tests/compiler/dart2js/end_to_end/library_env_test.dart
+++ b/tests/compiler/dart2js/end_to_end/library_env_test.dart
@@ -49,6 +49,7 @@
 class DummyCompilerInput implements CompilerInput {
   const DummyCompilerInput();
 
+  @override
   Future<Input> readFromUri(Uri uri,
       {InputKind inputKind: InputKind.UTF8}) async {
     if (uri.path.endsWith("libraries.json")) {
@@ -62,6 +63,7 @@
 class DummyCompilerDiagnostics implements CompilerDiagnostics {
   const DummyCompilerDiagnostics();
 
+  @override
   report(code, uri, begin, end, text, kind) {
     throw "should not be needed";
   }
diff --git a/tests/compiler/dart2js/end_to_end/user_crash_test.dart b/tests/compiler/dart2js/end_to_end/user_crash_test.dart
index a17fbf2..1f21642 100644
--- a/tests/compiler/dart2js/end_to_end/user_crash_test.dart
+++ b/tests/compiler/dart2js/end_to_end/user_crash_test.dart
@@ -96,7 +96,9 @@
 }
 
 class CrashingMap implements Map<String, String> {
+  @override
   operator [](_) => throw EXCEPTION;
 
+  @override
   noSuchMethod(_) => null;
 }
diff --git a/tests/compiler/dart2js/equivalence/check_helpers.dart b/tests/compiler/dart2js/equivalence/check_helpers.dart
index cef161e..2465a58 100644
--- a/tests/compiler/dart2js/equivalence/check_helpers.dart
+++ b/tests/compiler/dart2js/equivalence/check_helpers.dart
@@ -53,6 +53,7 @@
     return ' $indent';
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     printOn(sb, '');
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence.dart b/tests/compiler/dart2js/equivalence/id_equivalence.dart
index 4d76541..d664020 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence.dart
@@ -34,14 +34,17 @@
 
   const IdValue(this.id, this.value);
 
+  @override
   int get hashCode => id.hashCode * 13 + value.hashCode * 17;
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! IdValue) return false;
     return id == other.id && value == other.value;
   }
 
+  @override
   String toString() => idToString(id, value);
 
   static String idToString(Id id, String value) {
@@ -131,6 +134,7 @@
 class ElementId implements Id {
   final String className;
   final String memberName;
+  @override
   final bool isGlobal;
 
   factory ElementId(String text, {bool isGlobal: false}) {
@@ -145,44 +149,55 @@
 
   ElementId.internal(this.memberName, {this.className, this.isGlobal: false});
 
+  @override
   int get hashCode => className.hashCode * 13 + memberName.hashCode * 17;
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! ElementId) return false;
     return className == other.className && memberName == other.memberName;
   }
 
+  @override
   IdKind get kind => IdKind.element;
 
   String get name => className != null ? '$className.$memberName' : memberName;
 
+  @override
   String get descriptor => 'member $name';
 
+  @override
   String toString() => 'element:$name';
 }
 
 /// Id for a class.
 class ClassId implements Id {
   final String className;
+  @override
   final bool isGlobal;
 
   ClassId(this.className, {this.isGlobal: false});
 
+  @override
   int get hashCode => className.hashCode * 13;
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! ClassId) return false;
     return className == other.className;
   }
 
+  @override
   IdKind get kind => IdKind.cls;
 
   String get name => className;
 
+  @override
   String get descriptor => 'class $name';
 
+  @override
   String toString() => 'class:$name';
 }
 
@@ -190,22 +205,28 @@
 // TODO(johnniwinther): Create an [NodeId]-based equivalence with the kernel IR.
 class NodeId implements Id {
   final int value;
+  @override
   final IdKind kind;
 
   const NodeId(this.value, this.kind);
 
+  @override
   bool get isGlobal => false;
 
+  @override
   int get hashCode => value.hashCode * 13 + kind.hashCode * 17;
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! NodeId) return false;
     return value == other.value && kind == other.kind;
   }
 
+  @override
   String get descriptor => 'offset $value ($kind)';
 
+  @override
   String toString() => '$kind:$value';
 }
 
@@ -230,6 +251,7 @@
     return 'object `${'$object'.replaceAll('\n', '')}` (${object.runtimeType})';
   }
 
+  @override
   String toString() =>
       'ActualData(id=$id,value=$value,sourceSpan=$sourceSpan,object=$objectText)';
 }
@@ -272,7 +294,9 @@
 /// Abstract IR visitor for computing data corresponding to a node or element,
 /// and record it with a generic [Id]
 abstract class IrDataExtractor<T> extends ir.Visitor with DataRegistry<T> {
+  @override
   final DiagnosticReporter reporter;
+  @override
   final Map<Id, ActualData<T>> actualMap;
 
   /// Implement this to compute the data corresponding to [member].
@@ -352,15 +376,18 @@
     root.accept(this);
   }
 
+  @override
   defaultNode(ir.Node node) {
     node.visitChildren(this);
   }
 
+  @override
   defaultMember(ir.Member node) {
     computeForMember(node);
     super.defaultMember(node);
   }
 
+  @override
   visitMethodInvocation(ir.MethodInvocation node) {
     ir.TreeNode receiver = node.receiver;
     if (receiver is ir.VariableGet &&
@@ -384,15 +411,18 @@
     }
   }
 
+  @override
   visitLoadLibrary(ir.LoadLibrary node) {
     computeForNode(node, createInvokeId(node));
   }
 
+  @override
   visitPropertyGet(ir.PropertyGet node) {
     computeForNode(node, computeDefaultNodeId(node));
     super.visitPropertyGet(node);
   }
 
+  @override
   visitVariableDeclaration(ir.VariableDeclaration node) {
     if (node.name != null && node.parent is! ir.FunctionDeclaration) {
       // Skip synthetic variables and function declaration variables.
@@ -401,16 +431,19 @@
     super.visitVariableDeclaration(node);
   }
 
+  @override
   visitFunctionDeclaration(ir.FunctionDeclaration node) {
     computeForNode(node, computeDefaultNodeId(node));
     super.visitFunctionDeclaration(node);
   }
 
+  @override
   visitFunctionExpression(ir.FunctionExpression node) {
     computeForNode(node, computeDefaultNodeId(node));
     super.visitFunctionExpression(node);
   }
 
+  @override
   visitVariableGet(ir.VariableGet node) {
     if (node.variable.name != null && !node.variable.isFieldFormal) {
       // Skip use of synthetic variables.
@@ -419,11 +452,13 @@
     super.visitVariableGet(node);
   }
 
+  @override
   visitPropertySet(ir.PropertySet node) {
     computeForNode(node, createUpdateId(node));
     super.visitPropertySet(node);
   }
 
+  @override
   visitVariableSet(ir.VariableSet node) {
     if (node.variable.name != null) {
       // Skip use of synthetic variables.
@@ -432,16 +467,19 @@
     super.visitVariableSet(node);
   }
 
+  @override
   visitDoStatement(ir.DoStatement node) {
     computeForNode(node, createLoopId(node));
     super.visitDoStatement(node);
   }
 
+  @override
   visitForStatement(ir.ForStatement node) {
     computeForNode(node, createLoopId(node));
     super.visitForStatement(node);
   }
 
+  @override
   visitForInStatement(ir.ForInStatement node) {
     computeForNode(node, createLoopId(node));
     computeForNode(node, createIteratorId(node));
@@ -450,11 +488,13 @@
     super.visitForInStatement(node);
   }
 
+  @override
   visitWhileStatement(ir.WhileStatement node) {
     computeForNode(node, createLoopId(node));
     super.visitWhileStatement(node);
   }
 
+  @override
   visitLabeledStatement(ir.LabeledStatement node) {
     if (!JumpVisitor.canBeBreakTarget(node.body) &&
         !JumpVisitor.canBeContinueTarget(node.parent)) {
@@ -463,16 +503,19 @@
     super.visitLabeledStatement(node);
   }
 
+  @override
   visitBreakStatement(ir.BreakStatement node) {
     computeForNode(node, createGotoId(node));
     super.visitBreakStatement(node);
   }
 
+  @override
   visitSwitchStatement(ir.SwitchStatement node) {
     computeForNode(node, createSwitchId(node));
     super.visitSwitchStatement(node);
   }
 
+  @override
   visitSwitchCase(ir.SwitchCase node) {
     if (node.expressionOffsets.isNotEmpty) {
       computeForNode(node, createSwitchCaseId(node));
@@ -480,6 +523,7 @@
     super.visitSwitchCase(node);
   }
 
+  @override
   visitContinueSwitchStatement(ir.ContinueSwitchStatement node) {
     computeForNode(node, createGotoId(node));
     super.visitContinueSwitchStatement(node);
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
index ba46e61..ba5118a 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
@@ -476,6 +476,7 @@
     return _computedDataForEachFile[file];
   }
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('MemberAnnotations(');
diff --git a/tests/compiler/dart2js/field_analysis/jdata/regress_36222.dart b/tests/compiler/dart2js/field_analysis/jdata/regress_36222.dart
new file mode 100644
index 0000000..d798780
--- /dev/null
+++ b/tests/compiler/dart2js/field_analysis/jdata/regress_36222.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2019, 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.
+
+typedef int BinaryFunc(int x, int y);
+
+class A {
+  const A({this.foo = A.defaultFoo});
+
+  static int defaultFoo(int x, int y) {
+    return x + y;
+  }
+
+  /*element: A.foo:constant=FunctionConstant(A.defaultFoo)*/
+  final BinaryFunc foo;
+}
+
+@pragma('dart2js:assumeDynamic')
+@pragma('dart2js:noInline')
+test(dynamic a) => a.foo(1, 2);
+
+main() {
+  test(new A());
+}
diff --git a/tests/compiler/dart2js/field_analysis/jdata/static_initializers.dart b/tests/compiler/dart2js/field_analysis/jdata/static_initializers.dart
index 967f63c..4e0c97f 100644
--- a/tests/compiler/dart2js/field_analysis/jdata/static_initializers.dart
+++ b/tests/compiler/dart2js/field_analysis/jdata/static_initializers.dart
@@ -17,6 +17,56 @@
   print(field3b);
   field3c = null;
   print(field3c);
+  print(field3d);
+  print(field3e);
+  print(field3f);
+  print(field3g);
+  print(field3h);
+
+  print(field4a);
+  print(field4b);
+  print(field4c);
+
+  print(field5a);
+  print(field5b);
+  print(field5c);
+
+  print(field6a);
+  print(field6b);
+  print(field6c);
+
+  print(field7a);
+  print(field7b);
+  print(field7c);
+  print(field7d);
+  print(field7e);
+
+  print(field8a);
+  print(field8b);
+  print(field8c);
+  print(field8d);
+
+  print(field9a);
+  print(field9b);
+  print(field9c);
+  print(field9d);
+  field9e = null;
+  print(field9e);
+  print(field9f);
+  print(field9g);
+  print(field9h);
+  print(field9i);
+
+  print(field10a);
+  print(field10b);
+}
+
+method() {}
+
+class Class {
+  const Class.generative();
+
+  const factory Class.fact() = Class.generative;
 }
 
 /*element: field1a:constant=IntConstant(0)*/
@@ -37,11 +87,133 @@
 /*element: field2c:initial=ListConstant([])*/
 var field2c = const [];
 
-/*element: field3a:*/
+/*element: field3a:eager,final*/
 final field3a = [];
 
-/*element: field3b:*/
+/*element: field3b:eager,final*/
 var field3b = [];
 
-/*element: field3c:*/
+/*element: field3c:eager*/
 var field3c = [];
+
+/*element: field3d:eager,final*/
+var field3d = [1, 2, 3];
+
+/*element: field3e:eager,final*/
+var field3e = [
+  1,
+  2,
+  [
+    3,
+    4,
+    [5, 6, method]
+  ]
+];
+
+/*element: field3f:final,lazy*/
+var field3f = [
+  1,
+  2,
+  [
+    3,
+    4,
+    [5, 6, method()]
+  ]
+];
+
+/*element: field3g:final,lazy*/
+var field3g = [method()];
+
+// TODO(johnniwinther): Recognize this as of eager complexity.
+/*element: field3h:final,lazy*/
+var field3h = [1 + 3];
+
+/*element: field4a:constant=IntConstant(5)*/
+final field4a = 2 + 3;
+
+/*element: field4b:constant=IntConstant(5)*/
+var field4b = 2 + 3;
+
+/*element: field4c:constant=IntConstant(5)*/
+const field4c = 2 + 3;
+
+/*element: field5a:constant=FunctionConstant(method)*/
+final field5a = method;
+
+/*element: field5b:constant=FunctionConstant(method)*/
+var field5b = method;
+
+/*element: field5c:constant=FunctionConstant(method)*/
+const field5c = method;
+
+/*element: field6a:constant=ConstructedConstant(Class())*/
+var field6a = const Class.generative();
+
+/*element: field6b:constant=ConstructedConstant(Class())*/
+var field6b = const Class.fact();
+
+/*element: field6c:final,lazy*/
+var field6c = method();
+
+/*element: field7a:eager,final*/
+var field7a = {};
+
+/*element: field7b:eager,final*/
+var field7b = {0: 1};
+
+/*element: field7c:eager,final*/
+var field7c = {0: method};
+
+/*element: field7d:final,lazy*/
+var field7d = {0: method()};
+
+/*element: field7e:final,lazy*/
+var field7e = {method(): 0};
+
+/*element: field8a:eager,final*/
+var field8a = {};
+
+/*element: field8b:eager,final*/
+var field8b = {0};
+
+/*element: field8c:eager,final*/
+var field8c = {method};
+
+/*element: field8d:final,lazy*/
+var field8d = {method()};
+
+/*element: field9g:eager=[field9d],final,index=1*/
+var field9g = field9d;
+
+/*element: field9a:eager,final*/
+var field9a = [];
+
+/*element: field9c:eager=[field9b],final,index=3*/
+var field9c = [field9b];
+
+/*element: field9b:eager=[field9a],final,index=2*/
+var field9b = field9a;
+
+// Because [field9g] is declared first and it depends upon [field9d], [field9d]
+// must be created before [field9g] and thus has a lower index than, say,
+// [field9b].
+/*element: field9d:eager=[field9a],final,index=0*/
+var field9d = [field9a];
+
+/*element: field9e:eager*/
+var field9e = [];
+
+/*element: field9f:final,lazy*/
+var field9f = field9e;
+
+/*element: field9h:constant=ListConstant([])*/
+var field9h = const [];
+
+/*element: field9i:eager,final*/
+var field9i = [field9h];
+
+/*element: field10a:final,lazy*/
+int field10a = field10b;
+
+/*element: field10b:final,lazy*/
+int field10b = field10a;
diff --git a/tests/compiler/dart2js/field_analysis/jfield_analysis_test.dart b/tests/compiler/dart2js/field_analysis/jfield_analysis_test.dart
index 1e9dfb7..09870a6 100644
--- a/tests/compiler/dart2js/field_analysis/jfield_analysis_test.dart
+++ b/tests/compiler/dart2js/field_analysis/jfield_analysis_test.dart
@@ -26,6 +26,10 @@
   static const String isInitializedInAllocator = 'allocator';
   static const String initialValue = 'initial';
   static const String constantValue = 'constant';
+  static const String isEager = 'eager';
+  static const String eagerCreationIndex = 'index';
+  static const String isLazy = 'lazy';
+  static const String isEffectivelyFinal = 'final';
 }
 
 class JAllocatorAnalysisDataComputer extends DataComputer<Features> {
@@ -41,14 +45,33 @@
       ir.Member node = closedWorld.elementMap.getMemberDefinition(member).node;
       Features features = new Features();
       FieldAnalysisData fieldData = fieldAnalysis.getFieldData(member);
+      if (fieldData.isInitializedInAllocator) {
+        features.add(Tags.isInitializedInAllocator);
+      }
       if (fieldData.isEffectivelyConstant) {
         features[Tags.constantValue] =
             fieldData.constantValue.toStructuredText();
       } else if (fieldData.initialValue != null) {
         features[Tags.initialValue] = fieldData.initialValue.toStructuredText();
+      } else if (fieldData.isEager) {
+        if (fieldData.eagerCreationIndex != null) {
+          features[Tags.eagerCreationIndex] =
+              fieldData.eagerCreationIndex.toString();
+        }
+        if (fieldData.eagerFieldDependenciesForTesting != null) {
+          for (FieldEntity field
+              in fieldData.eagerFieldDependenciesForTesting) {
+            features.addElement(Tags.isEager, field.name);
+          }
+        } else {
+          features.add(Tags.isEager);
+        }
       }
-      if (fieldData.isInitializedInAllocator) {
-        features.add(Tags.isInitializedInAllocator);
+      if (!member.isInstanceMember && fieldData.isLazy) {
+        features.add(Tags.isLazy);
+      }
+      if (fieldData.isEffectivelyFinal && !fieldData.isEffectivelyConstant) {
+        features.add(Tags.isEffectivelyFinal);
       }
       Id id = computeEntityId(node);
       actualMap[id] = new ActualData<Features>(
diff --git a/tests/compiler/dart2js/field_analysis/kdata/regress_36222.dart b/tests/compiler/dart2js/field_analysis/kdata/regress_36222.dart
new file mode 100644
index 0000000..6794ac8
--- /dev/null
+++ b/tests/compiler/dart2js/field_analysis/kdata/regress_36222.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2019, 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.
+
+typedef int BinaryFunc(int x, int y);
+
+class A {
+  const A({this.foo = A.defaultFoo});
+
+  static int defaultFoo(int x, int y) {
+    return x + y;
+  }
+
+  /*element: A.foo:A.=foo:FunctionConstant(A.defaultFoo),initial=NullConstant*/
+  final BinaryFunc foo;
+}
+
+@pragma('dart2js:assumeDynamic')
+@pragma('dart2js:noInline')
+test(dynamic a) => a.foo(1, 2);
+
+main() {
+  test(new A());
+}
diff --git a/tests/compiler/dart2js/field_analysis/kdata/static_initializers.dart b/tests/compiler/dart2js/field_analysis/kdata/static_initializers.dart
index fc87293..6f393ef 100644
--- a/tests/compiler/dart2js/field_analysis/kdata/static_initializers.dart
+++ b/tests/compiler/dart2js/field_analysis/kdata/static_initializers.dart
@@ -14,10 +14,49 @@
   print(field3a);
   print(field3b);
   print(field3c);
+  print(field3d);
+  print(field3e);
+  print(field3f);
+  print(field3g);
+  print(field3h);
 
   print(field4a);
   print(field4b);
   print(field4c);
+
+  print(field5a);
+  print(field5b);
+  print(field5c);
+
+  print(field6a);
+  print(field6b);
+  print(field6c);
+
+  print(field7a);
+  print(field7b);
+  print(field7c);
+  print(field7d);
+  print(field7e);
+
+  print(field8a);
+  print(field8b);
+  print(field8c);
+  print(field8d);
+
+  print(field9a);
+  print(field9b);
+  print(field9c);
+
+  print(field10a);
+  print(field10b);
+}
+
+method() {}
+
+class Class {
+  const Class.generative();
+
+  const factory Class.fact() = Class.generative;
 }
 
 /*element: field1a:complexity=constant,initial=IntConstant(0)*/
@@ -38,16 +77,48 @@
 /*element: field2c:complexity=constant,initial=ListConstant([])*/
 const field2c = const [];
 
-/*element: field3a:complexity=lazy*/
+/*element: field3a:complexity=eager*/
 final field3a = [];
 
-/*element: field3b:complexity=lazy*/
+/*element: field3b:complexity=eager*/
 var field3b = [];
 
-/*element: field3c:complexity=lazy*/
+/*element: field3c:complexity=eager*/
 var field3c = [];
 
-// TODO(johnniwinther): Recognize these as of constant complexity.
+/*element: field3d:complexity=eager*/
+var field3d = [1, 2, 3];
+
+/*element: field3e:complexity=eager*/
+var field3e = [
+  1,
+  2,
+  [
+    3,
+    4,
+    [5, 6, method]
+  ]
+];
+
+/*element: field3f:complexity=lazy*/
+var field3f = [
+  1,
+  2,
+  [
+    3,
+    4,
+    [5, 6, method()]
+  ]
+];
+
+/*element: field3g:complexity=lazy*/
+var field3g = [method()];
+
+// TODO(johnniwinther): Recognize this as of eager complexity.
+/*element: field3h:complexity=lazy*/
+var field3h = [1 + 3];
+
+// TODO(johnniwinther): Recognize `field4*` as of constant complexity.
 /*element: field4a:complexity=lazy,initial=IntConstant(5)*/
 final field4a = 2 + 3;
 
@@ -56,3 +127,63 @@
 
 /*element: field4c:complexity=lazy,initial=IntConstant(5)*/
 const field4c = 2 + 3;
+
+/*element: field5a:complexity=constant,initial=FunctionConstant(method)*/
+final field5a = method;
+
+/*element: field5b:complexity=constant,initial=FunctionConstant(method)*/
+var field5b = method;
+
+/*element: field5c:complexity=constant,initial=FunctionConstant(method)*/
+const field5c = method;
+
+/*element: field6a:complexity=constant,initial=ConstructedConstant(Class())*/
+var field6a = const Class.generative();
+
+/*element: field6b:complexity=constant,initial=ConstructedConstant(Class())*/
+var field6b = const Class.fact();
+
+/*element: field6c:complexity=lazy*/
+var field6c = method();
+
+/*element: field7a:complexity=eager*/
+var field7a = {};
+
+/*element: field7b:complexity=eager*/
+var field7b = {0: 1};
+
+/*element: field7c:complexity=eager*/
+var field7c = {0: method};
+
+/*element: field7d:complexity=lazy*/
+var field7d = {0: method()};
+
+/*element: field7e:complexity=lazy*/
+var field7e = {method(): 0};
+
+/*element: field8a:complexity=eager*/
+var field8a = {};
+
+/*element: field8b:complexity=eager*/
+var field8b = {0};
+
+/*element: field8c:complexity=eager*/
+var field8c = {method};
+
+/*element: field8d:complexity=lazy*/
+var field8d = {method()};
+
+/*element: field9a:complexity=eager*/
+var field9a = [];
+
+/*element: field9b:complexity=eager&fields=[field9a]*/
+var field9b = field9a;
+
+/*element: field9c:complexity=eager&fields=[field9b]*/
+var field9c = [field9b];
+
+/*element: field10a:complexity=eager&fields=[field10b]*/
+int field10a = field10b;
+
+/*element: field10b:complexity=eager&fields=[field10a]*/
+int field10b = field10a;
diff --git a/tests/compiler/dart2js/helpers/diagnostic_helper.dart b/tests/compiler/dart2js/helpers/diagnostic_helper.dart
index e5d433d..d45306a 100644
--- a/tests/compiler/dart2js/helpers/diagnostic_helper.dart
+++ b/tests/compiler/dart2js/helpers/diagnostic_helper.dart
@@ -25,6 +25,7 @@
 
   MessageKind get messageKind => message?.kind;
 
+  @override
   String toString() {
     return '${message != null ? message.kind : ''}'
         ':$uri:$begin:$end:$text:$kind';
diff --git a/tests/compiler/dart2js/helpers/output_collector.dart b/tests/compiler/dart2js/helpers/output_collector.dart
index e9ff37b..30b62be 100644
--- a/tests/compiler/dart2js/helpers/output_collector.dart
+++ b/tests/compiler/dart2js/helpers/output_collector.dart
@@ -12,15 +12,18 @@
   StringBuffer sb = new StringBuffer();
   String text;
 
+  @override
   void add(String event) {
     sb.write(event);
   }
 
+  @override
   void close() {
     text = sb.toString();
     sb = null;
   }
 
+  @override
   String toString() {
     return text ?? sb.toString();
   }
@@ -33,12 +36,15 @@
 
   BufferedBinaryOutputSink(this.uri);
 
+  @override
   void write(List<int> buffer, [int start = 0, int end]) {
     list.addAll(buffer.sublist(start, end));
   }
 
+  @override
   void close() {}
 
+  @override
   String toString() {
     return 'BufferedBinaryOutputSink($uri)';
   }
@@ -79,6 +85,7 @@
     }
   }
 
+  @override
   BinaryOutputSink createBinarySink(Uri uri) {
     return binaryOutputMap.putIfAbsent(
         uri, () => new BufferedBinaryOutputSink(uri));
diff --git a/tests/compiler/dart2js/helpers/program_lookup.dart b/tests/compiler/dart2js/helpers/program_lookup.dart
index ccbf049..18d8e84 100644
--- a/tests/compiler/dart2js/helpers/program_lookup.dart
+++ b/tests/compiler/dart2js/helpers/program_lookup.dart
@@ -176,6 +176,7 @@
     return _staticFieldMap[field];
   }
 
+  @override
   String toString() => 'LibraryData(library=$library,_classMap=$_classMap,'
       '_methodMap=$_methodMap,_fieldMap=$_fieldMap)';
 }
@@ -220,6 +221,7 @@
     return _checkedSetterMap[field];
   }
 
+  @override
   String toString() => 'ClassData(cls=$cls,'
       '_methodMap=$_methodMap,_fieldMap=$_fieldMap)';
 }
diff --git a/tests/compiler/dart2js/helpers/stats_test.dart b/tests/compiler/dart2js/helpers/stats_test.dart
index 5271e12..9254ee9 100644
--- a/tests/compiler/dart2js/helpers/stats_test.dart
+++ b/tests/compiler/dart2js/helpers/stats_test.dart
@@ -8,10 +8,12 @@
 class CollectingOutput implements StatsOutput {
   final StringBuffer sb = new StringBuffer();
 
+  @override
   void println(String text) {
     sb.write('$text\n');
   }
 
+  @override
   String toString() => sb.toString();
 }
 
diff --git a/tests/compiler/dart2js/helpers/type_test_helper.dart b/tests/compiler/dart2js/helpers/type_test_helper.dart
index c4304da..cda6070 100644
--- a/tests/compiler/dart2js/helpers/type_test_helper.dart
+++ b/tests/compiler/dart2js/helpers/type_test_helper.dart
@@ -190,6 +190,7 @@
 
   const FunctionTypeData(this.returnType, this.name, this.parameters);
 
+  @override
   String toString() => '$returnType $name$parameters';
 }
 
diff --git a/tests/compiler/dart2js/impact/data/injected_cast.dart b/tests/compiler/dart2js/impact/data/injected_cast.dart
new file mode 100644
index 0000000..526414c
--- /dev/null
+++ b/tests/compiler/dart2js/impact/data/injected_cast.dart
@@ -0,0 +1,220 @@
+// Copyright (c) 2019, 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.
+
+class A {}
+
+class B {}
+
+class C {}
+
+class D {}
+
+class E {}
+
+/*element: Class1.:static=[Object.(0)]*/
+class Class1 {
+  /*element: Class1.field1:type=[inst:JSBool,inst:JSNull,param:A]*/
+  A field1;
+}
+
+/*element: method1:
+ dynamic=[Class1.field1=],
+ type=[
+  impl:A,
+  inst:JSBool,
+  is:Class1]
+*/
+method1(dynamic o, dynamic value) {
+  if (o is! Class1) return;
+  o.field1 = value;
+}
+
+/*element: Class2.:static=[Object.(0)]*/
+class Class2<T> {
+  /*element: Class2.field2:
+   static=*,
+   type=[inst:*,param:Class2.T]
+   */
+  T field2;
+}
+
+/*element: method2:
+ dynamic=[Class2.field2=],
+ static=*,
+ type=[
+  impl:A,
+  inst:*,
+  is:Class2<A>]
+*/
+method2(dynamic o, dynamic value) {
+  if (o is! Class2<A>) return;
+  o.field2 = value;
+}
+
+/*element: Class3.:static=[Object.(0)]*/
+class Class3 {
+  /*element: Class3.method3:type=[inst:JSBool,inst:JSNull,param:A,param:B,param:C]*/
+  method3(A a, [B b, C c]) {}
+}
+
+/*element: method3:
+ dynamic=[Class3.method3(3)],
+ type=[
+  impl:A,
+  impl:C,
+  inst:JSBool,
+  is:Class3,
+  param:B]
+*/
+method3(dynamic o, dynamic a, B b, dynamic c) {
+  if (o is! Class3) return;
+  o.method3(a, b, c);
+}
+
+/*element: Class4.:static=[Object.(0)]*/
+class Class4 {
+  /*element: Class4.method4:
+   type=[inst:JSBool,inst:JSNull,param:A,param:B,param:C]
+  */
+  method4(A a, {B b, C c}) {}
+}
+
+/*element: method4:
+ dynamic=[Class4.method4(1,b,c)],
+ type=[
+  impl:A,
+  impl:C,
+  inst:JSBool,
+  is:Class4,
+  param:B]
+*/
+method4(dynamic o, dynamic a, B b, dynamic c) {
+  if (o is! Class4) return;
+  o.method4(a, c: c, b: b);
+}
+
+/*element: Class5.:static=[Object.(0)]*/
+class Class5<T1, T2> {
+  /*element: Class5.method5:
+   static=*,
+   type=[
+    inst:*,
+    param:C,
+    param:Class5.T1,
+    param:Class5.T2,
+    param:Object,
+    param:method5.S1,
+    param:method5.S2]
+  */
+  method5<S1, S2>(T1 a, [T2 b, C c, S1 d, S2 e]) {}
+}
+
+/*element: method5:
+ dynamic=[Class5.method5<D,E>(5)],
+ static=*,
+ type=[
+  impl:A,
+  impl:D,
+  inst:*,
+  is:Class5<A,B>,
+  param:B,
+  param:C,
+  param:E]
+*/
+method5(dynamic o, dynamic a, B b, C c, dynamic d, E e) {
+  if (o is! Class5<A, B>) return;
+  o.method5<D, E>(a, b, c, d, e);
+}
+
+/*element: Class6.:static=[Object.(0)]*/
+class Class6<T1, T2> {
+  /*element: Class6.method6:
+   static=*,
+   type=[
+    inst:*,
+    param:C,
+    param:Class6.T1,
+    param:Class6.T2,
+    param:Object,
+    param:method6.S1,
+    param:method6.S2]
+  */
+  method6<S1, S2>(T1 a, {T2 b, C c, S1 d, S2 e}) {}
+}
+
+/*element: method6:
+ dynamic=[Class6.method6<D,E>(1,b,c,d,e)],
+ static=*,
+ type=[
+  impl:A,
+  impl:D,
+  inst:*,
+  is:Class6<A,B>,
+  param:B,
+  param:C,
+  param:E]
+*/
+method6(dynamic o, dynamic a, B b, C c, dynamic d, E e) {
+  if (o is! Class6<A, B>) return;
+  o.method6<D, E>(a, d: d, b: b, e: e, c: c);
+}
+
+/*element: Class7.:static=[Object.(0)]*/
+class Class7 {
+  /*element: Class7.f:type=[inst:JSNull]*/
+  A Function(A) get f => null;
+}
+
+/*element: method7:
+ dynamic=[Class7.f(1),call(1)],
+ type=[impl:A,inst:JSBool,is:Class7]
+*/
+method7(dynamic o, dynamic a) {
+  if (o is! Class7) return;
+  o.f(a);
+}
+
+/*element: F.:static=[Object.(0)]*/
+class F<T> {
+  /*element: F.method:static=*,type=[inst:*,param:List<F.T>]*/
+  T method(List<T> list) => null;
+
+  /*element: F.field:static=*,type=[inst:*,param:F.T]*/
+  T field;
+}
+
+/*element: G.:static=[F.(0)]*/
+class G extends F<int> {}
+
+/*element: method8:
+ dynamic=[G.method(1)],
+ static=*,
+ type=[impl:List<int>,inst:*,is:G,param:Iterable<int>]
+*/
+method8(dynamic g, Iterable<int> iterable) {
+  if (g is! G) return null;
+  return g.method(iterable);
+}
+
+/*element: method9:
+ dynamic=[G.field=],
+ type=[impl:int,inst:JSBool,inst:JSNull,is:G,param:num]
+*/
+method9(dynamic g, num value) {
+  if (g is! G) return null;
+  return g.field = value;
+}
+
+/*element: main:**/
+main() {
+  method1(new Class1(), null);
+  method2(new Class2<A>(), null);
+  method3(new Class3(), null, null, null);
+  method4(new Class4(), null, null, null);
+  method5(new Class5<A, B>(), null, null, null, null, null);
+  method6(new Class6<A, B>(), null, null, null, null, null);
+  method7(new Class7(), null);
+  method8(new G(), null);
+  method9(new G(), null);
+}
diff --git a/tests/compiler/dart2js/impact/impact_test.dart b/tests/compiler/dart2js/impact/impact_test.dart
index 2dc7d40..1237e4c 100644
--- a/tests/compiler/dart2js/impact/impact_test.dart
+++ b/tests/compiler/dart2js/impact/impact_test.dart
@@ -9,7 +9,6 @@
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/ir/util.dart';
 import 'package:compiler/src/kernel/kernel_strategy.dart';
-import 'package:compiler/src/kernel/element_map_impl.dart';
 import 'package:compiler/src/universe/feature.dart';
 import 'package:compiler/src/universe/use.dart';
 import 'package:compiler/src/universe/world_impact.dart';
diff --git a/tests/compiler/dart2js/inference/data/map_tracer_keys.dart b/tests/compiler/dart2js/inference/data/map_tracer_keys.dart
index af96537..576a02a 100644
--- a/tests/compiler/dart2js/inference/data/map_tracer_keys.dart
+++ b/tests/compiler/dart2js/inference/data/map_tracer_keys.dart
@@ -58,16 +58,16 @@
 test2() {
   dynamic theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
   theMap
-      /*update: Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
+      /*update: Map([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble])*/
       [aList2] = 5.5;
   /*iterator: [exact=LinkedHashMapKeyIterable]*/
   /*current: [exact=LinkedHashMapKeyIterator]*/
   /*moveNext: [exact=LinkedHashMapKeyIterator]*/
   for (var key in theMap.
-      /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
+      /*Map([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble])*/
       keys) {
     aDouble2 = theMap
-        /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
+        /*Map([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble])*/
         [key];
   }
   // We have to reference it somewhere, so that it always gets resolved.
diff --git a/tests/compiler/dart2js/inference/libs/mixin_constructor_default_parameter_values_lib.dart b/tests/compiler/dart2js/inference/libs/mixin_constructor_default_parameter_values_lib.dart
index a105fa0..8ae50e9 100644
--- a/tests/compiler/dart2js/inference/libs/mixin_constructor_default_parameter_values_lib.dart
+++ b/tests/compiler/dart2js/inference/libs/mixin_constructor_default_parameter_values_lib.dart
@@ -6,6 +6,7 @@
   /*element: _SECRET.:[exact=_SECRET]*/
   const _SECRET();
   /*element: _SECRET.toString:Value([exact=JSString], value: "SECRET!")*/
+  @override
   String toString() => "SECRET!";
 }
 
@@ -29,5 +30,6 @@
         this.y = b;
 
   /*element: C.toString:[exact=JSString]*/
+  @override
   String toString() => "C(${/*[exact=D]*/ x},${/*[exact=D]*/ y})";
 }
diff --git a/tests/compiler/dart2js/inference/type_combination_test.dart b/tests/compiler/dart2js/inference/type_combination_test.dart
index cddae20..cc65647 100644
--- a/tests/compiler/dart2js/inference/type_combination_test.dart
+++ b/tests/compiler/dart2js/inference/type_combination_test.dart
@@ -54,7 +54,9 @@
   final first;
   final second;
   Pair(this.first, this.second);
+  @override
   int get hashCode => first.hashCode * 47 + second.hashCode;
+  @override
   bool operator ==(other) =>
       other is Pair &&
       identical(first, other.first) &&
diff --git a/tests/compiler/dart2js/js/js_spec_string_test.dart b/tests/compiler/dart2js/js/js_spec_string_test.dart
index 0dc8344..193a39f 100644
--- a/tests/compiler/dart2js/js/js_spec_string_test.dart
+++ b/tests/compiler/dart2js/js/js_spec_string_test.dart
@@ -15,11 +15,13 @@
 
 class Listener extends DiagnosticReporter {
   String errorMessage;
+  @override
   internalError(spannable, message) {
     errorMessage = message;
     throw "error";
   }
 
+  @override
   reportError(message, [infos = const <DiagnosticMessage>[]]) {
     errorMessage =
         '${message.message.arguments}'; // E.g.  "{text: Duplicate tag 'new'.}"
@@ -33,6 +35,7 @@
         MessageTemplate.TEMPLATES[messageKind].message(arguments));
   }
 
+  @override
   noSuchMethod(_) => null;
 }
 
diff --git a/tests/compiler/dart2js/jumps/jump_test.dart b/tests/compiler/dart2js/jumps/jump_test.dart
index 4d954d7..5ea39a1 100644
--- a/tests/compiler/dart2js/jumps/jump_test.dart
+++ b/tests/compiler/dart2js/jumps/jump_test.dart
@@ -56,6 +56,7 @@
 
   TargetData(this.index, this.id, this.sourceSpan, this.target);
 
+  @override
   String toString() => 'TargetData(index=$index,id=$id,'
       'sourceSpan=$sourceSpan,target=$target)';
 }
@@ -67,6 +68,7 @@
 
   GotoData(this.id, this.sourceSpan, this.target);
 
+  @override
   String toString() => 'GotoData(id=$id,sourceSpan=$sourceSpan,target=$target)';
 }
 
@@ -113,6 +115,7 @@
     });
   }
 
+  @override
   void run(ir.Node root) {
     super.run(root);
     processData();
@@ -136,30 +139,35 @@
     }
   }
 
+  @override
   visitForStatement(ir.ForStatement node) {
     addTargetData(
         node, createLoopId(node), _localsMap.getJumpTargetForFor(node));
     super.visitForStatement(node);
   }
 
+  @override
   visitForInStatement(ir.ForInStatement node) {
     addTargetData(
         node, createLoopId(node), _localsMap.getJumpTargetForForIn(node));
     super.visitForInStatement(node);
   }
 
+  @override
   visitWhileStatement(ir.WhileStatement node) {
     addTargetData(
         node, createLoopId(node), _localsMap.getJumpTargetForWhile(node));
     super.visitWhileStatement(node);
   }
 
+  @override
   visitDoStatement(ir.DoStatement node) {
     addTargetData(
         node, createLoopId(node), _localsMap.getJumpTargetForDo(node));
     super.visitDoStatement(node);
   }
 
+  @override
   visitBreakStatement(ir.BreakStatement node) {
     JumpTarget target = _localsMap.getJumpTargetForBreak(node);
     assert(target != null, 'No target for $node.');
@@ -180,18 +188,21 @@
     super.visitLabeledStatement(node);
   }
 
+  @override
   visitSwitchStatement(ir.SwitchStatement node) {
     addTargetData(
         node, createSwitchId(node), _localsMap.getJumpTargetForSwitch(node));
     super.visitSwitchStatement(node);
   }
 
+  @override
   visitSwitchCase(ir.SwitchCase node) {
     addTargetData(node, createSwitchCaseId(node),
         _localsMap.getJumpTargetForSwitchCase(node));
     super.visitSwitchCase(node);
   }
 
+  @override
   visitContinueSwitchStatement(ir.ContinueSwitchStatement node) {
     JumpTarget target = _localsMap.getJumpTargetForContinueSwitch(node);
     assert(target != null, 'No target for $node.');
diff --git a/tests/compiler/dart2js/model/cfe_annotations_test.dart b/tests/compiler/dart2js/model/cfe_annotations_test.dart
index b6eed0b..4f8c619 100644
--- a/tests/compiler/dart2js/model/cfe_annotations_test.dart
+++ b/tests/compiler/dart2js/model/cfe_annotations_test.dart
@@ -24,11 +24,36 @@
 
 library lib;
 
+import 'package:meta/dart2js.dart';
+
 import 'jslib1.dart';
 import 'jslib2.dart';
 import 'nativelib.dart';
 
+@pragma('dart2js:noInline')
+method1() {}
+
+@noInline
+method2() {}
+
+@pragma('dart2js:tryInline')
+method3() {}
+
+@tryInline
+method4() {}
+
 main() {
+  method1();
+  method2();
+  method3();
+  method4();
+  new JsClass1()..jsMethod1()..jsMethod2();
+  new JsClass2();
+  jsMethod3();
+  new NativeClass1()..nativeMethod()..nativeField;
+  new NativeClass2()..nativeField;
+  new NativeClass3()..nativeMethod()..nativeGetter;
+  nativeMethod();
 }
 ''',
   '$pathPrefix/jslib1.dart': '''
@@ -39,11 +64,11 @@
 import 'package:js/js.dart';
 
 @JS('JsInteropClass1')
-class Class1 {
+class JsClass1 {
   @JS('jsInteropMethod1')
-  external method1();
+  external jsMethod1();
   
-  external method2();
+  external jsMethod2();
 }
 
 ''',
@@ -56,35 +81,68 @@
 
 @JS()
 @anonymous
-class Class2 {
+class JsClass2 {
 }
 
 @JS('jsInteropMethod3')
-external method3();
+external jsMethod3();
 ''',
   '$pathPrefix/nativelib.dart': '''
+library lib3; 
+ 
 import 'dart:_js_helper';
 
-@Native('NativeClass1')
-class Class1 {
+@Native('Class1')
+class NativeClass1 {
+  @JSName('field1')
+  var nativeField;
+  
+  @JSName('method1')
+  nativeMethod() native;
 }
 
-@Native('NativeClass2,!nonleaf')
-class Class2 {
+@Native('Class2,!nonleaf')
+class NativeClass2 {
+  @JSName('field2')
+  var nativeField;
 }
 
-@Native('NativeClass3a,NativeClass3b')
-class Class3 {
+@Native('Class3a,Class3b')
+class NativeClass3 {
+  
+  @JSName('method2')
+  get nativeGetter native;
+
+  @Creates('String')
+  @Returns('int')
+  nativeMethod() native;
 }
 
-
+@JSName('method3')
+nativeMethod() native;
 ''',
 };
 
 const Map<String, String> expectedNativeClassNames = {
-  '$pathPrefix/nativelib.dart::Class1': 'NativeClass1',
-  '$pathPrefix/nativelib.dart::Class2': 'NativeClass2,!nonleaf',
-  '$pathPrefix/nativelib.dart::Class3': 'NativeClass3a,NativeClass3b',
+  '$pathPrefix/nativelib.dart::NativeClass1': 'Class1',
+  '$pathPrefix/nativelib.dart::NativeClass2': 'Class2,!nonleaf',
+  '$pathPrefix/nativelib.dart::NativeClass3': 'Class3a,Class3b',
+};
+
+const Map<String, String> expectedNativeMemberNames = {
+  '$pathPrefix/nativelib.dart::NativeClass1::nativeField': 'field1',
+  '$pathPrefix/nativelib.dart::NativeClass1::nativeMethod': 'method1',
+  '$pathPrefix/nativelib.dart::NativeClass2::nativeField': 'field2',
+  '$pathPrefix/nativelib.dart::NativeClass3::nativeGetter': 'method2',
+  '$pathPrefix/nativelib.dart::nativeMethod': 'method3',
+};
+
+const Map<String, String> expectedCreates = {
+  '$pathPrefix/nativelib.dart::NativeClass3::nativeMethod': 'String',
+};
+
+const Map<String, String> expectedReturns = {
+  '$pathPrefix/nativelib.dart::NativeClass3::nativeMethod': 'int',
 };
 
 const Map<String, String> expectedJsInteropLibraryNames = {
@@ -93,17 +151,27 @@
 };
 
 const Map<String, String> expectedJsInteropClassNames = {
-  '$pathPrefix/jslib1.dart::Class1': 'JsInteropClass1',
-  '$pathPrefix/jslib2.dart::Class2': '',
+  '$pathPrefix/jslib1.dart::JsClass1': 'JsInteropClass1',
+  '$pathPrefix/jslib2.dart::JsClass2': '',
 };
 
 const Map<String, String> expectedJsInteropMemberNames = {
-  '$pathPrefix/jslib1.dart::Class1::method1': 'jsInteropMethod1',
-  '$pathPrefix/jslib2.dart::method3': 'jsInteropMethod3',
+  '$pathPrefix/jslib1.dart::JsClass1::jsMethod1': 'jsInteropMethod1',
+  '$pathPrefix/jslib2.dart::jsMethod3': 'jsInteropMethod3',
 };
 
 const Set<String> expectedAnonymousJsInteropClasses = {
-  '$pathPrefix/jslib2.dart::Class2',
+  '$pathPrefix/jslib2.dart::JsClass2',
+};
+
+const Set<String> expectedNoInlineMethods = {
+  '$pathPrefix/main.dart::method1',
+  '$pathPrefix/main.dart::method2',
+};
+
+const Set<String> expectedTryInlineMethods = {
+  '$pathPrefix/main.dart::method3',
+  '$pathPrefix/main.dart::method4',
 };
 
 main(List<String> args) {
@@ -116,6 +184,7 @@
     List<String> options = getOptions(argResults);
 
     runTest({bool useIr}) async {
+      useIrAnnotationsDataForTesting = useIr;
       CompilationResult result = await runCompiler(
           entryPoint: Uri.parse('memory:$pathPrefix/main.dart'),
           memorySourceFiles: source,
@@ -132,23 +201,63 @@
       NativeData nativeData =
           compiler.resolutionWorldBuilder.closedWorldForTesting.nativeData;
       ir.Component component = elementMap.env.mainComponent;
-      IrAnnotationData annotationData;
-      if (useIr) {
-        annotationData = processAnnotations(component);
-      }
+      IrAnnotationData annotationData =
+          frontendStrategy.irAnnotationDataForTesting;
 
       void testMember(String idPrefix, ir.Member member,
-          {bool implicitJsInteropMember}) {
+          {bool implicitJsInteropMember, bool implicitNativeMember}) {
         String memberId = '$idPrefix::${member.name.name}';
         MemberEntity memberEntity = elementMap.getMember(member);
 
         String expectedJsInteropMemberName =
             expectedJsInteropMemberNames[memberId];
+        String expectedNativeMemberName = expectedNativeMemberNames[memberId];
+        Set<String> expectedPragmaNames = {};
+        if (expectedNoInlineMethods.contains(memberId)) {
+          expectedPragmaNames.add('dart2js:noInline');
+        }
+        if (expectedTryInlineMethods.contains(memberId)) {
+          expectedPragmaNames.add('dart2js:tryInline');
+        }
+
+        String expectedCreatesText = expectedCreates[memberId];
+        String expectedReturnsText = expectedReturns[memberId];
+
         if (useIr) {
           Expect.equals(
               expectedJsInteropMemberName,
               annotationData.getJsInteropMemberName(member),
-              "Unexpected js interop member name from IR for $member");
+              "Unexpected js interop member name from IR for $member, "
+              "id: $memberId");
+
+          Expect.equals(
+              expectedNativeMemberName,
+              annotationData.getNativeMemberName(member),
+              "Unexpected js interop member name from IR for $member, "
+              "id: $memberId");
+
+          List<PragmaAnnotationData> pragmaAnnotations =
+              annotationData.getMemberPragmaAnnotationData(member);
+          Set<String> pragmaNames =
+              pragmaAnnotations.map((d) => d.name).toSet();
+          Expect.setEquals(expectedPragmaNames, pragmaNames,
+              "Unexpected pragmas from IR for $member, " "id: $memberId");
+
+          List<String> createsAnnotations =
+              annotationData.getCreatesAnnotations(member);
+          Expect.equals(
+              expectedCreatesText,
+              createsAnnotations.isEmpty ? null : createsAnnotations.join(','),
+              "Unexpected create annotations from IR for $member, "
+              "id: $memberId");
+
+          List<String> returnsAnnotations =
+              annotationData.getReturnsAnnotations(member);
+          Expect.equals(
+              expectedReturnsText,
+              returnsAnnotations.isEmpty ? null : returnsAnnotations.join(','),
+              "Unexpected returns annotations from IR for $member, "
+              "id: $memberId");
         }
         bool isJsInteropMember =
             (implicitJsInteropMember && member.isExternal) ||
@@ -156,13 +265,82 @@
         Expect.equals(
             isJsInteropMember,
             nativeData.isJsInteropMember(memberEntity),
-            "Unexpected js interop member result from native data for $member");
+            "Unexpected js interop member result from native data for $member, "
+            "id: $memberId");
         Expect.equals(
             isJsInteropMember
                 ? expectedJsInteropMemberName ?? memberEntity.name
                 : null,
             nativeData.getJsInteropMemberName(memberEntity),
-            "Unexpected js interop member name from native data for $member");
+            "Unexpected js interop member name from native data for $member, "
+            "id: $memberId");
+
+        bool isNativeMember =
+            implicitNativeMember || expectedNativeMemberName != null;
+        Expect.equals(
+            isNativeMember || isJsInteropMember,
+            nativeData.isNativeMember(memberEntity),
+            "Unexpected native member result from native data for $member, "
+            "id: $memberId");
+        Expect.equals(
+            isNativeMember
+                ? expectedNativeMemberName ?? memberEntity.name
+                : (isJsInteropMember
+                    ? expectedJsInteropMemberName ?? memberEntity.name
+                    : null),
+            nativeData.getFixedBackendName(memberEntity),
+            "Unexpected fixed backend name from native data for $member, "
+            "id: $memberId");
+
+        if (expectedCreatesText != null) {
+          String createsText;
+          if (memberEntity.isField) {
+            createsText = nativeData
+                .getNativeFieldLoadBehavior(memberEntity)
+                .typesInstantiated
+                .join(',');
+          } else {
+            createsText = nativeData
+                .getNativeMethodBehavior(memberEntity)
+                .typesInstantiated
+                .join(',');
+          }
+          Expect.equals(
+              expectedCreatesText,
+              createsText,
+              "Unexpected create annotations from native data for $member, "
+              "id: $memberId");
+        }
+
+        if (expectedReturnsText != null) {
+          String returnsText;
+          if (memberEntity.isField) {
+            returnsText = nativeData
+                .getNativeFieldLoadBehavior(memberEntity)
+                .typesReturned
+                .join(',');
+          } else {
+            returnsText = nativeData
+                .getNativeMethodBehavior(memberEntity)
+                .typesReturned
+                .join(',');
+          }
+          Expect.equals(
+              expectedReturnsText,
+              returnsText,
+              "Unexpected returns annotations from native data for $member, "
+              "id: $memberId");
+        }
+
+        List<PragmaAnnotationData> pragmaAnnotations = frontendStrategy
+            .modularStrategyForTesting
+            .getPragmaAnnotationData(member);
+        Set<String> pragmaNames = pragmaAnnotations.map((d) => d.name).toSet();
+        Expect.setEquals(
+            expectedPragmaNames,
+            pragmaNames,
+            "Unexpected pragmas from modular strategy for $member, "
+            "id: $memberId");
       }
 
       for (ir.Library library in component.libraries) {
@@ -248,20 +426,24 @@
             for (ir.Member member in cls.members) {
               testMember(clsId, member,
                   implicitJsInteropMember:
-                      nativeData.isJsInteropClass(classEntity));
+                      nativeData.isJsInteropClass(classEntity),
+                  implicitNativeMember: member is! ir.Constructor &&
+                      nativeData.isNativeClass(classEntity) &&
+                      !nativeData.isJsInteropClass(classEntity));
             }
           }
           for (ir.Member member in library.members) {
-            testMember(libraryId, member, implicitJsInteropMember: false);
+            testMember(libraryId, member,
+                implicitJsInteropMember: false, implicitNativeMember: false);
           }
         }
       }
     }
 
-    print('test annotations from IR');
-    await runTest(useIr: true);
-
     print('test annotations from K-model');
     await runTest(useIr: false);
+
+    print('test annotations from IR');
+    await runTest(useIr: true);
   });
 }
diff --git a/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart b/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart
index c5c9d5b..fafdcbb 100644
--- a/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart
+++ b/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart
@@ -64,6 +64,7 @@
 
   MemoryEnvironment(this._environment, [this.env = const <String, String>{}]);
 
+  @override
   bool get checkCasts => true;
 
   @override
diff --git a/tests/compiler/dart2js/model/enqueuer_test.dart b/tests/compiler/dart2js/model/enqueuer_test.dart
index 8a8a6a6..3417206 100644
--- a/tests/compiler/dart2js/model/enqueuer_test.dart
+++ b/tests/compiler/dart2js/model/enqueuer_test.dart
@@ -71,6 +71,7 @@
   const Impact.invoke(this.clsName, this.memberName)
       : this.kind = ImpactKind.invoke;
 
+  @override
   String toString() =>
       'Impact(kind=$kind,clsName=$clsName,memberName=$memberName)';
 }
diff --git a/tests/compiler/dart2js/model/native_test.dart b/tests/compiler/dart2js/model/native_test.dart
index 3e7284b..c281c63f 100644
--- a/tests/compiler/dart2js/model/native_test.dart
+++ b/tests/compiler/dart2js/model/native_test.dart
@@ -290,6 +290,7 @@
     return sb.toString();
   }
 
+  @override
   String toString() {
     return lines.values.join('\n');
   }
diff --git a/tests/compiler/dart2js/model/strong_mode_impact_test.dart b/tests/compiler/dart2js/model/strong_mode_impact_test.dart
index 1b2f5ad..eec9e9d 100644
--- a/tests/compiler/dart2js/model/strong_mode_impact_test.dart
+++ b/tests/compiler/dart2js/model/strong_mode_impact_test.dart
@@ -136,6 +136,7 @@
       this.implicitCasts: const <String>[],
       this.parameterChecks: const <String>[]});
 
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('Impact(');
diff --git a/tests/compiler/dart2js/optimization/data/index.dart b/tests/compiler/dart2js/optimization/data/index.dart
index 12586ad..b6dd480 100644
--- a/tests/compiler/dart2js/optimization/data/index.dart
+++ b/tests/compiler/dart2js/optimization/data/index.dart
@@ -40,6 +40,7 @@
 /*strong.element: mutableDynamicListDynamicIndex:Specializer=[!Index]*/
 /*omit.element: mutableDynamicListDynamicIndex:Specializer=[Index]*/
 @pragma('dart2js:noInline')
+@pragma('dart2js:disableFinal')
 mutableDynamicListDynamicIndex(dynamic index) {
   dynamic list = [0];
   return list[index];
diff --git a/tests/compiler/dart2js/rti/emission/function_typed_arguments.dart b/tests/compiler/dart2js/rti/emission/function_typed_arguments.dart
new file mode 100644
index 0000000..a434694
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/function_typed_arguments.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2019, 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 'package:expect/expect.dart';
+
+/*class: A:checkedInstance,checks=[],instance*/
+class A<T> {}
+
+main() {
+  test1();
+  test2();
+  test3();
+  test4();
+  test5();
+  test6();
+}
+
+/*class: B1:checkedTypeArgument,checks=[],typeArgument*/
+class B1<T> {}
+
+/*class: C1:checkedTypeArgument,checks=[$asB1],typeArgument*/
+class C1 extends B1<int> {}
+
+@pragma('dart2js:noInline')
+test1() {
+  Expect.isTrue(_test1(new A<void Function(C1)>()));
+  Expect.isTrue(_test1(new A<void Function(B1<int>)>()));
+  Expect.isFalse(_test1(new A<void Function(B1<String>)>()));
+}
+
+@pragma('dart2js:noInline')
+_test1(f) => f is A<void Function(C1)>;
+
+/*class: B2:checks=[],typeArgument*/
+class B2<T> {}
+
+/*class: C2:checkedTypeArgument,checks=[],typeArgument*/
+class C2 extends B2<int> {}
+
+@pragma('dart2js:noInline')
+test2() {
+  Expect.isTrue(_test2(new A<C2 Function()>()));
+  Expect.isFalse(_test2(new A<B2<int> Function()>()));
+  Expect.isFalse(_test2(new A<B2<String> Function()>()));
+}
+
+@pragma('dart2js:noInline')
+_test2(f) => f is A<C2 Function()>;
+
+/*class: B3:checkedTypeArgument,checks=[],typeArgument*/
+class B3<T> {}
+
+/*class: C3:checkedTypeArgument,checks=[$asB3],typeArgument*/
+class C3 extends B3<int> {}
+
+@pragma('dart2js:noInline')
+test3() {
+  Expect.isFalse(_test3(new A<void Function(C3)>()));
+  Expect.isTrue(_test3(new A<void Function(B3<int>)>()));
+  Expect.isFalse(_test3(new A<void Function(B3<String>)>()));
+}
+
+@pragma('dart2js:noInline')
+_test3(f) => f is A<void Function(B3<int>)>;
+
+/*class: B4:checkedTypeArgument,checks=[],typeArgument*/
+class B4<T> {}
+
+/*class: C4:checks=[$asB4],typeArgument*/
+class C4 extends B4<int> {}
+
+@pragma('dart4js:noInline')
+test4() {
+  Expect.isTrue(_test4(new A<C4 Function()>()));
+  Expect.isTrue(_test4(new A<B4<int> Function()>()));
+  Expect.isFalse(_test4(new A<B4<String> Function()>()));
+}
+
+@pragma('dart4js:noInline')
+_test4(f) => f is A<B4<int> Function()>;
+
+/*class: B5:checkedTypeArgument,checks=[],typeArgument*/
+class B5<T> {}
+
+/*class: C5:checkedTypeArgument,checks=[$asB5],typeArgument*/
+class C5 extends B5<int> {}
+
+@pragma('dart2js:noInline')
+test5() {
+  Expect.isTrue(_test5(new A<void Function(C5 Function())>()));
+  Expect.isTrue(_test5(new A<void Function(B5<int> Function())>()));
+  Expect.isFalse(_test5(new A<void Function(B5<String> Function())>()));
+}
+
+@pragma('dart2js:noInline')
+_test5(f) => f is A<void Function(C5 Function())>;
+
+/*class: B6:checks=[],typeArgument*/
+class B6<T> {}
+
+/*class: C6:checkedTypeArgument,checks=[],typeArgument*/
+class C6 extends B6<int> {}
+
+@pragma('dart2js:noInline')
+test6() {
+  Expect.isTrue(_test6(new A<void Function(void Function(C6))>()));
+  Expect.isFalse(_test6(new A<void Function(void Function(B6<int>))>()));
+  Expect.isFalse(_test6(new A<void Function(void Function(B6<String>))>()));
+}
+
+@pragma('dart2js:noInline')
+_test6(f) => f is A<void Function(void Function(C6))>;
diff --git a/tests/compiler/dart2js/rti/emission/generic_methods_dynamic_02.dart b/tests/compiler/dart2js/rti/emission/generic_methods_dynamic_02.dart
index e091714..947dcca 100644
--- a/tests/compiler/dart2js/rti/emission/generic_methods_dynamic_02.dart
+++ b/tests/compiler/dart2js/rti/emission/generic_methods_dynamic_02.dart
@@ -20,6 +20,7 @@
   List<T> bar<T>(Iterable<T> t) => <T>[t.first];
 }
 
+@pragma('dart2js:disableFinal')
 main() {
   B b = new B();
   C c = new C();
diff --git a/tests/compiler/dart2js/rti/emission/tear_off_types.dart b/tests/compiler/dart2js/rti/emission/tear_off_types.dart
new file mode 100644
index 0000000..86d41eb
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/tear_off_types.dart
@@ -0,0 +1,159 @@
+// Copyright (c) 2019, 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 'package:expect/expect.dart';
+
+main() {
+  test1();
+  test2();
+  test3();
+  test4();
+  test5();
+  test6();
+  test7();
+}
+
+/*class: A1:checkedTypeArgument,checks=[],typeArgument*/
+class A1<T> {}
+
+/*class: B1:checks=[$asA1],typeArgument*/
+class B1 extends A1<int> {}
+
+@pragma('dart2js:noInline')
+test1() {
+  Expect.isTrue(_test1(method1a));
+  Expect.isTrue(_test1(method1b));
+  Expect.isFalse(_test1(method1c));
+}
+
+B1 method1a() => null;
+A1<int> method1b() => null;
+A1<String> method1c() => null;
+
+@pragma('dart2js:noInline')
+bool _test1(f) => f is A1<int> Function();
+
+/*strong.class: A2:checkedInstance,checkedTypeArgument,checks=[],typeArgument*/
+/*omit.class: A2:checkedTypeArgument,checks=[],typeArgument*/
+class A2<T> {}
+
+/*strong.class: B2:checkedInstance,checkedTypeArgument,checks=[$asA2],typeArgument*/
+/*omit.class: B2:checkedTypeArgument,checks=[$asA2],typeArgument*/
+class B2 extends A2<int> {}
+
+@pragma('dart2js:noInline')
+test2() {
+  Expect.isFalse(_test2(method2a));
+  Expect.isTrue(_test2(method2b));
+  Expect.isFalse(_test2(method2c));
+}
+
+void method2a(B2 b) {}
+void method2b(A2<int> a) {}
+void method2c(A2<String> a) {}
+
+@pragma('dart2js:noInline')
+bool _test2(f) => f is void Function(A2<int>);
+
+/*strong.class: A3:checkedInstance,checkedTypeArgument,checks=[],typeArgument*/
+/*omit.class: A3:checkedTypeArgument,checks=[],typeArgument*/
+class A3<T> {}
+
+/*strong.class: B3:checkedInstance,checkedTypeArgument,checks=[$asA3],typeArgument*/
+/*omit.class: B3:checkedTypeArgument,checks=[$asA3],typeArgument*/
+class B3 extends A3<int> {}
+
+@pragma('dart3js:noInline')
+test3() {
+  Expect.isTrue(_test3(method3a));
+  Expect.isTrue(_test3(method3b));
+  Expect.isFalse(_test3(method3c));
+}
+
+void method3a(B3 b) {}
+void method3b(A3<int> a) {}
+void method3c(A3<String> a) {}
+
+@pragma('dart3js:noInline')
+_test3(f) => f is void Function(B3);
+
+/*class: A4:checks=[],typeArgument*/
+class A4<T> {}
+
+/*class: B4:checkedTypeArgument,checks=[],typeArgument*/
+class B4 extends A4<int> {}
+
+@pragma('dart4js:noInline')
+test4() {
+  Expect.isTrue(_test4(method4a));
+  Expect.isFalse(_test4(method4b));
+  Expect.isFalse(_test4(method4c));
+}
+
+B4 method4a() => null;
+A4<int> method4b() => null;
+A4<String> method4c() => null;
+
+@pragma('dart4js:noInline')
+_test4(f) => f is B4 Function();
+
+/*class: A5:checkedTypeArgument,checks=[],typeArgument*/
+class A5<T> {}
+
+/*class: B5:checks=[$asA5],typeArgument*/
+class B5 extends A5<int> {}
+
+@pragma('dart2js:noInline')
+test5() {
+  Expect.isTrue(_test5(method5a));
+  Expect.isTrue(_test5(method5b));
+  Expect.isFalse(_test5(method5c));
+}
+
+void method5a(void Function(B5) f) => null;
+void method5b(void Function(A5<int>) f) => null;
+void method5c(void Function(A5<String>) f) => null;
+
+@pragma('dart2js:noInline')
+bool _test5(f) => f is void Function(void Function(A5<int>));
+
+/*class: A6:checkedTypeArgument,checks=[],typeArgument*/
+class A6<T> {}
+
+/*class: B6:checkedTypeArgument,checks=[$asA6],typeArgument*/
+class B6 extends A6<int> {}
+
+@pragma('dart6js:noInline')
+test6() {
+  Expect.isTrue(_test6(method6a));
+  Expect.isTrue(_test6(method6b));
+  Expect.isFalse(_test6(method6c));
+}
+
+void Function(B6) method6a() => null;
+void Function(A6<int>) method6b() => null;
+void Function(A6<String>) method6c() => null;
+
+@pragma('dart6js:noInline')
+_test6(f) => f is void Function(B6) Function();
+
+/*class: A7:checks=[],typeArgument*/
+class A7<T> {}
+
+/*class: B7:checkedTypeArgument,checks=[],typeArgument*/
+class B7 extends A7<int> {}
+
+@pragma('dart7js:noInline')
+test7() {
+  Expect.isTrue(_test7(method7a));
+  Expect.isFalse(_test7(method7b));
+  Expect.isFalse(_test7(method7c));
+}
+
+void method7a(void Function(B7) f) => null;
+void method7b(void Function(A7<int>) f) => null;
+void method7c(void Function(A7<String>) f) => null;
+
+@pragma('dart7js:noInline')
+_test7(f) => f is void Function(void Function(B7));
diff --git a/tests/compiler/dart2js/rti/rti_emission_test.dart b/tests/compiler/dart2js/rti/rti_emission_test.dart
index 5b7e145..0e580ca 100644
--- a/tests/compiler/dart2js/rti/rti_emission_test.dart
+++ b/tests/compiler/dart2js/rti/rti_emission_test.dart
@@ -125,12 +125,15 @@
 
 class RtiClassEmissionIrComputer extends DataRegistry<String>
     with ComputeValueMixin {
+  @override
   final Compiler compiler;
   final JsToElementMap _elementMap;
+  @override
   final Map<Id, ActualData<String>> actualMap;
 
   RtiClassEmissionIrComputer(this.compiler, this._elementMap, this.actualMap);
 
+  @override
   DiagnosticReporter get reporter => compiler.reporter;
 
   void computeClassValue(ClassEntity cls) {
@@ -145,6 +148,7 @@
     with ComputeValueMixin {
   final JsToElementMap _elementMap;
   final ClosureData _closureDataLookup;
+  @override
   final Compiler compiler;
 
   RtiMemberEmissionIrComputer(
diff --git a/tests/compiler/dart2js/rti/rti_need_test_helper.dart b/tests/compiler/dart2js/rti/rti_need_test_helper.dart
index f601ebc..4c54942 100644
--- a/tests/compiler/dart2js/rti/rti_need_test_helper.dart
+++ b/tests/compiler/dart2js/rti/rti_need_test_helper.dart
@@ -318,12 +318,15 @@
 
 class RtiClassNeedIrComputer extends DataRegistry<String>
     with ComputeValueMixin, IrMixin {
+  @override
   final Compiler compiler;
   final JsToElementMap _elementMap;
+  @override
   final Map<Id, ActualData<String>> actualMap;
 
   RtiClassNeedIrComputer(this.compiler, this._elementMap, this.actualMap);
 
+  @override
   DiagnosticReporter get reporter => compiler.reporter;
 
   void computeClassValue(ClassEntity cls) {
@@ -339,6 +342,7 @@
     with ComputeValueMixin, IrMixin {
   final JsToElementMap _elementMap;
   final ClosureData _closureDataLookup;
+  @override
   final Compiler compiler;
 
   RtiMemberNeedIrComputer(
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/colors.dart b/tests/compiler/dart2js/sourcemaps/helpers/colors.dart
index 4595382..f3d435d 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/colors.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/colors.dart
@@ -22,6 +22,7 @@
   /// all in range 0..1.
   const RGB(this.r, this.g, this.b);
 
+  @override
   String get toCss {
     StringBuffer sb = new StringBuffer();
     sb.write('#');
@@ -41,6 +42,7 @@
     return sb.toString();
   }
 
+  @override
   String toString() => 'rgb($r,$g,$b)';
 }
 
@@ -49,6 +51,7 @@
 
   const RGBA(double r, double g, double b, this.a) : super(r, g, b);
 
+  @override
   String get toCss {
     StringBuffer sb = new StringBuffer();
 
@@ -84,6 +87,7 @@
   /// saturation [s] in range 0..1, and value [v] in range 0..1.
   const HSV(this.h, this.s, this.v);
 
+  @override
   String get toCss => toRGB(this).toCss;
 
   static RGB toRGB(HSV hsv) {
@@ -116,5 +120,6 @@
     }
   }
 
+  @override
   String toString() => 'hsv($h,$s,$v)';
 }
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/diff.dart b/tests/compiler/dart2js/sourcemaps/helpers/diff.dart
index 7be8f761..012679e 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/diff.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/diff.dart
@@ -24,14 +24,17 @@
 
   const DiffColumn(this.type, [this.index]);
 
+  @override
   int get hashCode => type.hashCode * 19 + index.hashCode * 23;
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! DiffColumn) return false;
     return type == other.type && index == other.index;
   }
 
+  @override
   String toString() => '$type${index != null ? index : ''}';
 }
 
@@ -46,6 +49,7 @@
 
   PartsColumnBlock(this.parts);
 
+  @override
   void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context) {
     if (parts.isNotEmpty) {
       for (HtmlPart part in parts) {
@@ -62,6 +66,7 @@
 
   CodeLinesColumnBlock(this.jsCodeLines, this.jsToDartMap);
 
+  @override
   void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context) {
     if (jsCodeLines.isNotEmpty) {
       htmlBuffer.write('<table style="width:100%">');
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/html_parts.dart b/tests/compiler/dart2js/sourcemaps/helpers/html_parts.dart
index 77dd7cf..ad951bc 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/html_parts.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/html_parts.dart
@@ -36,8 +36,10 @@
   const AnnotationData(
       {this.tag: 'a', this.properties: const <String, String>{}});
 
+  @override
   int get hashCode => tag.hashCode * 13 + properties.hashCode * 19;
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! AnnotationData) return false;
@@ -171,6 +173,7 @@
 
   const ConstHtmlPart(this.html);
 
+  @override
   HtmlPartKind get kind => HtmlPartKind.CONST;
 
   @override
@@ -178,6 +181,7 @@
     buffer.write(html);
   }
 
+  @override
   toJson(JsonStrategy strategy) {
     return {'kind': kind.index, 'html': html};
   }
@@ -190,8 +194,10 @@
 class NewLine implements HtmlPart {
   const NewLine();
 
+  @override
   HtmlPartKind get kind => HtmlPartKind.NEWLINE;
 
+  @override
   void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {
     if (context.usePre) {
       buffer.write('\n');
@@ -200,6 +206,7 @@
     }
   }
 
+  @override
   toJson(JsonStrategy strategy) {
     return {'kind': kind.index};
   }
@@ -210,13 +217,16 @@
 
   const HtmlText(this.text);
 
+  @override
   HtmlPartKind get kind => HtmlPartKind.TEXT;
 
+  @override
   void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {
     String escaped = escape(text);
     buffer.write(escaped);
   }
 
+  @override
   toJson(JsonStrategy strategy) {
     return {'kind': kind.index, 'text': text};
   }
@@ -235,6 +245,7 @@
       {this.properties: const <String, String>{},
       this.content: const <HtmlPart>[]});
 
+  @override
   HtmlPartKind get kind => HtmlPartKind.TAG;
 
   @override
@@ -252,6 +263,7 @@
     buffer.write('</$tag>');
   }
 
+  @override
   toJson(JsonStrategy strategy) {
     return {
       'kind': kind.index,
@@ -271,6 +283,7 @@
 class HtmlLine implements HtmlPart {
   final List<HtmlPart> htmlParts = <HtmlPart>[];
 
+  @override
   HtmlPartKind get kind => HtmlPartKind.LINE;
 
   @override
@@ -280,6 +293,7 @@
     }
   }
 
+  @override
   Map toJson(JsonStrategy strategy) {
     return {
       'kind': kind.index,
@@ -370,6 +384,7 @@
 
   LineNumber(this.lineNo, this.lineAnnotation);
 
+  @override
   HtmlPartKind get kind => HtmlPartKind.LINE_NUMBER;
 
   @override
@@ -407,6 +422,7 @@
 
   CodeLine(this.lineNo, this.offset, {this.uri});
 
+  @override
   HtmlPartKind get kind => HtmlPartKind.CODE;
 
   String get code {
@@ -432,6 +448,7 @@
     }
   }
 
+  @override
   Map toJson(JsonStrategy strategy) {
     return {
       'kind': kind.index,
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/js_tracer.dart b/tests/compiler/dart2js/sourcemaps/helpers/js_tracer.dart
index bc504c76..aa234a1 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/js_tracer.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/js_tracer.dart
@@ -33,6 +33,7 @@
 
   StepTraceListener(this.graph);
 
+  @override
   SourceInformationReader get reader => const SourceInformationReader();
 
   @override
@@ -114,6 +115,7 @@
     steppableMap[node] = step;
   }
 
+  @override
   void pushBranch(BranchKind kind, [value]) {
     var branch;
     switch (kind) {
@@ -136,6 +138,7 @@
     graph.pushBranch(branch);
   }
 
+  @override
   void popBranch() {
     graph.popBranch();
   }
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/output_structure.dart b/tests/compiler/dart2js/sourcemaps/helpers/output_structure.dart
index f12212a..ddfd8c9 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/output_structure.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/output_structure.dart
@@ -86,40 +86,50 @@
 abstract class BaseOutputVisitor<R, A> extends OutputVisitor<R, A> {
   R visitEntity(OutputEntity entity, A arg) => null;
 
+  @override
   R visitStructure(OutputStructure entity, A arg) => visitEntity(entity, arg);
+  @override
   R visitLibrary(LibraryBlock entity, A arg) => visitEntity(entity, arg);
+  @override
   R visitClass(LibraryClass entity, A arg) => visitEntity(entity, arg);
 
   R visitMember(BasicEntity entity, A arg) => visitEntity(entity, arg);
 
   R visitTopLevelMember(BasicEntity entity, A arg) => visitMember(entity, arg);
 
+  @override
   R visitTopLevelFunction(TopLevelFunction entity, A arg) {
     return visitTopLevelMember(entity, arg);
   }
 
+  @override
   R visitTopLevelValue(TopLevelValue entity, A arg) {
     return visitTopLevelMember(entity, arg);
   }
 
   R visitClassMember(BasicEntity entity, A arg) => visitMember(entity, arg);
 
+  @override
   R visitMemberObject(MemberObject entity, A arg) {
     return visitClassMember(entity, arg);
   }
 
+  @override
   R visitMemberFunction(MemberFunction entity, A arg) {
     return visitClassMember(entity, arg);
   }
 
+  @override
   R visitMemberValue(MemberValue entity, A arg) {
     return visitClassMember(entity, arg);
   }
 
+  @override
   R visitStatics(Statics entity, A arg) {
     return visitClassMember(entity, arg);
   }
 
+  @override
   R visitStaticFunction(StaticFunction entity, A arg) {
     return visitClassMember(entity, arg);
   }
@@ -130,6 +140,7 @@
   final List<CodeLine> lines;
   final int headerEnd;
   final int footerStart;
+  @override
   final List<LibraryBlock> children;
 
   OutputStructure(this.lines, this.headerEnd, this.footerStart, this.children);
@@ -137,14 +148,19 @@
   @override
   EntityKind get kind => EntityKind.STRUCTURE;
 
+  @override
   Interval get interval => new Interval(0, lines.length);
 
+  @override
   Interval get header => new Interval(0, headerEnd);
 
+  @override
   Interval get footer => new Interval(footerStart, lines.length);
 
+  @override
   bool get canHaveChildren => true;
 
+  @override
   OutputEntity getEntityForLine(int line) {
     if (line < headerEnd || line >= footerStart) {
       return this;
@@ -221,6 +237,7 @@
     return new OutputStructure(lines, headerEnd, footerStart, libraryBlocks);
   }
 
+  @override
   accept(OutputVisitor visitor, arg) => visitor.visitStructure(this, arg);
 
   @override
@@ -252,6 +269,7 @@
 
   AbstractEntity(this.name, this.from);
 
+  @override
   Interval get interval => new Interval(from, to);
 
   @override
@@ -328,6 +346,7 @@
 
 /// A block defining the content of a Dart library.
 class LibraryBlock extends AbstractEntity {
+  @override
   List<BasicEntity> children = <BasicEntity>[];
   int get headerEnd => from + 2;
   int get footerStart => to /* - 1*/;
@@ -337,10 +356,13 @@
   @override
   EntityKind get kind => EntityKind.LIBRARY;
 
+  @override
   Interval get header => new Interval(from, headerEnd);
 
+  @override
   Interval get footer => new Interval(footerStart, to);
 
+  @override
   bool get canHaveChildren => true;
 
   void preprocess(List<CodeLine> lines) {
@@ -383,8 +405,10 @@
     }
   }
 
+  @override
   accept(OutputVisitor visitor, arg) => visitor.visitLibrary(this, arg);
 
+  @override
   OutputEntity getEntityForLine(int line) {
     if (line < headerEnd || line >= footerStart) {
       return this;
@@ -402,10 +426,13 @@
 abstract class BasicEntity extends AbstractEntity {
   BasicEntity(String name, int from) : super(name, from);
 
+  @override
   Interval get header => new Interval(from, to);
 
+  @override
   Interval get footer => new Interval(to, to);
 
+  @override
   List<OutputEntity> get children => const <OutputEntity>[];
 
   void preprocess(List<CodeLine> lines) {}
@@ -425,6 +452,7 @@
   @override
   EntityKind get kind => EntityKind.TOP_LEVEL_FUNCTION;
 
+  @override
   accept(OutputVisitor visitor, arg) {
     return visitor.visitTopLevelFunction(this, arg);
   }
@@ -436,6 +464,7 @@
   @override
   EntityKind get kind => EntityKind.TOP_LEVEL_VALUE;
 
+  @override
   accept(OutputVisitor visitor, arg) {
     return visitor.visitTopLevelValue(this, arg);
   }
@@ -443,6 +472,7 @@
 
 /// A block defining a Dart class.
 class LibraryClass extends BasicEntity {
+  @override
   List<BasicEntity> children = <BasicEntity>[];
   int get headerEnd => from + 1;
   int get footerStart => to - 1;
@@ -452,12 +482,16 @@
   @override
   EntityKind get kind => EntityKind.CLASS;
 
+  @override
   Interval get header => new Interval(from, headerEnd);
 
+  @override
   Interval get footer => new Interval(footerStart, to);
 
+  @override
   bool get canHaveChildren => true;
 
+  @override
   void preprocess(List<CodeLine> lines) {
     int index = headerEnd;
     BasicEntity current;
@@ -503,8 +537,10 @@
     }
   }
 
+  @override
   accept(OutputVisitor visitor, arg) => visitor.visitClass(this, arg);
 
+  @override
   OutputEntity getEntityForLine(int line) {
     if (line < headerEnd || line >= footerStart) {
       return this;
@@ -520,6 +556,7 @@
 
 /// A block defining static members of a Dart class.
 class Statics extends BasicEntity {
+  @override
   List<BasicEntity> children = <BasicEntity>[];
   int get headerEnd => from + 1;
   int get footerStart => to - 1;
@@ -529,12 +566,16 @@
   @override
   EntityKind get kind => EntityKind.STATICS;
 
+  @override
   Interval get header => new Interval(from, headerEnd);
 
+  @override
   Interval get footer => new Interval(footerStart, to);
 
+  @override
   bool get canHaveChildren => true;
 
+  @override
   void preprocess(List<CodeLine> lines) {
     int index = headerEnd;
     BasicEntity current;
@@ -561,8 +602,10 @@
     }
   }
 
+  @override
   accept(OutputVisitor visitor, arg) => visitor.visitStatics(this, arg);
 
+  @override
   OutputEntity getEntityForLine(int line) {
     if (line < headerEnd || line >= footerStart) {
       return this;
@@ -582,6 +625,7 @@
   @override
   EntityKind get kind => EntityKind.MEMBER_FUNCTION;
 
+  @override
   accept(OutputVisitor visitor, arg) => visitor.visitMemberFunction(this, arg);
 }
 
@@ -591,6 +635,7 @@
   @override
   EntityKind get kind => EntityKind.MEMBER_OBJECT;
 
+  @override
   accept(OutputVisitor visitor, arg) => visitor.visitMemberObject(this, arg);
 }
 
@@ -600,6 +645,7 @@
   @override
   EntityKind get kind => EntityKind.MEMBER_VALUE;
 
+  @override
   accept(OutputVisitor visitor, arg) => visitor.visitMemberValue(this, arg);
 }
 
@@ -609,6 +655,7 @@
   @override
   EntityKind get kind => EntityKind.STATIC_FUNCTION;
 
+  @override
   accept(OutputVisitor visitor, arg) => visitor.visitStaticFunction(this, arg);
 }
 
@@ -634,6 +681,7 @@
     return from - windowSize <= index && index < to + windowSize;
   }
 
+  @override
   String toString() => '[$from,$to[';
 }
 
@@ -652,6 +700,7 @@
     assert(uri != null);
   }
 
+  @override
   String toString() => '$uri:$name:$offset';
 
   Map toJson(JsonStrategy strategy) {
@@ -681,6 +730,7 @@
 
   CodeSource(this.kind, this.uri, this.name, this.begin, this.end);
 
+  @override
   int get hashCode {
     return kind.hashCode * 13 +
         uri.hashCode * 17 +
@@ -688,6 +738,7 @@
         begin.hashCode * 23;
   }
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! CodeSource) return false;
@@ -697,6 +748,7 @@
         begin == other.begin;
   }
 
+  @override
   String toString() => '${toJson()}';
 
   Map toJson() {
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/source_map_validator_helper.dart b/tests/compiler/dart2js/sourcemaps/helpers/source_map_validator_helper.dart
index a0b6a5a..aab0969 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/source_map_validator_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/source_map_validator_helper.dart
@@ -304,6 +304,7 @@
     return line < other.line || line == other.line && column <= other.column;
   }
 
+  @override
   String toString() => '[${line + 1},${column + 1}]';
 }
 
@@ -317,5 +318,6 @@
     return begin <= other && other <= end;
   }
 
+  @override
   String toString() => '$begin-$end';
 }
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
index 8826468..f38c7a6 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
@@ -277,6 +277,7 @@
 
   FindVisitor(this.soughtNode);
 
+  @override
   visitNode(js.Node node) {
     if (node == soughtNode) {
       found = true;
@@ -437,6 +438,7 @@
             element != null ? computeElementNameForSourceMaps(element) : '',
         this.element = element;
 
+  @override
   String toString() {
     return '$name:$element';
   }
@@ -473,8 +475,10 @@
   @override
   void registerPop(int codeOffset, {bool isEmpty: false}) {}
 
+  @override
   Iterable<js.Node> get nodes => _nodeMap.keys;
 
+  @override
   Map<int, List<SourceLocation>> operator [](js.Node node) {
     return _nodeMap[node];
   }
@@ -486,8 +490,10 @@
 
   _FilteredLocationMap(this._nodes, this.map);
 
+  @override
   Iterable<js.Node> get nodes => map.nodes.where((n) => _nodes.contains(n));
 
+  @override
   Map<int, List<SourceLocation>> operator [](js.Node node) {
     return map[node];
   }
@@ -522,6 +528,7 @@
 
   /// Called when [node] defines a step of the given [kind] at the given
   /// [offset] when the generated JavaScript code.
+  @override
   void onStep(js.Node node, Offset offset, StepKind kind) {
     if (kind == StepKind.ACCESS) return;
     register(kind, node);
@@ -588,6 +595,7 @@
       this.dartCode,
       {this.isMissing: false});
 
+  @override
   String toString() {
     return 'CodePoint[kind=$kind,js=$jsCode,dart=$dartCode,'
         'location=$sourceLocation]';
@@ -601,6 +609,7 @@
 
   IOSourceFileManager(this.base);
 
+  @override
   SourceFile getSourceFile(var uri) {
     Uri absoluteUri;
     if (uri is Uri) {
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_html_helper.dart b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_html_helper.dart
index e4b8c95..57869ca 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_html_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_html_helper.dart
@@ -80,6 +80,7 @@
   SourceMapHtmlInfo(
       this.sourceMapInfo, this.codeProcessor, this.sourceLocationCollection);
 
+  @override
   String toString() {
     return sourceMapInfo.toString();
   }
@@ -117,6 +118,7 @@
 }
 
 class CustomColorScheme implements CssColorScheme {
+  @override
   final bool showLocationAsSpan;
   final Function single;
   final Function multi;
@@ -126,8 +128,10 @@
       String this.single(int id),
       String this.multi(List<int> ids)});
 
+  @override
   String singleLocationToCssColor(int id) => single != null ? single(id) : null;
 
+  @override
   String multiLocationToCssColor(List<int> ids) =>
       multi != null ? multi(ids) : null;
 }
@@ -135,12 +139,15 @@
 class PatternCssColorScheme implements CssColorScheme {
   const PatternCssColorScheme();
 
+  @override
   bool get showLocationAsSpan => true;
 
+  @override
   String singleLocationToCssColor(int index) {
     return "background:${toPattern(index)};";
   }
 
+  @override
   String multiLocationToCssColor(List<int> indices) {
     StringBuffer sb = new StringBuffer();
     double delta = 100.0 / (indices.length);
@@ -163,12 +170,15 @@
 class SingleColorScheme implements CssColorScheme {
   const SingleColorScheme();
 
+  @override
   bool get showLocationAsSpan => false;
 
+  @override
   String singleLocationToCssColor(int index) {
     return "background:${toColorCss(index)};";
   }
 
+  @override
   String multiLocationToCssColor(List<int> indices) {
     StringBuffer sb = new StringBuffer();
     double delta = 100.0 / (indices.length);
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/trace_graph.dart b/tests/compiler/dart2js/sourcemaps/helpers/trace_graph.dart
index feceab2..d4481f8 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/trace_graph.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/trace_graph.dart
@@ -62,5 +62,6 @@
   TraceStep(this.kind, this.id, this.node, this.offset, this.text,
       [this.sourceLocation]);
 
+  @override
   String toString() => '<span style="background:${toColorCss(id)}">$id</span>';
 }
diff --git a/tests/compiler/dart2js/sourcemaps/mapping_test.dart b/tests/compiler/dart2js/sourcemaps/mapping_test.dart
index ed5d544..6c933ee 100644
--- a/tests/compiler/dart2js/sourcemaps/mapping_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/mapping_test.dart
@@ -171,9 +171,11 @@
 
   SourceLocation(this.methodName, this.lineNo, this.columnNo);
 
+  @override
   int get hashCode =>
       methodName.hashCode * 13 + lineNo.hashCode * 17 + columnNo.hashCode * 19;
 
+  @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! SourceLocation) return false;
@@ -182,5 +184,6 @@
         columnNo == other.columnNo;
   }
 
+  @override
   String toString() => '$methodName:$lineNo:$columnNo';
 }
diff --git a/tests/compiler/dart2js/sourcemaps/minified/no_such_method.dart b/tests/compiler/dart2js/sourcemaps/minified/no_such_method.dart
index 6fcd2aa..88383df 100644
--- a/tests/compiler/dart2js/sourcemaps/minified/no_such_method.dart
+++ b/tests/compiler/dart2js/sourcemaps/minified/no_such_method.dart
@@ -17,6 +17,7 @@
 confuse(x) => x;
 
 class A {
+  @override
   noSuchMethod(i) => null;
 }
 
diff --git a/tests/compiler/dart2js/sourcemaps/minified/no_such_method2.dart b/tests/compiler/dart2js/sourcemaps/minified/no_such_method2.dart
index 98e56b9..c169326 100644
--- a/tests/compiler/dart2js/sourcemaps/minified/no_such_method2.dart
+++ b/tests/compiler/dart2js/sourcemaps/minified/no_such_method2.dart
@@ -17,6 +17,7 @@
 confuse(x) => x;
 
 class A {
+  @override
   noSuchMethod(i) => null;
 }
 
diff --git a/tests/compiler/dart2js/sourcemaps/tools/diff_view.dart b/tests/compiler/dart2js/sourcemaps/tools/diff_view.dart
index ea6456b..2701c10 100644
--- a/tests/compiler/dart2js/sourcemaps/tools/diff_view.dart
+++ b/tests/compiler/dart2js/sourcemaps/tools/diff_view.dart
@@ -124,6 +124,7 @@
 class CodeLineAnnotationJsonStrategy implements JsonStrategy {
   const CodeLineAnnotationJsonStrategy();
 
+  @override
   Map encodeAnnotation(Annotation annotation) {
     CodeLineAnnotation data = annotation.data;
     return {
@@ -134,6 +135,7 @@
     };
   }
 
+  @override
   Annotation decodeAnnotation(Map json) {
     return new Annotation(json['id'], json['codeOffset'], json['title'],
         data: CodeLineAnnotation.fromJson(json['data'], this));
diff --git a/tests/compiler/dart2js/sourcemaps/tools/source_mapping_test_viewer.dart b/tests/compiler/dart2js/sourcemaps/tools/source_mapping_test_viewer.dart
index f6e7687..ac18b0b 100644
--- a/tests/compiler/dart2js/sourcemaps/tools/source_mapping_test_viewer.dart
+++ b/tests/compiler/dart2js/sourcemaps/tools/source_mapping_test_viewer.dart
@@ -92,7 +92,9 @@
 }
 
 class OutputConfigurations implements Configurations {
+  @override
   final Iterable<String> configs;
+  @override
   final Iterable<String> files;
   final Map<Pair, String> pathMap = {};
   final Map<Pair, Uri> uriMap = {};
@@ -156,6 +158,7 @@
 
   Measurement(this.config, this.filename, this.missing, this.count);
 
+  @override
   String toString() {
     double percentage = 100 * missing / count;
     return "Config '${config}', file: '${filename}': "
diff --git a/tests/compiler/dart2js_extra/constant_folding_test.dart b/tests/compiler/dart2js_extra/constant_folding_test.dart
new file mode 100644
index 0000000..cc88f68
--- /dev/null
+++ b/tests/compiler/dart2js_extra/constant_folding_test.dart
@@ -0,0 +1,1241 @@
+// Copyright (c) 2019, 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 "package:expect/expect.dart";
+
+void main() {
+  const BitNot(42, 4294967253).check();
+  const BitNot(4294967253, 42).check();
+  const BitNot(-42, 41).check();
+  const BitNot(-1, 0).check();
+  const BitNot(0, 0xFFFFFFFF).check();
+  const BitNot(4294967295, 0).check();
+  const BitNot(0x12121212121212, 0xEDEDEDED).check();
+
+  const Negate(0, -0).check();
+  const Negate(-0, 0).check();
+  const Negate(0.0, -0.0).check();
+  const Negate(-0.0, 0.0).check();
+  const Negate(-0.0, 0).check();
+  const Negate(-0, 0.0).check();
+  const Negate(0, -0.0).check();
+  const Negate(0.0, -0).check();
+  const Negate(1, -1).check();
+  const Negate(-1, 1).check();
+  const Negate(1.0, -1.0).check();
+  const Negate(-1.0, 1.0).check();
+  const Negate(3.14, -3.14).check();
+  const Negate(-3.14, 3.14).check();
+  const Negate(4294967295, -4294967295).check();
+  const Negate(-4294967295, 4294967295).check();
+  const Negate(4294967295.5, -4294967295.5).check();
+  const Negate(-4294967295.5, 4294967295.5).check();
+  const Negate(4294967296, -4294967296).check();
+  const Negate(-4294967296, 4294967296).check();
+  const Negate(4294967296.5, -4294967296.5).check();
+  const Negate(-4294967296.5, 4294967296.5).check();
+  const Negate(9007199254740991, -9007199254740991).check();
+  const Negate(-9007199254740991, 9007199254740991).check();
+  const Negate(9007199254740991.5, -9007199254740991.5).check();
+  const Negate(-9007199254740991.5, 9007199254740991.5).check();
+  const Negate(9007199254740992, -9007199254740992).check();
+  const Negate(-9007199254740992, 9007199254740992).check();
+  const Negate(9007199254740992.5, -9007199254740992.5).check();
+  const Negate(-9007199254740992.5, 9007199254740992.5).check();
+  const Negate(double.infinity, double.negativeInfinity).check();
+  const Negate(double.negativeInfinity, double.infinity).check();
+  const Negate(double.maxFinite, -double.maxFinite).check();
+  const Negate(-double.maxFinite, double.maxFinite).check();
+  const Negate(double.minPositive, -double.minPositive).check();
+  const Negate(-double.minPositive, double.minPositive).check();
+  const Negate(double.nan, double.nan).check();
+
+  const Not(true, false).check();
+  const Not(false, true).check();
+
+  const BitAnd(314159, 271828, 262404).check();
+  const BitAnd(271828, 314159, 262404).check();
+  const BitAnd(0, 0, 0).check();
+  const BitAnd(-1, 0, 0).check();
+  const BitAnd(-1, 314159, 314159).check();
+  const BitAnd(-1, 0xFFFFFFFF, 0xFFFFFFFF).check();
+  const BitAnd(0xff, -4, 0xfc).check();
+  const BitAnd(0, 0xFFFFFFFF, 0).check();
+  const BitAnd(0xFFFFFFFF, 0, 0).check();
+  const BitAnd(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF).check();
+  const BitAnd(0x123456789ABC, 0xEEEEEEEEEEEE, 0x46688AAC).check();
+
+  const BitOr(314159, 271828, 323583).check();
+  const BitOr(271828, 314159, 323583).check();
+  const BitOr(0, 0, 0).check();
+  const BitOr(-8, 0, 0xFFFFFFF8).check();
+  const BitOr(-8, 271828, 0xFFFFFFFC).check();
+  const BitOr(-8, 0xFFFFFFFF, 0xFFFFFFFF).check();
+  const BitOr(0x1, -4, 0xFFFFFFFD).check();
+  const BitOr(0, 0xFFFFFFFF, 0xFFFFFFFF).check();
+  const BitOr(0xFFFFFFFF, 0, 0xFFFFFFFF).check();
+  const BitOr(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF).check();
+  const BitOr(0x123456789ABC, 0x111111111111, 0x57799BBD).check();
+
+  const BitXor(314159, 271828, 61179).check();
+  const BitXor(271828, 314159, 61179).check();
+  const BitXor(0, 0, 0).check();
+  const BitXor(-1, 0, 0xFFFFFFFF).check();
+  const BitXor(-256, 1, 0xFFFFFF01).check();
+  const BitXor(-256, -255, 1).check();
+  const BitXor(0, 0xFFFFFFFF, 0xFFFFFFFF).check();
+  const BitXor(0xFFFFFFFF, 0, 0xFFFFFFFF).check();
+  const BitXor(0xFFFFFFFF, 0xFFFFFFFF, 0).check();
+  const BitXor(0x123456789ABC, 0x111111111111, 0x47698BAD).check();
+
+  const ShiftLeft(42, 0, 42).check();
+  const ShiftLeft(42, 5, 1344).check();
+  const ShiftLeft(1, 31, 0x80000000).check();
+  const ShiftLeft(1, 32, 0).check();
+  const ShiftLeft(1, 100, 0).check();
+  const ShiftLeft(0, 0, 0).check();
+  const ShiftLeft(0, 5, 0).check();
+  const ShiftLeft(0, 31, 0).check();
+  const ShiftLeft(0, 32, 0).check();
+  const ShiftLeft(0, 100, 0).check();
+  const ShiftLeft(-1, 0, 0xFFFFFFFF).check();
+  const ShiftLeft(-1, 5, 0xFFFFFFE0).check();
+  const ShiftLeft(-1, 31, 0x80000000).check();
+  const ShiftLeft(-1, 32, 0).check();
+  const ShiftLeft(-1, 100, 0).check();
+
+  const ShiftRight(8675309, 0, 8675309).check();
+  const ShiftRight(8675309, 5, 271103).check();
+  const ShiftRight(0xFEDCBA98, 0, 0xFEDCBA98).check();
+  const ShiftRight(0xFEDCBA98, 5, 0x07F6E5D4).check();
+  const ShiftRight(0xFEDCBA98, 31, 1).check();
+  const ShiftRight(0xFEDCBA98, 32, 0).check();
+  const ShiftRight(0xFEDCBA98, 100, 0).check();
+  const ShiftRight(0xFFFFFEDCBA98, 0, 0xFEDCBA98).check();
+  const ShiftRight(0xFFFFFEDCBA98, 5, 0x07F6E5D4).check();
+  const ShiftRight(0xFFFFFEDCBA98, 31, 1).check();
+  const ShiftRight(0xFFFFFEDCBA98, 32, 0).check();
+  const ShiftRight(0xFFFFFEDCBA98, 100, 0).check();
+  const ShiftRight(-1, 0, 0xFFFFFFFF).check();
+  const ShiftRight(-1, 5, 0xFFFFFFFF).check();
+  const ShiftRight(-1, 31, 0xFFFFFFFF).check();
+  const ShiftRight(-1, 32, 0xFFFFFFFF).check();
+  const ShiftRight(-1, 100, 0xFFFFFFFF).check();
+  const ShiftRight(-1073741824, 0, 0xC0000000).check();
+  const ShiftRight(-1073741824, 5, 0xFE000000).check();
+  const ShiftRight(-1073741824, 31, 0xFFFFFFFF).check();
+  const ShiftRight(-1073741824, 32, 0xFFFFFFFF).check();
+  const ShiftRight(-1073741824, 100, 0xFFFFFFFF).check();
+
+  const BooleanAnd(true, true, true).check();
+  const BooleanAnd(true, false, false).check();
+  const BooleanAnd(false, true, false).check();
+  const BooleanAnd(false, false, false).check();
+  const BooleanAnd(false, null, false).check();
+
+  const BooleanOr(true, true, true).check();
+  const BooleanOr(true, false, true).check();
+  const BooleanOr(false, true, true).check();
+  const BooleanOr(false, false, false).check();
+  const BooleanOr(true, null, true).check();
+
+  const Subtract(314159, 271828, 42331).check();
+  const Subtract(271828, 314159, -42331).check();
+  const Subtract(0, 0, 0).check();
+  const Subtract(0, 42, -42).check();
+  const Subtract(0, -42, 42).check();
+  const Subtract(42, 0, 42).check();
+  const Subtract(42, 42, 0).check();
+  const Subtract(42, -42, 84).check();
+  const Subtract(-42, 0, -42).check();
+  const Subtract(-42, 42, -84).check();
+  const Subtract(-42, -42, 0).check();
+  const Subtract(4294967295, -1, 4294967296).check();
+  const Subtract(4294967296, -1, 4294967297).check();
+  const Subtract(9007199254740991, -1, 9007199254740992).check();
+  const Subtract(9007199254740992, -1, 9007199254740992).check();
+  const Subtract(9007199254740992, -100, 9007199254741092).check();
+  const Subtract(-4294967295, 1, -4294967296).check();
+  const Subtract(-4294967296, 1, -4294967297).check();
+  const Subtract(-9007199254740991, 1, -9007199254740992).check();
+  const Subtract(-9007199254740992, 1, -9007199254740992).check();
+  const Subtract(-9007199254740992, 100, -9007199254741092).check();
+  const Subtract(
+          0x7fffffff00000000, -0x7fffffff00000000, 2 * 0x7fffffff00000000)
+      .check();
+  const Subtract(4.2, 1.5, 2.7).check();
+  const Subtract(1.5, 4.2, -2.7).check();
+  const Subtract(1.5, 0, 1.5).check();
+  const Subtract(0, 1.5, -1.5).check();
+  const Subtract(1.5, 1.5, 0.0).check();
+  const Subtract(-1.5, -1.5, 0.0).check();
+  const Subtract(0.0, 0.0, 0.0).check();
+  const Subtract(0.0, -0.0, 0.0).check();
+  const Subtract(-0.0, 0.0, -0.0).check();
+  const Subtract(-0.0, -0.0, 0.0).check();
+  const Subtract(double.maxFinite, -double.maxFinite, double.infinity).check();
+  const Subtract(-double.maxFinite, double.maxFinite, double.negativeInfinity)
+      .check();
+  const Subtract(1.5, double.nan, double.nan).check();
+  const Subtract(double.nan, 1.5, double.nan).check();
+  const Subtract(double.nan, double.nan, double.nan).check();
+  const Subtract(double.nan, double.infinity, double.nan).check();
+  const Subtract(double.nan, double.negativeInfinity, double.nan).check();
+  const Subtract(double.infinity, double.nan, double.nan).check();
+  const Subtract(double.negativeInfinity, double.nan, double.nan).check();
+  const Subtract(double.infinity, double.maxFinite, double.infinity).check();
+  const Subtract(double.infinity, -double.maxFinite, double.infinity).check();
+  const Subtract(
+          double.negativeInfinity, double.maxFinite, double.negativeInfinity)
+      .check();
+  const Subtract(
+          double.negativeInfinity, -double.maxFinite, double.negativeInfinity)
+      .check();
+  const Subtract(1.5, double.infinity, double.negativeInfinity).check();
+  const Subtract(1.5, double.negativeInfinity, double.infinity).check();
+  const Subtract(double.infinity, double.infinity, double.nan).check();
+  const Subtract(double.infinity, double.negativeInfinity, double.infinity)
+      .check();
+  const Subtract(
+          double.negativeInfinity, double.infinity, double.negativeInfinity)
+      .check();
+  const Subtract(double.negativeInfinity, double.negativeInfinity, double.nan)
+      .check();
+  const Subtract(double.minPositive, double.minPositive, 0.0).check();
+  const Subtract(-double.minPositive, -double.minPositive, 0.0).check();
+
+  const Multiply(6, 7, 42).check();
+  const Multiply(-6, 7, -42).check();
+  const Multiply(6, -7, -42).check();
+  const Multiply(-6, -7, 42).check();
+  const Multiply(0, 0, 0).check();
+  const Multiply(0, 7, 0).check();
+  const Multiply(6, 0, 0).check();
+  const Multiply(65536, 65536, 4294967296).check();
+  const Multiply(4294967296, -1, -4294967296).check();
+  const Multiply(-1, 4294967296, -4294967296).check();
+  const Multiply(134217728, 134217728, 18014398509481984).check();
+  const Multiply(18014398509481984, -1, -18014398509481984).check();
+  const Multiply(-1, 18014398509481984, -18014398509481984).check();
+  const Multiply(9000000000000000, 9000000000000000, 8.1e31).check();
+  const Multiply(0x7fff000000000000, 0x8000000000000000, 8.506799558180535e37)
+      .check();
+  const Multiply(0x8000000000000000, 1.2, 11068046444225730000.0).check();
+  const Multiply(3.14, 2.72, 8.5408).check();
+  const Multiply(-3.14, 2.72, -8.5408).check();
+  const Multiply(3.14, -2.72, -8.5408).check();
+  const Multiply(-3.14, -2.72, 8.5408).check();
+  const Multiply(3.14, 0, 0.0).check();
+  const Multiply(0, 2.72, 0.0).check();
+  const Multiply(0.0, 0.0, 0.0).check();
+  const Multiply(0.0, -0.0, -0.0).check();
+  const Multiply(-0.0, 0.0, -0.0).check();
+  const Multiply(-0.0, -0.0, 0.0).check();
+  const Multiply(double.maxFinite, double.maxFinite, double.infinity).check();
+  const Multiply(double.maxFinite, -double.maxFinite, double.negativeInfinity)
+      .check();
+  const Multiply(-double.maxFinite, double.maxFinite, double.negativeInfinity)
+      .check();
+  const Multiply(-double.maxFinite, -double.maxFinite, double.infinity).check();
+  const Multiply(0, double.nan, double.nan).check();
+  const Multiply(double.nan, 0, double.nan).check();
+  const Multiply(double.nan, double.nan, double.nan).check();
+  const Multiply(0, double.infinity, double.nan).check();
+  const Multiply(double.infinity, 0, double.nan).check();
+  const Multiply(0, double.negativeInfinity, double.nan).check();
+  const Multiply(double.negativeInfinity, 0, double.nan).check();
+  const Multiply(-0.0, double.infinity, double.nan).check();
+  const Multiply(double.infinity, -0.0, double.nan).check();
+  const Multiply(-0.0, double.negativeInfinity, double.nan).check();
+  const Multiply(double.negativeInfinity, -0.0, double.nan).check();
+  const Multiply(double.infinity, double.infinity, double.infinity).check();
+  const Multiply(
+          double.infinity, double.negativeInfinity, double.negativeInfinity)
+      .check();
+  const Multiply(
+          double.negativeInfinity, double.infinity, double.negativeInfinity)
+      .check();
+  const Multiply(
+          double.negativeInfinity, double.negativeInfinity, double.infinity)
+      .check();
+  const Multiply(double.minPositive, 0.5, 0.0).check();
+  const Multiply(double.minPositive, -0.5, -0.0).check();
+  const Multiply(-double.minPositive, 0.5, -0.0).check();
+  const Multiply(-double.minPositive, -0.5, 0.0).check();
+  const Multiply(1e-300, -1e-300, -0.0).check();
+  const Multiply(double.minPositive, double.infinity, double.infinity).check();
+  const Multiply(
+          double.minPositive, double.negativeInfinity, double.negativeInfinity)
+      .check();
+  const Multiply(double.minPositive, double.maxFinite, 8.881784197001251e-16)
+      .check();
+
+  const Modulo(27, 314159, 27).check();
+  const Modulo(27, 1, 0).check();
+  const Modulo(27, -1, 0).check();
+  const Modulo(-27, 1, 0).check();
+  const Modulo(-27, -1, 0).check();
+  const Modulo(314159, 27, 14).check();
+  const Modulo(314159, -27, 14).check();
+  const Modulo(-314159, 27, 13).check();
+  const Modulo(-314159, -27, 13).check();
+  const Modulo(4294967295, 4294967296, 4294967295).check();
+  const Modulo(4294967295, -4294967296, 4294967295).check();
+  const Modulo(-4294967295, 4294967296, 1).check();
+  const Modulo(-4294967295, -4294967296, 1).check();
+  const Modulo(9007199254740991, 9007199254740992, 9007199254740991).check();
+  const Modulo(9007199254740991, -9007199254740992, 9007199254740991).check();
+  const Modulo(-9007199254740991, 9007199254740992, 1).check();
+  const Modulo(-9007199254740991, -9007199254740992, 1).check();
+  const Modulo(2.71828, 3.14159, 2.71828).check();
+  const Modulo(2.71828, 1, 0.71828).check();
+  const Modulo(2.71828, -1, 0.71828).check();
+  const Modulo(-2.71828, 1, 0.28171999999999997).check();
+  const Modulo(-2.71828, -1, 0.28171999999999997).check();
+  const Modulo(27.1828, 3.14159, 2.0500800000000012).check();
+  const Modulo(27.1828, -3.14159, 2.0500800000000012).check();
+  const Modulo(-27.1828, 3.14159, 1.0915099999999986).check();
+  const Modulo(-27.1828, -3.14159, 1.0915099999999986).check();
+  const Modulo(42, double.nan, double.nan).check();
+  const Modulo(double.nan, 42, double.nan).check();
+  const Modulo(0, double.nan, double.nan).check();
+  const Modulo(double.nan, double.nan, double.nan).check();
+  const Modulo(double.infinity, double.nan, double.nan).check();
+  const Modulo(double.nan, double.infinity, double.nan).check();
+  const Modulo(0.0, double.infinity, 0).check();
+  const Modulo(-0.0, double.infinity, 0).check();
+  const Modulo(0.0, double.negativeInfinity, 0).check();
+  const Modulo(-0.0, double.negativeInfinity, 0).check();
+  const Modulo(42, double.infinity, 42).check();
+  const Modulo(-42, double.infinity, double.infinity).check();
+  const Modulo(42, double.negativeInfinity, 42).check();
+  const Modulo(-42, double.negativeInfinity, double.infinity).check();
+  const Modulo(double.infinity, 42, double.nan).check();
+  const Modulo(double.infinity, -42, double.nan).check();
+  const Modulo(double.negativeInfinity, 42, double.nan).check();
+  const Modulo(double.negativeInfinity, -42, double.nan).check();
+  const Modulo(double.infinity, double.infinity, double.nan).check();
+  const Modulo(double.negativeInfinity, double.infinity, double.nan).check();
+  const Modulo(double.infinity, double.negativeInfinity, double.nan).check();
+  const Modulo(double.negativeInfinity, double.negativeInfinity, double.nan)
+      .check();
+
+  const TruncatingDivide(27, 314159, 0).check();
+  const TruncatingDivide(27, 1, 27).check();
+  const TruncatingDivide(27, -1, -27).check();
+  const TruncatingDivide(-27, 1, -27).check();
+  const TruncatingDivide(-27, -1, 27).check();
+  const TruncatingDivide(314159, 27, 11635).check();
+  const TruncatingDivide(314159, -27, -11635).check();
+  const TruncatingDivide(-314159, 27, -11635).check();
+  const TruncatingDivide(-314159, -27, 11635).check();
+  const TruncatingDivide(4294967295, 4294967296, 0).check();
+  const TruncatingDivide(4294967295, -4294967296, 0).check();
+  const TruncatingDivide(-4294967295, 4294967296, 0).check();
+  const TruncatingDivide(-4294967295, -4294967296, 0).check();
+  const TruncatingDivide(9007199254740991, 9007199254740992, 0).check();
+  const TruncatingDivide(9007199254740991, -9007199254740992, 0).check();
+  const TruncatingDivide(-9007199254740991, 9007199254740992, 0).check();
+  const TruncatingDivide(-9007199254740991, -9007199254740992, 0).check();
+  const TruncatingDivide(4294967295, 0.5, 8589934590).check();
+  const TruncatingDivide(4294967295, -0.5, -8589934590).check();
+  const TruncatingDivide(-4294967295, 0.5, -8589934590).check();
+  const TruncatingDivide(-4294967295, -0.5, 8589934590).check();
+  const TruncatingDivide(9007199254740991, 0.5, 18014398509481982).check();
+  const TruncatingDivide(9007199254740991, -0.5, -18014398509481982).check();
+  const TruncatingDivide(-9007199254740991, 0.5, -18014398509481982).check();
+  const TruncatingDivide(-9007199254740991, -0.5, 18014398509481982).check();
+  const TruncatingDivide(
+          0x80000000 * 0x100000000, -1, -0x80000000 * 0x100000000)
+      .check();
+  const TruncatingDivide(2.71828, 3.14159, 0).check();
+  const TruncatingDivide(2.71828, 1, 2).check();
+  const TruncatingDivide(2.71828, -1, -2).check();
+  const TruncatingDivide(-2.71828, 1, -2).check();
+  const TruncatingDivide(-2.71828, -1, 2).check();
+  const TruncatingDivide(27.1828, 3.14159, 8).check();
+  const TruncatingDivide(27.1828, -3.14159, -8).check();
+  const TruncatingDivide(-27.1828, 3.14159, -8).check();
+  const TruncatingDivide(-27.1828, -3.14159, 8).check();
+  const TruncatingDivide(0.0, double.infinity, 0).check();
+  const TruncatingDivide(-0.0, double.infinity, 0).check();
+  const TruncatingDivide(0.0, double.negativeInfinity, 0).check();
+  const TruncatingDivide(-0.0, double.negativeInfinity, 0).check();
+  const TruncatingDivide(42, double.infinity, 0).check();
+  const TruncatingDivide(-42, double.infinity, 0).check();
+  const TruncatingDivide(42, double.negativeInfinity, 0).check();
+  const TruncatingDivide(-42, double.negativeInfinity, 0).check();
+
+  const Divide(27, 3, 9).check();
+  const Divide(27, 1, 27).check();
+  const Divide(27, -1, -27).check();
+  const Divide(-27, 1, -27).check();
+  const Divide(-27, -1, 27).check();
+  const Divide(0, 1, 0).check();
+  const Divide(0, -1, -0.0).check();
+  const Divide(-0.0, 1, -0.0).check();
+  const Divide(-0.0, -1, 0).check();
+  const Divide(314159, 27, 11635.518518518518).check();
+  const Divide(314159, -27, -11635.518518518518).check();
+  const Divide(-314159, 27, -11635.518518518518).check();
+  const Divide(-314159, -27, 11635.518518518518).check();
+  const Divide(4294967295, 4294967296, 0.9999999997671694).check();
+  const Divide(4294967295, -4294967296, -0.9999999997671694).check();
+  const Divide(-4294967295, 4294967296, -0.9999999997671694).check();
+  const Divide(-4294967295, -4294967296, 0.9999999997671694).check();
+  const Divide(9007199254740991, 9007199254740992, 0.9999999999999999).check();
+  const Divide(9007199254740991, -9007199254740992, -0.9999999999999999)
+      .check();
+  const Divide(-9007199254740991, 9007199254740992, -0.9999999999999999)
+      .check();
+  const Divide(-9007199254740991, -9007199254740992, 0.9999999999999999)
+      .check();
+  const Divide(4294967296, 4294967295, 1.0000000002328306).check();
+  const Divide(4294967296, -4294967295, -1.0000000002328306).check();
+  const Divide(-4294967296, 4294967295, -1.0000000002328306).check();
+  const Divide(-4294967296, -4294967295, 1.0000000002328306).check();
+  const Divide(9007199254740992, 9007199254740991, 1.0000000000000002).check();
+  const Divide(9007199254740992, -9007199254740991, -1.0000000000000002)
+      .check();
+  const Divide(-9007199254740992, 9007199254740991, -1.0000000000000002)
+      .check();
+  const Divide(-9007199254740992, -9007199254740991, 1.0000000000000002)
+      .check();
+  const Divide(4294967295, 0.5, 8589934590).check();
+  const Divide(4294967295, -0.5, -8589934590).check();
+  const Divide(-4294967295, 0.5, -8589934590).check();
+  const Divide(-4294967295, -0.5, 8589934590).check();
+  const Divide(9007199254740991, 0.5, 18014398509481982).check();
+  const Divide(9007199254740991, -0.5, -18014398509481982).check();
+  const Divide(-9007199254740991, 0.5, -18014398509481982).check();
+  const Divide(-9007199254740991, -0.5, 18014398509481982).check();
+  const Divide(2.71828, 3.14159, 0.8652561282662601).check();
+  const Divide(2.71828, 1, 2.71828).check();
+  const Divide(2.71828, -1, -2.71828).check();
+  const Divide(-2.71828, 1, -2.71828).check();
+  const Divide(-2.71828, -1, 2.71828).check();
+  const Divide(27.1828, 3.14159, 8.652561282662601).check();
+  const Divide(27.1828, -3.14159, -8.652561282662601).check();
+  const Divide(-27.1828, 3.14159, -8.652561282662601).check();
+  const Divide(-27.1828, -3.14159, 8.652561282662601).check();
+  const Divide(1, 0, double.infinity).check();
+  const Divide(1, -0.0, double.negativeInfinity).check();
+  const Divide(-1, 0, double.negativeInfinity).check();
+  const Divide(-1, -0.0, double.infinity).check();
+  const Divide(0, 0, double.nan).check();
+  const Divide(0, -0.0, double.nan).check();
+  const Divide(-0.0, 0, double.nan).check();
+  const Divide(-0.0, -0.0, double.nan).check();
+  const Divide(double.infinity, 0, double.infinity).check();
+  const Divide(double.infinity, -0.0, double.negativeInfinity).check();
+  const Divide(double.negativeInfinity, 0, double.negativeInfinity).check();
+  const Divide(double.negativeInfinity, -0.0, double.infinity).check();
+  const Divide(double.nan, 0, double.nan).check();
+  const Divide(double.nan, -0.0, double.nan).check();
+  const Divide(double.nan, 1, double.nan).check();
+  const Divide(1, double.nan, double.nan).check();
+  const Divide(0, double.nan, double.nan).check();
+  const Divide(double.nan, double.nan, double.nan).check();
+  const Divide(double.nan, double.infinity, double.nan).check();
+  const Divide(double.infinity, double.nan, double.nan).check();
+  const Divide(double.negativeInfinity, double.nan, double.nan).check();
+  const Divide(double.infinity, 1, double.infinity).check();
+  const Divide(double.infinity, -1, double.negativeInfinity).check();
+  const Divide(double.negativeInfinity, 1, double.negativeInfinity).check();
+  const Divide(double.negativeInfinity, -1, double.infinity).check();
+  const Divide(0, double.infinity, 0).check();
+  const Divide(0, double.negativeInfinity, -0.0).check();
+  const Divide(-0.0, double.infinity, -0.0).check();
+  const Divide(-0.0, double.negativeInfinity, 0).check();
+  const Divide(1, double.infinity, 0).check();
+  const Divide(1, double.negativeInfinity, -0.0).check();
+  const Divide(-1, double.infinity, -0.0).check();
+  const Divide(-1, double.negativeInfinity, 0).check();
+  const Divide(double.infinity, double.infinity, double.nan).check();
+  const Divide(double.minPositive, double.maxFinite, 0).check();
+  const Divide(double.minPositive, -double.maxFinite, -0.0).check();
+  const Divide(-double.minPositive, double.maxFinite, -0.0).check();
+  const Divide(-double.minPositive, -double.maxFinite, 0).check();
+  const Divide(double.maxFinite, double.minPositive, double.infinity).check();
+  const Divide(double.maxFinite, -double.minPositive, double.negativeInfinity)
+      .check();
+  const Divide(-double.maxFinite, double.minPositive, double.negativeInfinity)
+      .check();
+  const Divide(-double.maxFinite, -double.minPositive, double.infinity).check();
+
+  const Add("", "", "").check();
+  const Add("foo", "", "foo").check();
+  const Add("", "bar", "bar").check();
+  const Add("foo", "bar", "foobar").check();
+  const Add(314159, 271828, 585987).check();
+  const Add(314159, -271828, 42331).check();
+  const Add(-314159, 271828, -42331).check();
+  const Add(-314159, -271828, -585987).check();
+  const Add(0, 0, 0).check();
+  const Add(0, 42, 42).check();
+  const Add(0, -42, -42).check();
+  const Add(42, 0, 42).check();
+  const Add(42, 42, 84).check();
+  const Add(42, -42, 0).check();
+  const Add(-42, 0, -42).check();
+  const Add(-42, 42, 0).check();
+  const Add(-42, -42, -84).check();
+  const Add(4294967295, 1, 4294967296).check();
+  const Add(4294967296, 1, 4294967297).check();
+  const Add(9007199254740991, 1, 9007199254740992).check();
+  const Add(9007199254740992, 1, 9007199254740992).check();
+  const Add(9007199254740992, 100, 9007199254741092).check();
+  const Add(-4294967295, -1, -4294967296).check();
+  const Add(-4294967296, -1, -4294967297).check();
+  const Add(-9007199254740991, -1, -9007199254740992).check();
+  const Add(-9007199254740992, -1, -9007199254740992).check();
+  const Add(-9007199254740992, -100, -9007199254741092).check();
+  const Add(4.2, 1.5, 5.7).check();
+  const Add(4.2, -1.5, 2.7).check();
+  const Add(-4.2, 1.5, -2.7).check();
+  const Add(-4.2, -1.5, -5.7).check();
+  const Add(1.5, 0, 1.5).check();
+  const Add(0, 1.5, 1.5).check();
+  const Add(1.5, -1.5, 0.0).check();
+  const Add(-1.5, 1.5, 0.0).check();
+  const Add(0.0, 0.0, 0.0).check();
+  const Add(0.0, -0.0, 0.0).check();
+  const Add(-0.0, 0.0, 0.0).check();
+  const Add(-0.0, -0.0, -0.0).check();
+  const Add(double.maxFinite, double.maxFinite, double.infinity).check();
+  const Add(-double.maxFinite, -double.maxFinite, double.negativeInfinity)
+      .check();
+  const Add(1.5, double.nan, double.nan).check();
+  const Add(double.nan, 1.5, double.nan).check();
+  const Add(double.nan, double.nan, double.nan).check();
+  const Add(double.nan, double.infinity, double.nan).check();
+  const Add(double.nan, double.negativeInfinity, double.nan).check();
+  const Add(double.infinity, double.nan, double.nan).check();
+  const Add(double.negativeInfinity, double.nan, double.nan).check();
+  const Add(double.infinity, -double.maxFinite, double.infinity).check();
+  const Add(double.infinity, double.maxFinite, double.infinity).check();
+  const Add(double.negativeInfinity, -double.maxFinite, double.negativeInfinity)
+      .check();
+  const Add(double.negativeInfinity, double.maxFinite, double.negativeInfinity)
+      .check();
+  const Add(1.5, double.negativeInfinity, double.negativeInfinity).check();
+  const Add(1.5, double.infinity, double.infinity).check();
+  const Add(double.infinity, double.infinity, double.infinity).check();
+  const Add(double.infinity, double.negativeInfinity, double.nan).check();
+  const Add(double.negativeInfinity, double.infinity, double.nan).check();
+  const Add(double.negativeInfinity, double.negativeInfinity,
+          double.negativeInfinity)
+      .check();
+  const Add(double.minPositive, -double.minPositive, 0.0).check();
+  const Add(-double.minPositive, double.minPositive, 0.0).check();
+
+  const Less(double.nan, double.nan, false).check();
+  const Less(double.nan, double.infinity, false).check();
+  const Less(double.infinity, double.nan, false).check();
+  const Less(double.nan, double.maxFinite, false).check();
+  const Less(double.maxFinite, double.nan, false).check();
+  const Less(double.nan, -double.maxFinite, false).check();
+  const Less(-double.maxFinite, double.nan, false).check();
+  const Less(double.nan, double.negativeInfinity, false).check();
+  const Less(double.negativeInfinity, double.nan, false).check();
+  const Less(double.negativeInfinity, double.negativeInfinity, false).check();
+  const Less(double.negativeInfinity, -double.maxFinite, true).check();
+  const Less(-double.maxFinite, double.negativeInfinity, false).check();
+  const Less(-double.maxFinite, -double.maxFinite, false).check();
+  const Less(-double.maxFinite, -9007199254740992, true).check();
+  const Less(-9007199254740992, -double.maxFinite, false).check();
+  const Less(-9007199254740992, -9007199254740992, false).check();
+  const Less(-9007199254740992, -4294967296, true).check();
+  const Less(-4294967296, -9007199254740992, false).check();
+  const Less(-4294967296, -4294967296, false).check();
+  const Less(-4294967296, -42, true).check();
+  const Less(-42, -4294967296, false).check();
+  const Less(-42, -42, false).check();
+  const Less(-42, -42.0, false).check();
+  const Less(-42.0, -42, false).check();
+  const Less(-42.0, -42.0, false).check();
+  const Less(-42, -3.14, true).check();
+  const Less(-3.14, -42, false).check();
+  const Less(-3.14, -3.14, false).check();
+  const Less(-3.14, -double.minPositive, true).check();
+  const Less(-double.minPositive, -3.14, false).check();
+  const Less(-double.minPositive, -double.minPositive, false).check();
+  const Less(-double.minPositive, -0.0, true).check();
+  const Less(-0.0, -double.minPositive, false).check();
+  const Less(-0.0, -0.0, false).check();
+  const Less(0, 0, false).check();
+  const Less(0.0, 0.0, false).check();
+  const Less(-0.0, 0, false).check();
+  const Less(0, -0.0, false).check();
+  const Less(-0.0, 0.0, false).check();
+  const Less(0.0, -0.0, false).check();
+  const Less(0, 0.0, false).check();
+  const Less(0.0, 0, false).check();
+  const Less(0.0, double.minPositive, true).check();
+  const Less(double.minPositive, 0.0, false).check();
+  const Less(double.minPositive, double.minPositive, false).check();
+  const Less(double.minPositive, 3.14, true).check();
+  const Less(3.14, double.minPositive, false).check();
+  const Less(3.14, 3.14, false).check();
+  const Less(3.14, 42, true).check();
+  const Less(42, 3.14, false).check();
+  const Less(42.0, 42.0, false).check();
+  const Less(42, 42.0, false).check();
+  const Less(42.0, 42, false).check();
+  const Less(42, 42, false).check();
+  const Less(42, 4294967296, true).check();
+  const Less(4294967296, 42, false).check();
+  const Less(4294967296, 4294967296, false).check();
+  const Less(4294967296, 9007199254740992, true).check();
+  const Less(9007199254740992, 4294967296, false).check();
+  const Less(9007199254740992, 9007199254740992, false).check();
+  const Less(9007199254740992, double.maxFinite, true).check();
+  const Less(double.maxFinite, 9007199254740992, false).check();
+  const Less(double.maxFinite, double.maxFinite, false).check();
+  const Less(double.maxFinite, double.infinity, true).check();
+  const Less(double.infinity, double.maxFinite, false).check();
+  const Less(double.infinity, double.infinity, false).check();
+  const Less(0x7fffffff00000000, 0x8000000000000000, true).check();
+  const Less(0x8000000000000000, 0x7fffffff00000000, false).check();
+
+  const LessEqual(double.nan, double.nan, false).check();
+  const LessEqual(double.nan, double.infinity, false).check();
+  const LessEqual(double.infinity, double.nan, false).check();
+  const LessEqual(double.nan, double.maxFinite, false).check();
+  const LessEqual(double.maxFinite, double.nan, false).check();
+  const LessEqual(double.nan, -double.maxFinite, false).check();
+  const LessEqual(-double.maxFinite, double.nan, false).check();
+  const LessEqual(double.nan, double.negativeInfinity, false).check();
+  const LessEqual(double.negativeInfinity, double.nan, false).check();
+  const LessEqual(double.negativeInfinity, double.negativeInfinity, true)
+      .check();
+  const LessEqual(double.negativeInfinity, -double.maxFinite, true).check();
+  const LessEqual(-double.maxFinite, double.negativeInfinity, false).check();
+  const LessEqual(-double.maxFinite, -double.maxFinite, true).check();
+  const LessEqual(-double.maxFinite, -9007199254740992, true).check();
+  const LessEqual(-9007199254740992, -double.maxFinite, false).check();
+  const LessEqual(-9007199254740992, -9007199254740992, true).check();
+  const LessEqual(-9007199254740992, -4294967296, true).check();
+  const LessEqual(-4294967296, -9007199254740992, false).check();
+  const LessEqual(-4294967296, -4294967296, true).check();
+  const LessEqual(-4294967296, -42, true).check();
+  const LessEqual(-42, -4294967296, false).check();
+  const LessEqual(-42, -42, true).check();
+  const LessEqual(-42, -42.0, true).check();
+  const LessEqual(-42.0, -42, true).check();
+  const LessEqual(-42.0, -42.0, true).check();
+  const LessEqual(-42, -3.14, true).check();
+  const LessEqual(-3.14, -42, false).check();
+  const LessEqual(-3.14, -3.14, true).check();
+  const LessEqual(-3.14, -double.minPositive, true).check();
+  const LessEqual(-double.minPositive, -3.14, false).check();
+  const LessEqual(-double.minPositive, -double.minPositive, true).check();
+  const LessEqual(-double.minPositive, -0.0, true).check();
+  const LessEqual(-0.0, -double.minPositive, false).check();
+  const LessEqual(-0.0, -0.0, true).check();
+  const LessEqual(0, 0, true).check();
+  const LessEqual(0.0, 0.0, true).check();
+  const LessEqual(-0.0, 0, true).check();
+  const LessEqual(0, -0.0, true).check();
+  const LessEqual(-0.0, 0.0, true).check();
+  const LessEqual(0.0, -0.0, true).check();
+  const LessEqual(0, 0.0, true).check();
+  const LessEqual(0.0, 0, true).check();
+  const LessEqual(0.0, double.minPositive, true).check();
+  const LessEqual(double.minPositive, 0.0, false).check();
+  const LessEqual(double.minPositive, double.minPositive, true).check();
+  const LessEqual(double.minPositive, 3.14, true).check();
+  const LessEqual(3.14, double.minPositive, false).check();
+  const LessEqual(3.14, 3.14, true).check();
+  const LessEqual(3.14, 42, true).check();
+  const LessEqual(42, 3.14, false).check();
+  const LessEqual(42.0, 42.0, true).check();
+  const LessEqual(42, 42.0, true).check();
+  const LessEqual(42.0, 42, true).check();
+  const LessEqual(42, 42, true).check();
+  const LessEqual(42, 4294967296, true).check();
+  const LessEqual(4294967296, 42, false).check();
+  const LessEqual(4294967296, 4294967296, true).check();
+  const LessEqual(4294967296, 9007199254740992, true).check();
+  const LessEqual(9007199254740992, 4294967296, false).check();
+  const LessEqual(9007199254740992, 9007199254740992, true).check();
+  const LessEqual(9007199254740992, double.maxFinite, true).check();
+  const LessEqual(double.maxFinite, 9007199254740992, false).check();
+  const LessEqual(double.maxFinite, double.maxFinite, true).check();
+  const LessEqual(double.maxFinite, double.infinity, true).check();
+  const LessEqual(double.infinity, double.maxFinite, false).check();
+  const LessEqual(double.infinity, double.infinity, true).check();
+  const LessEqual(0x7fffffff00000000, 0x8000000000000000, true).check();
+  const LessEqual(0x8000000000000000, 0x7fffffff00000000, false).check();
+
+  const Greater(double.nan, double.nan, false).check();
+  const Greater(double.nan, double.infinity, false).check();
+  const Greater(double.infinity, double.nan, false).check();
+  const Greater(double.nan, double.maxFinite, false).check();
+  const Greater(double.maxFinite, double.nan, false).check();
+  const Greater(double.nan, -double.maxFinite, false).check();
+  const Greater(-double.maxFinite, double.nan, false).check();
+  const Greater(double.nan, double.negativeInfinity, false).check();
+  const Greater(double.negativeInfinity, double.nan, false).check();
+  const Greater(double.negativeInfinity, double.negativeInfinity, false)
+      .check();
+  const Greater(double.negativeInfinity, -double.maxFinite, false).check();
+  const Greater(-double.maxFinite, double.negativeInfinity, true).check();
+  const Greater(-double.maxFinite, -double.maxFinite, false).check();
+  const Greater(-double.maxFinite, -9007199254740992, false).check();
+  const Greater(-9007199254740992, -double.maxFinite, true).check();
+  const Greater(-9007199254740992, -9007199254740992, false).check();
+  const Greater(-9007199254740992, -4294967296, false).check();
+  const Greater(-4294967296, -9007199254740992, true).check();
+  const Greater(-4294967296, -4294967296, false).check();
+  const Greater(-4294967296, -42, false).check();
+  const Greater(-42, -4294967296, true).check();
+  const Greater(-42, -42, false).check();
+  const Greater(-42, -42.0, false).check();
+  const Greater(-42.0, -42, false).check();
+  const Greater(-42.0, -42.0, false).check();
+  const Greater(-42, -3.14, false).check();
+  const Greater(-3.14, -42, true).check();
+  const Greater(-3.14, -3.14, false).check();
+  const Greater(-3.14, -double.minPositive, false).check();
+  const Greater(-double.minPositive, -3.14, true).check();
+  const Greater(-double.minPositive, -double.minPositive, false).check();
+  const Greater(-double.minPositive, -0.0, false).check();
+  const Greater(-0.0, -double.minPositive, true).check();
+  const Greater(-0.0, -0.0, false).check();
+  const Greater(0, 0, false).check();
+  const Greater(0.0, 0.0, false).check();
+  const Greater(-0.0, 0, false).check();
+  const Greater(0, -0.0, false).check();
+  const Greater(-0.0, 0.0, false).check();
+  const Greater(0.0, -0.0, false).check();
+  const Greater(0, 0.0, false).check();
+  const Greater(0.0, 0, false).check();
+  const Greater(0.0, double.minPositive, false).check();
+  const Greater(double.minPositive, 0.0, true).check();
+  const Greater(double.minPositive, double.minPositive, false).check();
+  const Greater(double.minPositive, 3.14, false).check();
+  const Greater(3.14, double.minPositive, true).check();
+  const Greater(3.14, 3.14, false).check();
+  const Greater(3.14, 42, false).check();
+  const Greater(42, 3.14, true).check();
+  const Greater(42.0, 42.0, false).check();
+  const Greater(42, 42.0, false).check();
+  const Greater(42.0, 42, false).check();
+  const Greater(42, 42, false).check();
+  const Greater(42, 4294967296, false).check();
+  const Greater(4294967296, 42, true).check();
+  const Greater(4294967296, 4294967296, false).check();
+  const Greater(4294967296, 9007199254740992, false).check();
+  const Greater(9007199254740992, 4294967296, true).check();
+  const Greater(9007199254740992, 9007199254740992, false).check();
+  const Greater(9007199254740992, double.maxFinite, false).check();
+  const Greater(double.maxFinite, 9007199254740992, true).check();
+  const Greater(double.maxFinite, double.maxFinite, false).check();
+  const Greater(double.maxFinite, double.infinity, false).check();
+  const Greater(double.infinity, double.maxFinite, true).check();
+  const Greater(double.infinity, double.infinity, false).check();
+  const Greater(0x7fffffff00000000, 0x8000000000000000, false).check();
+  const Greater(0x8000000000000000, 0x7fffffff00000000, true).check();
+
+  const GreaterEqual(double.nan, double.nan, false).check();
+  const GreaterEqual(double.nan, double.infinity, false).check();
+  const GreaterEqual(double.infinity, double.nan, false).check();
+  const GreaterEqual(double.nan, double.maxFinite, false).check();
+  const GreaterEqual(double.maxFinite, double.nan, false).check();
+  const GreaterEqual(double.nan, -double.maxFinite, false).check();
+  const GreaterEqual(-double.maxFinite, double.nan, false).check();
+  const GreaterEqual(double.nan, double.negativeInfinity, false).check();
+  const GreaterEqual(double.negativeInfinity, double.nan, false).check();
+  const GreaterEqual(double.negativeInfinity, double.negativeInfinity, true)
+      .check();
+  const GreaterEqual(double.negativeInfinity, -double.maxFinite, false).check();
+  const GreaterEqual(-double.maxFinite, double.negativeInfinity, true).check();
+  const GreaterEqual(-double.maxFinite, -double.maxFinite, true).check();
+  const GreaterEqual(-double.maxFinite, -9007199254740992, false).check();
+  const GreaterEqual(-9007199254740992, -double.maxFinite, true).check();
+  const GreaterEqual(-9007199254740992, -9007199254740992, true).check();
+  const GreaterEqual(-9007199254740992, -4294967296, false).check();
+  const GreaterEqual(-4294967296, -9007199254740992, true).check();
+  const GreaterEqual(-4294967296, -4294967296, true).check();
+  const GreaterEqual(-4294967296, -42, false).check();
+  const GreaterEqual(-42, -4294967296, true).check();
+  const GreaterEqual(-42, -42, true).check();
+  const GreaterEqual(-42, -42.0, true).check();
+  const GreaterEqual(-42.0, -42, true).check();
+  const GreaterEqual(-42.0, -42.0, true).check();
+  const GreaterEqual(-42, -3.14, false).check();
+  const GreaterEqual(-3.14, -42, true).check();
+  const GreaterEqual(-3.14, -3.14, true).check();
+  const GreaterEqual(-3.14, -double.minPositive, false).check();
+  const GreaterEqual(-double.minPositive, -3.14, true).check();
+  const GreaterEqual(-double.minPositive, -double.minPositive, true).check();
+  const GreaterEqual(-double.minPositive, -0.0, false).check();
+  const GreaterEqual(-0.0, -double.minPositive, true).check();
+  const GreaterEqual(-0.0, -0.0, true).check();
+  const GreaterEqual(0, 0, true).check();
+  const GreaterEqual(0.0, 0.0, true).check();
+  const GreaterEqual(-0.0, 0, true).check();
+  const GreaterEqual(0, -0.0, true).check();
+  const GreaterEqual(-0.0, 0.0, true).check();
+  const GreaterEqual(0.0, -0.0, true).check();
+  const GreaterEqual(0, 0.0, true).check();
+  const GreaterEqual(0.0, 0, true).check();
+  const GreaterEqual(0.0, double.minPositive, false).check();
+  const GreaterEqual(double.minPositive, 0.0, true).check();
+  const GreaterEqual(double.minPositive, double.minPositive, true).check();
+  const GreaterEqual(double.minPositive, 3.14, false).check();
+  const GreaterEqual(3.14, double.minPositive, true).check();
+  const GreaterEqual(3.14, 3.14, true).check();
+  const GreaterEqual(3.14, 42, false).check();
+  const GreaterEqual(42, 3.14, true).check();
+  const GreaterEqual(42.0, 42.0, true).check();
+  const GreaterEqual(42, 42.0, true).check();
+  const GreaterEqual(42.0, 42, true).check();
+  const GreaterEqual(42, 42, true).check();
+  const GreaterEqual(42, 4294967296, false).check();
+  const GreaterEqual(4294967296, 42, true).check();
+  const GreaterEqual(4294967296, 4294967296, true).check();
+  const GreaterEqual(4294967296, 9007199254740992, false).check();
+  const GreaterEqual(9007199254740992, 4294967296, true).check();
+  const GreaterEqual(9007199254740992, 9007199254740992, true).check();
+  const GreaterEqual(9007199254740992, double.maxFinite, false).check();
+  const GreaterEqual(double.maxFinite, 9007199254740992, true).check();
+  const GreaterEqual(double.maxFinite, double.maxFinite, true).check();
+  const GreaterEqual(double.maxFinite, double.infinity, false).check();
+  const GreaterEqual(double.infinity, double.maxFinite, true).check();
+  const GreaterEqual(double.infinity, double.infinity, true).check();
+  const GreaterEqual(0x7fffffff00000000, 0x8000000000000000, false).check();
+  const GreaterEqual(0x8000000000000000, 0x7fffffff00000000, true).check();
+
+  const Equals(null, null, true).check();
+  const Equals(null, "", false).check();
+  const Equals("", null, false).check();
+  const Equals("", "", true).check();
+  const Equals(true, true, true).check();
+  const Equals(false, false, true).check();
+  const Equals(true, false, false).check();
+  const Equals(false, true, false).check();
+  const Equals(0, false, false).check();
+  const Equals(true, 1, false).check();
+  const Equals(double.nan, double.nan, false).check();
+  const Equals(0, 0, true).check();
+  const Equals(0.0, 0.0, true).check();
+  const Equals(-0.0, -0.0, true).check();
+  const Equals(0, 0.0, true).check();
+  const Equals(0.0, 0, true).check();
+  const Equals(0, -0.0, true).check();
+  const Equals(-0.0, 0, true).check();
+  const Equals(0.0, -0.0, true).check();
+  const Equals(-0.0, 0.0, true).check();
+  const Equals(1, 1, true).check();
+  const Equals(1.0, 1.0, true).check();
+  const Equals(1, 1.0, true).check();
+  const Equals(1.0, 1, true).check();
+  const Equals(double.infinity, double.infinity, true).check();
+  const Equals(double.infinity, double.negativeInfinity, false).check();
+  const Equals(double.negativeInfinity, double.infinity, false).check();
+  const Equals(double.negativeInfinity, double.negativeInfinity, true).check();
+
+  const Identity(null, null, true).check();
+  const Identity(null, "", false).check();
+  const Identity("", null, false).check();
+  const Identity("", "", true).check();
+  const Identity(true, true, true).check();
+  const Identity(false, false, true).check();
+  const Identity(true, false, false).check();
+  const Identity(false, true, false).check();
+  const Identity(0, false, false).check();
+  const Identity(true, 1, false).check();
+  // TODO(36194)
+  //const Identity(double.nan, double.nan, false).check();
+  const Identity(0, 0, true).check();
+  const Identity(0.0, 0.0, true).check();
+  const Identity(-0.0, -0.0, true).check();
+  const Identity(0, 0.0, true).check();
+  const Identity(0.0, 0, true).check();
+  const Identity(0, -0.0, true).check();
+  const Identity(-0.0, 0, true).check();
+  const Identity(0.0, -0.0, true).check();
+  const Identity(-0.0, 0.0, true).check();
+  const Identity(1, 1, true).check();
+  const Identity(1.0, 1.0, true).check();
+  const Identity(1, 1.0, true).check();
+  const Identity(1.0, 1, true).check();
+  const Identity(double.infinity, double.infinity, true).check();
+  const Identity(double.infinity, double.negativeInfinity, false).check();
+  const Identity(double.negativeInfinity, double.infinity, false).check();
+  const Identity(double.negativeInfinity, double.negativeInfinity, true)
+      .check();
+
+  const IfNull(null, null, null).check();
+  const IfNull(null, 1, 1).check();
+  const IfNull("foo", 1, "foo").check();
+  const IfNull("foo", null, "foo").check();
+}
+
+/// Wraps [Expect.equals] to accommodate JS equality semantics.
+///
+/// Naively using [Expect.equals] causes JS values to be compared with `===`.
+/// This can yield some unintended results:
+///
+/// * Since `NaN === NaN` is `false`, [Expect.equals] will throw even if both
+///   values are `NaN`. Therefore, we check for `NaN` specifically.
+/// * Since `0.0 === -0.0` is `true`, [Expect.equals] will fail to throw if one
+///   constant evaluation results in `0` or `0.0` and the other results in
+///   `-0.0`. Therefore, we additionally check that both values have the same
+///   sign in this case.
+void jsEquals(expected, actual, [String reason = null]) {
+  if (expected is num && actual is num) {
+    if (expected.isNaN && actual.isNaN) return;
+  }
+
+  Expect.equals(expected, actual, reason);
+
+  if (expected == 0 && actual == 0) {
+    Expect.equals(
+        expected.isNegative,
+        actual.isNegative,
+        (reason == null ? "" : "$reason ") +
+            "${expected.toString()} and "
+            "${actual.toString()} have different signs.");
+  }
+}
+
+abstract class TestOp {
+  final expected;
+  final result;
+
+  const TestOp(this.expected, this.result);
+
+  @pragma('dart2js:noInline')
+  checkAll(evalResult) {
+    jsEquals(expected, result,
+        "Frontend constant evaluation does not yield expected value.");
+    jsEquals(expected, evalResult,
+        "Backend constant evaluation does not yield expected value.");
+    jsEquals(expected, eval(), "eval() does not yield expected value.");
+  }
+
+  eval();
+}
+
+class BitNot extends TestOp {
+  final arg;
+
+  const BitNot(this.arg, expected) : super(expected, ~arg);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @override
+  @pragma('dart2js:tryInline')
+  eval() => ~arg;
+}
+
+class Negate extends TestOp {
+  final arg;
+
+  const Negate(this.arg, expected) : super(expected, -arg);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @override
+  @pragma('dart2js:tryInline')
+  eval() => -arg;
+}
+
+class Not extends TestOp {
+  final arg;
+
+  const Not(this.arg, expected) : super(expected, !arg);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @override
+  @pragma('dart2js:tryInline')
+  eval() => !arg;
+}
+
+class BitAnd extends TestOp {
+  final arg1;
+  final arg2;
+
+  const BitAnd(this.arg1, this.arg2, expected) : super(expected, arg1 & arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @override
+  @pragma('dart2js:tryInline')
+  eval() => arg1 & arg2;
+}
+
+class BitOr extends TestOp {
+  final arg1;
+  final arg2;
+
+  const BitOr(this.arg1, this.arg2, expected) : super(expected, arg1 | arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @override
+  @pragma('dart2js:tryInline')
+  eval() => arg1 | arg2;
+}
+
+class BitXor extends TestOp {
+  final arg1;
+  final arg2;
+
+  const BitXor(this.arg1, this.arg2, expected) : super(expected, arg1 ^ arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @override
+  @pragma('dart2js:tryInline')
+  eval() => arg1 ^ arg2;
+}
+
+class ShiftLeft extends TestOp {
+  final arg1;
+  final arg2;
+
+  const ShiftLeft(this.arg1, this.arg2, expected)
+      : super(expected, arg1 << arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @override
+  @pragma('dart2js:tryInline')
+  eval() => arg1 << arg2;
+}
+
+class ShiftRight extends TestOp {
+  final arg1;
+  final arg2;
+
+  const ShiftRight(this.arg1, this.arg2, expected)
+      : super(expected, arg1 >> arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @override
+  @pragma('dart2js:tryInline')
+  eval() => arg1 >> arg2;
+}
+
+class BooleanAnd extends TestOp {
+  final arg1;
+  final arg2;
+
+  const BooleanAnd(this.arg1, this.arg2, expected)
+      : super(expected, arg1 && arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @override
+  @pragma('dart2js:tryInline')
+  eval() => arg1 && arg2;
+}
+
+class BooleanOr extends TestOp {
+  final arg1;
+  final arg2;
+
+  const BooleanOr(this.arg1, this.arg2, expected)
+      : super(expected, arg1 || arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @override
+  @pragma('dart2js:tryInline')
+  eval() => arg1 || arg2;
+}
+
+class Subtract extends TestOp {
+  final arg1;
+  final arg2;
+
+  const Subtract(this.arg1, this.arg2, expected) : super(expected, arg1 - arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @override
+  @pragma('dart2js:tryInline')
+  eval() => arg1 - arg2;
+}
+
+class Multiply extends TestOp {
+  final arg1;
+  final arg2;
+
+  const Multiply(this.arg1, this.arg2, expected) : super(expected, arg1 * arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @override
+  @pragma('dart2js:tryInline')
+  eval() => arg1 * arg2;
+}
+
+class Modulo extends TestOp {
+  final arg1;
+  final arg2;
+
+  const Modulo(this.arg1, this.arg2, expected) : super(expected, arg1 % arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @override
+  @pragma('dart2js:tryInline')
+  eval() => arg1 % arg2;
+}
+
+class TruncatingDivide extends TestOp {
+  final arg1;
+  final arg2;
+
+  const TruncatingDivide(this.arg1, this.arg2, expected)
+      : super(expected, arg1 ~/ arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @override
+  @pragma('dart2js:tryInline')
+  eval() => arg1 ~/ arg2;
+}
+
+class Divide extends TestOp {
+  final arg1;
+  final arg2;
+
+  const Divide(this.arg1, this.arg2, expected) : super(expected, arg1 / arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @override
+  @pragma('dart2js:tryInline')
+  eval() => arg1 / arg2;
+}
+
+class Add extends TestOp {
+  final arg1;
+  final arg2;
+
+  const Add(this.arg1, this.arg2, expected) : super(expected, arg1 + arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @pragma('dart2js:tryInline')
+  eval() => arg1 + arg2;
+}
+
+class Less extends TestOp {
+  final arg1;
+  final arg2;
+
+  const Less(this.arg1, this.arg2, expected) : super(expected, arg1 < arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @pragma('dart2js:tryInline')
+  eval() => arg1 < arg2;
+}
+
+class LessEqual extends TestOp {
+  final arg1;
+  final arg2;
+
+  const LessEqual(this.arg1, this.arg2, expected)
+      : super(expected, arg1 <= arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @pragma('dart2js:tryInline')
+  eval() => arg1 <= arg2;
+}
+
+class Greater extends TestOp {
+  final arg1;
+  final arg2;
+
+  const Greater(this.arg1, this.arg2, expected) : super(expected, arg1 > arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @pragma('dart2js:tryInline')
+  eval() => arg1 > arg2;
+}
+
+class GreaterEqual extends TestOp {
+  final arg1;
+  final arg2;
+
+  const GreaterEqual(this.arg1, this.arg2, expected)
+      : super(expected, arg1 >= arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @pragma('dart2js:tryInline')
+  eval() => arg1 >= arg2;
+}
+
+class Equals extends TestOp {
+  final arg1;
+  final arg2;
+
+  const Equals(this.arg1, this.arg2, expected) : super(expected, arg1 == arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @pragma('dart2js:tryInline')
+  eval() => arg1 == arg2;
+}
+
+class Identity extends TestOp {
+  final arg1;
+  final arg2;
+
+  const Identity(this.arg1, this.arg2, expected)
+      : super(expected, identical(arg1, arg2));
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @pragma('dart2js:tryInline')
+  eval() => identical(arg1, arg2);
+}
+
+class IfNull extends TestOp {
+  final arg1;
+  final arg2;
+
+  const IfNull(this.arg1, this.arg2, expected) : super(expected, arg1 ?? arg2);
+
+  @pragma('dart2js:tryInline')
+  check() => checkAll(eval());
+
+  @pragma('dart2js:tryInline')
+  eval() => arg1 ?? arg2;
+}
diff --git a/tests/compiler/dart2js_extra/effectively_constant_instance_field_test.dart b/tests/compiler/dart2js_extra/effectively_constant_instance_field_test.dart
new file mode 100644
index 0000000..94020a2
--- /dev/null
+++ b/tests/compiler/dart2js_extra/effectively_constant_instance_field_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, 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.
+
+// dart2jsOptions=--omit-implicit-checks
+
+import 'package:expect/expect.dart';
+
+class C {
+  const C();
+}
+
+class A {
+  var field = const C();
+}
+
+class B {
+  var field;
+}
+
+@pragma('dart2js:noInline')
+test(o) => o.field;
+
+main() {
+  Expect.isNotNull(test(new A()));
+  Expect.isNull(test(new B()));
+}
diff --git a/tests/compiler/dart2js_extra/function_typed_arguments_test.dart b/tests/compiler/dart2js_extra/function_typed_arguments_test.dart
new file mode 100644
index 0000000..f18daee
--- /dev/null
+++ b/tests/compiler/dart2js_extra/function_typed_arguments_test.dart
@@ -0,0 +1,104 @@
+// Copyright (c) 2019, 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.
+
+// dart2jsOptions=--omit-implicit-checks
+
+// Test type tests of function types used a type argument.
+
+import 'package:expect/expect.dart';
+
+class A<T> {}
+
+main() {
+  test1();
+  test2();
+  test3();
+  test4();
+  test5();
+  test6();
+}
+
+class B1<T> {}
+
+class C1 extends B1<int> {}
+
+@pragma('dart2js:noInline')
+test1() {
+  Expect.isTrue(_test1(new A<void Function(C1)>()));
+  Expect.isTrue(_test1(new A<void Function(B1<int>)>())); //# 01: ok
+  Expect.isFalse(_test1(new A<void Function(B1<String>)>()));
+}
+
+@pragma('dart2js:noInline')
+_test1(f) => f is A<void Function(C1)>;
+
+class B2<T> {}
+
+class C2 extends B2<int> {}
+
+@pragma('dart2js:noInline')
+test2() {
+  Expect.isTrue(_test2(new A<C2 Function()>()));
+  Expect.isFalse(_test2(new A<B2<int> Function()>()));
+  Expect.isFalse(_test2(new A<B2<String> Function()>()));
+}
+
+@pragma('dart2js:noInline')
+_test2(f) => f is A<C2 Function()>;
+
+class B3<T> {}
+
+class C3 extends B3<int> {}
+
+@pragma('dart2js:noInline')
+test3() {
+  Expect.isFalse(_test3(new A<void Function(C3)>()));
+  Expect.isTrue(_test3(new A<void Function(B3<int>)>()));
+  Expect.isFalse(_test3(new A<void Function(B3<String>)>()));
+}
+
+@pragma('dart2js:noInline')
+_test3(f) => f is A<void Function(B3<int>)>;
+
+class B4<T> {}
+
+class C4 extends B4<int> {}
+
+@pragma('dart4js:noInline')
+test4() {
+  Expect.isTrue(_test4(new A<C4 Function()>()));
+  Expect.isTrue(_test4(new A<B4<int> Function()>()));
+  Expect.isFalse(_test4(new A<B4<String> Function()>()));
+}
+
+@pragma('dart4js:noInline')
+_test4(f) => f is A<B4<int> Function()>;
+
+class B5<T> {}
+
+class C5 extends B5<int> {}
+
+@pragma('dart2js:noInline')
+test5() {
+  Expect.isTrue(_test5(new A<void Function(C5 Function())>()));
+  Expect.isTrue(_test5(new A<void Function(B5<int> Function())>())); //# 02: ok
+  Expect.isFalse(_test5(new A<void Function(B5<String> Function())>()));
+}
+
+@pragma('dart2js:noInline')
+_test5(f) => f is A<void Function(C5 Function())>;
+
+class B6<T> {}
+
+class C6 extends B6<int> {}
+
+@pragma('dart2js:noInline')
+test6() {
+  Expect.isTrue(_test6(new A<void Function(void Function(C6))>()));
+  Expect.isFalse(_test6(new A<void Function(void Function(B6<int>))>()));
+  Expect.isFalse(_test6(new A<void Function(void Function(B6<String>))>()));
+}
+
+@pragma('dart2js:noInline')
+_test6(f) => f is A<void Function(void Function(C6))>;
diff --git a/tests/compiler/dart2js_extra/injected_cast_test.dart b/tests/compiler/dart2js_extra/injected_cast_test.dart
new file mode 100644
index 0000000..3ab671c
--- /dev/null
+++ b/tests/compiler/dart2js_extra/injected_cast_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2019, 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 'package:expect/expect.dart';
+
+var field;
+
+class Class {
+  @pragma('dart2js:noInline')
+  method(int i, int j, int k) {}
+}
+
+@pragma('dart2js:noInline')
+test1(dynamic c, num n) {
+  if (c is Class) {
+    c.method(field = 41, n, field = 42);
+  }
+}
+
+@pragma('dart2js:noInline')
+test2(dynamic c, num n) {
+  if (c is! Class) return;
+  c.method(field = 86, n, field = 87);
+}
+
+main() {
+  try {
+    test1(new Class(), 0.5);
+    field = 123;
+    field = 123;
+  } catch (e) {}
+  // CFE inserts the implicit cast directly on the argument expression, making
+  // it fail before later arguments are evaluated.
+  Expect.equals(41, field);
+
+  try {
+    test2(new Class(), 0.5);
+    field = 321;
+    field = 321;
+  } catch (e) {}
+  // dart2js inserts implicit casts, but does so after evaluating all arguments
+  // to ensure semantics match what it would be like to check the types when
+  // entering the callee.
+  Expect.equals(87, field);
+}
diff --git a/tests/compiler/dart2js_extra/regress_36222_test.dart b/tests/compiler/dart2js_extra/regress_36222_test.dart
new file mode 100644
index 0000000..f030833
--- /dev/null
+++ b/tests/compiler/dart2js_extra/regress_36222_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2019, 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.
+
+typedef int BinaryFunc(int x, int y);
+
+class A {
+  const A({this.foo = A.defaultFoo});
+
+  static int defaultFoo(int x, int y) {
+    return x + y;
+  }
+
+  final BinaryFunc foo;
+}
+
+@pragma('dart2js:assumeDynamic')
+@pragma('dart2js:noInline')
+test(dynamic a) => a.foo(1, 2);
+
+main() {
+  test(new A());
+}
diff --git a/tests/compiler/dart2js_extra/tear_off_types_test.dart b/tests/compiler/dart2js_extra/tear_off_types_test.dart
new file mode 100644
index 0000000..d7f6c41
--- /dev/null
+++ b/tests/compiler/dart2js_extra/tear_off_types_test.dart
@@ -0,0 +1,143 @@
+// Copyright (c) 2019, 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.
+
+// dart2jsOptions=--omit-implicit-checks
+
+import 'package:expect/expect.dart';
+
+main() {
+  test1();
+  test2();
+  test3();
+  test4();
+  test5();
+  test6();
+  test7();
+}
+
+class A1<T> {}
+
+class B1 extends A1<int> {}
+
+@pragma('dart2js:noInline')
+test1() {
+  Expect.isTrue(_test1(method1a));
+  Expect.isTrue(_test1(method1b));
+  Expect.isFalse(_test1(method1c));
+}
+
+B1 method1a() => null;
+A1<int> method1b() => null;
+A1<String> method1c() => null;
+
+@pragma('dart2js:noInline')
+bool _test1(f) => f is A1<int> Function();
+
+class A2<T> {}
+
+class B2 extends A2<int> {}
+
+@pragma('dart2js:noInline')
+test2() {
+  Expect.isFalse(_test2(method2a));
+  Expect.isTrue(_test2(method2b));
+  Expect.isFalse(_test2(method2c));
+}
+
+void method2a(B2 b) {}
+void method2b(A2<int> a) {}
+void method2c(A2<String> a) {}
+
+@pragma('dart2js:noInline')
+bool _test2(f) => f is void Function(A2<int>);
+
+class A3<T> {}
+
+class B3 extends A3<int> {}
+
+@pragma('dart3js:noInline')
+test3() {
+  Expect.isTrue(_test3(method3a));
+  Expect.isTrue(_test3(method3b));
+  Expect.isFalse(_test3(method3c));
+}
+
+void method3a(B3 b) {}
+void method3b(A3<int> a) {}
+void method3c(A3<String> a) {}
+
+@pragma('dart3js:noInline')
+_test3(f) => f is void Function(B3);
+
+class A4<T> {}
+
+class B4 extends A4<int> {}
+
+@pragma('dart4js:noInline')
+test4() {
+  Expect.isTrue(_test4(method4a));
+  Expect.isFalse(_test4(method4b));
+  Expect.isFalse(_test4(method4c));
+}
+
+B4 method4a() => null;
+A4<int> method4b() => null;
+A4<String> method4c() => null;
+
+@pragma('dart4js:noInline')
+_test4(f) => f is B4 Function();
+
+class A5<T> {}
+
+class B5 extends A5<int> {}
+
+@pragma('dart2js:noInline')
+test5() {
+  Expect.isTrue(_test5(method5a));
+  Expect.isTrue(_test5(method5b));
+  Expect.isFalse(_test5(method5c));
+}
+
+void method5a(void Function(B5) f) => null;
+void method5b(void Function(A5<int>) f) => null;
+void method5c(void Function(A5<String>) f) => null;
+
+@pragma('dart2js:noInline')
+bool _test5(f) => f is void Function(void Function(A5<int>));
+
+class A6<T> {}
+
+class B6 extends A6<int> {}
+
+@pragma('dart6js:noInline')
+test6() {
+  Expect.isTrue(_test6(method6a));
+  Expect.isTrue(_test6(method6b));
+  Expect.isFalse(_test6(method6c));
+}
+
+void Function(B6) method6a() => null;
+void Function(A6<int>) method6b() => null;
+void Function(A6<String>) method6c() => null;
+
+@pragma('dart6js:noInline')
+_test6(f) => f is void Function(B6) Function();
+
+class A7<T> {}
+
+class B7 extends A7<int> {}
+
+@pragma('dart7js:noInline')
+test7() {
+  Expect.isTrue(_test7(method7a));
+  Expect.isFalse(_test7(method7b));
+  Expect.isFalse(_test7(method7c));
+}
+
+void method7a(void Function(B7) f) => null;
+void method7b(void Function(A7<int>) f) => null;
+void method7c(void Function(A7<String>) f) => null;
+
+@pragma('dart7js:noInline')
+_test7(f) => f is void Function(void Function(B7));
diff --git a/tests/corelib_2/bigint_test.dart b/tests/corelib_2/bigint_test.dart
index 46b69e1..01dea1f 100644
--- a/tests/corelib_2/bigint_test.dart
+++ b/tests/corelib_2/bigint_test.dart
@@ -1065,5 +1065,9 @@
     var b = BigInt.parse("10000000000000000001"); /// 27: ok
     Expect.equals(false, a.hashCode == b.hashCode); /// 27: ok
     Expect.equals(true, a.hashCode == (b - BigInt.one).hashCode); /// 27: ok
+
+    // Regression test for http://dartbug.com/36105
+    var overbig = -BigInt.from(10).pow(309);
+    Expect.equals(overbig.toDouble(), double.negativeInfinity);
   }
 }
diff --git a/tests/corelib_2/regexp/lookbehind_test.dart b/tests/corelib_2/regexp/lookbehind_test.dart
new file mode 100644
index 0000000..5ccdcdb
--- /dev/null
+++ b/tests/corelib_2/regexp/lookbehind_test.dart
@@ -0,0 +1,440 @@
+// Copyright (c) 2019, the Dart project authors. All rights reserved.
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import 'package:expect/expect.dart';
+
+import 'v8_regexp_utils.dart';
+
+void main() {
+  // Tests captures in positive and negative look-behind in regular expressions.
+
+  void testRE(RegExp re, String input, bool expectedResult) {
+    if (expectedResult) {
+      assertTrue(re.hasMatch(input));
+    } else {
+      assertFalse(re.hasMatch(input));
+    }
+  }
+
+  void execRE(RegExp re, String input, List<String> expectedResult) {
+    assertTrue(re.hasMatch(input));
+    shouldBe(re.firstMatch(input), expectedResult);
+  }
+
+  void multiRE(RegExp re, String input, List<List<String>> expectedResult) {
+    assertTrue(re.hasMatch(input));
+    final matches = re.allMatches(input);
+    assertEquals(matches.length, expectedResult.length);
+    for (var i = 0; i < matches.length; i++) {
+      shouldBe(matches.elementAt(i), expectedResult[i]);
+    }
+  }
+
+  // Simple fixed-length matches.
+
+  var re = new RegExp(r"^.(?<=a)");
+  execRE(re, "a", ["a"]);
+  testRE(re, "b", false);
+
+  re = new RegExp(r"^f..(?<=.oo)");
+  execRE(re, "foo1", ["foo"]);
+
+  re = new RegExp(r"^f\w\w(?<=\woo)");
+  execRE(re, "foo2", ["foo"]);
+  testRE(re, "boo", false);
+  testRE(re, "fao", false);
+  testRE(re, "foa", false);
+
+  re = new RegExp(r"(?<=abc)\w\w\w");
+  execRE(re, "abcdef", ["def"]);
+
+  re = new RegExp(r"(?<=a.c)\w\w\w");
+  execRE(re, "abcdef", ["def"]);
+
+  re = new RegExp(r"(?<=a\wc)\w\w\w");
+  execRE(re, "abcdef", ["def"]);
+
+  re = new RegExp(r"(?<=a[a-z])\w\w\w");
+  execRE(re, "abcdef", ["cde"]);
+
+  re = new RegExp(r"(?<=a[a-z][a-z])\w\w\w");
+  execRE(re, "abcdef", ["def"]);
+
+  re = new RegExp(r"(?<=a[a-z]{2})\w\w\w");
+  execRE(re, "abcdef", ["def"]);
+
+  re = new RegExp(r"(?<=a{1})\w\w\w");
+  execRE(re, "abcdef", ["bcd"]);
+
+  re = new RegExp(r"(?<=a{1}b{1})\w\w\w");
+  execRE(re, "abcdef", ["cde"]);
+
+  re = new RegExp(r"(?<=a{1}[a-z]{2})\w\w\w");
+  execRE(re, "abcdef", ["def"]);
+
+  // Variable-length matches.
+
+  re = new RegExp(r"(?<=[a|b|c]*)[^a|b|c]{3}");
+  execRE(re, "abcdef", ["def"]);
+
+  re = new RegExp(r"(?<=\w*)[^a|b|c]{3}");
+  execRE(re, "abcdef", ["def"]);
+
+  re = new RegExp(r"(?<=b|c)\w");
+  multiRE(re, "abcdef", [
+    ["c"],
+    ["d"]
+  ]);
+
+  re = new RegExp(r"(?<=[b-e])\w{2}");
+  multiRE(re, "abcdef", [
+    ["cd"],
+    ["ef"]
+  ]);
+
+  // Start of line matches.
+
+  re = new RegExp(r"(?<=^abc)def");
+  execRE(re, "abcdef", ["def"]);
+
+  re = new RegExp(r"(?<=^[a-c]{3})def");
+  execRE(re, "abcdef", ["def"]);
+
+  re = new RegExp(r"(?<=^[a-c]{3})def", multiLine: true);
+  execRE(re, "xyz\nabcdef", ["def"]);
+
+  re = new RegExp(r"(?<=^)\w+", multiLine: true);
+  multiRE(re, "ab\ncd\nefg", [
+    ["ab"],
+    ["cd"],
+    ["efg"]
+  ]);
+
+  re = new RegExp(r"\w+(?<=$)", multiLine: true);
+  multiRE(re, "ab\ncd\nefg", [
+    ["ab"],
+    ["cd"],
+    ["efg"]
+  ]);
+
+  re = new RegExp(r"(?<=^)\w+(?<=$)", multiLine: true);
+  multiRE(re, "ab\ncd\nefg", [
+    ["ab"],
+    ["cd"],
+    ["efg"]
+  ]);
+
+  re = new RegExp(r"(?<=^[^a-c]{3})def");
+  testRE(re, "abcdef", false);
+
+  re = new RegExp(r"^foooo(?<=^o+)$");
+  testRE(re, "foooo", false);
+
+  re = new RegExp(r"^foooo(?<=^o*)$");
+  testRE(re, "foooo", false);
+
+  re = new RegExp(r"^foo(?<=^fo+)$");
+  execRE(re, "foo", ["foo"]);
+
+  re = new RegExp(r"^foooo(?<=^fo*)");
+  execRE(re, "foooo", ["foooo"]);
+
+  re = new RegExp(r"^(f)oo(?<=^\1o+)$");
+  testRE(re, "foo", true);
+  execRE(re, "foo", ["foo", "f"]);
+
+  re = new RegExp(r"^(f)oo(?<=^\1o+)$", caseSensitive: false);
+  execRE(re, "foo", ["foo", "f"]);
+
+  re = new RegExp(r"^(f)oo(?<=^\1o+).$", caseSensitive: false);
+  execRE(re, "foo\u1234", ["foo\u1234", "f"]);
+
+  re = new RegExp(r"(?<=^\w+)def");
+  execRE(re, "abcdefdef", ["def"]);
+  multiRE(re, "abcdefdef", [
+    ["def"],
+    ["def"]
+  ]);
+
+  // Word boundary matches.
+
+  re = new RegExp(r"(?<=\b)[d-f]{3}");
+  execRE(re, "abc def", ["def"]);
+
+  re = new RegExp(r"(?<=\B)\w{3}");
+  execRE(re, "ab cdef", ["def"]);
+
+  re = new RegExp(r"(?<=\B)(?<=c(?<=\w))\w{3}");
+  execRE(re, "ab cdef", ["def"]);
+
+  re = new RegExp(r"(?<=\b)[d-f]{3}");
+  testRE(re, "abcdef", false);
+
+  // Negative lookbehind.
+
+  re = new RegExp(r"(?<!abc)\w\w\w");
+  execRE(re, "abcdef", ["abc"]);
+
+  re = new RegExp(r"(?<!a.c)\w\w\w");
+  execRE(re, "abcdef", ["abc"]);
+
+  re = new RegExp(r"(?<!a\wc)\w\w\w");
+  execRE(re, "abcdef", ["abc"]);
+
+  re = new RegExp(r"(?<!a[a-z])\w\w\w");
+  execRE(re, "abcdef", ["abc"]);
+
+  re = new RegExp(r"(?<!a[a-z]{2})\w\w\w");
+  execRE(re, "abcdef", ["abc"]);
+
+  re = new RegExp(r"(?<!abc)def");
+  testRE(re, "abcdef", false);
+
+  re = new RegExp(r"(?<!a.c)def");
+  testRE(re, "abcdef", false);
+
+  re = new RegExp(r"(?<!a\wc)def");
+  testRE(re, "abcdef", false);
+
+  re = new RegExp(r"(?<!a[a-z][a-z])def");
+  testRE(re, "abcdef", false);
+
+  re = new RegExp(r"(?<!a[a-z]{2})def");
+  testRE(re, "abcdef", false);
+
+  re = new RegExp(r"(?<!a{1}b{1})cde");
+  testRE(re, "abcdef", false);
+
+  re = new RegExp(r"(?<!a{1}[a-z]{2})def");
+  testRE(re, "abcdef", false);
+
+  // Capturing matches.
+  re = new RegExp(r"(?<=(c))def");
+  execRE(re, "abcdef", ["def", "c"]);
+
+  re = new RegExp(r"(?<=(\w{2}))def");
+  execRE(re, "abcdef", ["def", "bc"]);
+
+  re = new RegExp(r"(?<=(\w(\w)))def");
+  execRE(re, "abcdef", ["def", "bc", "c"]);
+
+  re = new RegExp(r"(?<=(\w){3})def");
+  execRE(re, "abcdef", ["def", "a"]);
+
+  re = new RegExp(r"(?<=(bc)|(cd)).");
+  execRE(re, "abcdef", ["d", "bc", null]);
+
+  re = new RegExp(r"(?<=([ab]{1,2})\D|(abc))\w");
+  execRE(re, "abcdef", ["c", "a", null]);
+
+  re = new RegExp(r"\D(?<=([ab]+))(\w)");
+  execRE(re, "abcdef", ["ab", "a", "b"]);
+
+  // Captures inside negative lookbehind. (They never capture.)
+  re = new RegExp(r"(?<!(^|[ab]))\w{2}");
+  execRE(re, "abcdef", ["de", null]);
+
+  // Nested lookaround.
+  re = new RegExp(r"(?<=ab(?=c)\wd)\w\w");
+  execRE(re, "abcdef", ["ef"]);
+
+  re = new RegExp(r"(?<=a(?=([^a]{2})d)\w{3})\w\w");
+  execRE(re, "abcdef", ["ef", "bc"]);
+
+  re = new RegExp(r"(?<=a(?=([bc]{2}(?<!a{2}))d)\w{3})\w\w");
+  execRE(re, "abcdef", ["ef", "bc"]);
+
+  re = new RegExp(r"(?<=a(?=([bc]{2}(?<!a*))d)\w{3})\w\w/");
+  testRE(re, "abcdef", false);
+
+  re = new RegExp(r"^faaao?(?<=^f[oa]+(?=o))");
+  execRE(re, "faaao", ["faaa"]);
+
+  // Back references.
+  re = new RegExp(r"(.)(?<=(\1\1))");
+  execRE(re, "abb", ["b", "b", "bb"]);
+
+  re = new RegExp(r"(.)(?<=(\1\1))", caseSensitive: false);
+  execRE(re, "abB", ["B", "B", "bB"]);
+
+  re = new RegExp(r"((\w)\w)(?<=\1\2\1)", caseSensitive: false);
+  execRE(re, "aabAaBa", ["aB", "aB", "a"]);
+
+  re = new RegExp(r"(\w(\w))(?<=\1\2\1)", caseSensitive: false);
+  execRE(re, "aabAaBa", ["Ba", "Ba", "a"]);
+
+  re = new RegExp(r"(?=(\w))(?<=(\1)).", caseSensitive: false);
+  execRE(re, "abaBbAa", ["b", "b", "B"]);
+
+  re = new RegExp(r"(?<=(.))(\w+)(?=\1)");
+  execRE(re, "  'foo'  ", ["foo", "'", "foo"]);
+  execRE(re, "  \"foo\"  ", ["foo", "\"", "foo"]);
+  testRE(re, "  .foo\"  ", false);
+
+  re = new RegExp(r"(.)(?<=\1\1\1)");
+  testRE(re, "ab", false);
+  testRE(re, "abb", false);
+  execRE(re, "abbb", ["b", "b"]);
+
+  re = new RegExp(r"(..)(?<=\1\1\1)");
+  testRE(re, "ab", false);
+  testRE(re, "abb", false);
+  testRE(re, "aabb", false);
+  testRE(re, "abab", false);
+  testRE(re, "fabxbab", false);
+  testRE(re, "faxabab", false);
+  execRE(re, "fababab", ["ab", "ab"]);
+
+  // Back references to captures inside the lookbehind.
+  re = new RegExp(r"(?<=\1(\w))d", caseSensitive: false);
+  execRE(re, "abcCd", ["d", "C"]);
+
+  re = new RegExp(r"(?<=\1([abx]))d");
+  execRE(re, "abxxd", ["d", "x"]);
+
+  re = new RegExp(r"(?<=\1(\w+))c");
+  execRE(re, "ababc", ["c", "ab"]);
+  execRE(re, "ababbc", ["c", "b"]);
+  testRE(re, "ababdc", false);
+
+  re = new RegExp(r"(?<=(\w+)\1)c");
+  execRE(re, "ababc", ["c", "abab"]);
+
+  // Alternations are tried left to right,
+  // and we do not backtrack into a lookbehind.
+  re = new RegExp(r".*(?<=(..|...|....))(.*)");
+  execRE(re, "xabcd", ["xabcd", "cd", ""]);
+
+  re = new RegExp(r".*(?<=(xx|...|....))(.*)");
+  execRE(re, "xabcd", ["xabcd", "bcd", ""]);
+
+  re = new RegExp(r".*(?<=(xx|...))(.*)");
+  execRE(re, "xxabcd", ["xxabcd", "bcd", ""]);
+
+  re = new RegExp(r".*(?<=(xx|xxx))(.*)");
+  execRE(re, "xxabcd", ["xxabcd", "xx", "abcd"]);
+
+  // We do not backtrack into a lookbehind.
+  // The lookbehind captures "abc" so that \1 does not match. We do not backtrack
+  // to capture only "bc" in the lookbehind.
+  re = new RegExp(r"(?<=([abc]+)).\1");
+  testRE(re, "abcdbc", false);
+
+  // Greedy loop.
+  re = new RegExp(r"(?<=(b+))c");
+  execRE(re, "abbbbbbc", ["c", "bbbbbb"]);
+
+  re = new RegExp(r"(?<=(b\d+))c");
+  execRE(re, "ab1234c", ["c", "b1234"]);
+
+  re = new RegExp(r"(?<=((?:b\d{2})+))c");
+  execRE(re, "ab12b23b34c", ["c", "b12b23b34"]);
+
+  // Sticky
+  re = new RegExp(r"(?<=^(\w+))def");
+  multiRE(re, "abcdefdef", [
+    ["def", "abc"],
+    ["def", "abcdef"]
+  ]);
+
+  re = new RegExp(r"\Bdef");
+  multiRE(re, "abcdefdef", [
+    ["def"],
+    ["def"]
+  ]);
+
+  // Misc
+  re = new RegExp(r"(?<=$abc)def");
+  testRE(re, "abcdef", false);
+
+  re = new RegExp(r"^foo(?<=foo)$");
+  execRE(re, "foo", ["foo"]);
+
+  re = new RegExp(r"^f.o(?<=foo)$");
+  execRE(re, "foo", ["foo"]);
+
+  re = new RegExp(r"^f.o(?<=foo)$");
+  testRE(re, "fno", false);
+
+  re = new RegExp(r"^foo(?<!foo)$");
+  testRE(re, "foo", false);
+
+  re = new RegExp(r"^f.o(?<!foo)$");
+  testRE(re, "foo", false);
+  execRE(re, "fno", ["fno"]);
+
+  re = new RegExp(r"^foooo(?<=fo+)$");
+  execRE(re, "foooo", ["foooo"]);
+
+  re = new RegExp(r"^foooo(?<=fo*)$");
+  execRE(re, "foooo", ["foooo"]);
+
+  re = new RegExp(r"(abc\1)");
+  execRE(re, "abc", ["abc", "abc"]);
+  execRE(re, "abc\u1234", ["abc", "abc"]);
+
+  re = new RegExp(r"(abc\1)", caseSensitive: false);
+  execRE(re, "abc", ["abc", "abc"]);
+  execRE(re, "abc\u1234", ["abc", "abc"]);
+
+  final oob_subject = "abcdefghijklmnabcdefghijklmn".substring(14);
+  re = new RegExp(r"(?=(abcdefghijklmn))(?<=\1)a", caseSensitive: false);
+  testRE(re, oob_subject, false);
+
+  re = new RegExp(r"(?=(abcdefghijklmn))(?<=\1)a");
+  testRE(re, oob_subject, false);
+
+  re = new RegExp(r"(?=(abcdefg))(?<=\1)");
+  testRE(re, "abcdefgabcdefg".substring(1), false);
+
+  // Mutual recursive capture/back references
+  re = new RegExp(r"(?<=a(.\2)b(\1)).{4}");
+  execRE(re, "aabcacbc", ["cacb", "a", ""]);
+
+  re = new RegExp(r"(?<=a(\2)b(..\1))b");
+  execRE(re, "aacbacb", ["b", "ac", "ac"]);
+
+  re = new RegExp(r"(?<=(?:\1b)(aa)).");
+  execRE(re, "aabaax", ["x", "aa"]);
+
+  re = new RegExp(r"(?<=(?:\1|b)(aa)).");
+  execRE(re, "aaaax", ["x", "aa"]);
+
+  // Restricted syntax in Annex B 1.4.
+  // The check for quantifiers on lookbehinds was added later than the
+  // original feature in v8, so we may need to approve failures here
+  // separately from the rest of the file.
+  assertThrows(() => new RegExp(r"(?<=.)*")); //# 01: ok
+  assertThrows(() => new RegExp(r"(?<=.)?")); //# 01: ok
+  assertThrows(() => new RegExp(r"(?<=.)+")); //# 01: ok
+
+  // No unicode flag (yet), so can't test these.
+  // See https://github.com/dart-lang/sdk/issues/36170.
+  // assertThrows("/(?<=.)*/u", SyntaxError);
+  // assertThrows("/(?<=.){1,2}/u", SyntaxError);
+}
diff --git a/tests/corelib_2/string_replace_all_2_test.dart b/tests/corelib_2/string_replace_all_2_test.dart
new file mode 100644
index 0000000..39d196a
--- /dev/null
+++ b/tests/corelib_2/string_replace_all_2_test.dart
@@ -0,0 +1,11 @@
+// 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.
+//
+// dart2jsOptions=-Ddart2js.testing.String.replaceAll.force.regexp=true
+
+import "string_replace_all_test.dart" as base;
+
+main() {
+  base.main();
+}
diff --git a/tests/language_2/cascaded_forwarding_stubs_test.dart b/tests/language_2/cascaded_forwarding_stubs_test.dart
index 1af182b..a10cc2e 100644
--- a/tests/language_2/cascaded_forwarding_stubs_test.dart
+++ b/tests/language_2/cascaded_forwarding_stubs_test.dart
@@ -24,7 +24,9 @@
 }
 
 // E contains a forwarding stub for f which ensures that `y` is type checked.
-class E extends D implements I2 {}
+class E extends D implements I2 {
+  void f(B x, B y);
+}
 
 main() {
   E e = new E();
diff --git a/tests/language_2/control_flow_collections/experimental_flag_test.dart b/tests/language_2/control_flow_collections/experimental_flag_test.dart
index aa3d8a1..a044a01 100644
--- a/tests/language_2/control_flow_collections/experimental_flag_test.dart
+++ b/tests/language_2/control_flow_collections/experimental_flag_test.dart
@@ -4,9 +4,6 @@
 
 // Check that control flow is not enabled without the experimental flag.
 
-// Do enable set literals, just not the new syntax in them.
-// SharedOptions=--enable-experiment=set-literals
-
 // TODO(rnystrom): Remove this test when the feature is enabled without a flag.
 
 void main() {
diff --git a/tests/language_2/control_flow_collections/for_const_test.dart b/tests/language_2/control_flow_collections/for_const_test.dart
index 022ec24..3ba2d91 100644
--- a/tests/language_2/control_flow_collections/for_const_test.dart
+++ b/tests/language_2/control_flow_collections/for_const_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,control-flow-collections
+// SharedOptions=--enable-experiment=control-flow-collections
 
 void main() {
   // For cannot be used in a const collection.
diff --git a/tests/language_2/control_flow_collections/for_inference_test.dart b/tests/language_2/control_flow_collections/for_inference_test.dart
index 3d9773b..9c462262 100644
--- a/tests/language_2/control_flow_collections/for_inference_test.dart
+++ b/tests/language_2/control_flow_collections/for_inference_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,control-flow-collections,spread-collections
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
 
 // Test how control flow interacts with inference.
 import 'package:expect/expect.dart';
diff --git a/tests/language_2/control_flow_collections/for_test.dart b/tests/language_2/control_flow_collections/for_test.dart
index 6add35f..f9aee00 100644
--- a/tests/language_2/control_flow_collections/for_test.dart
+++ b/tests/language_2/control_flow_collections/for_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,control-flow-collections,spread-collections
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
 
 import 'package:expect/expect.dart';
 
@@ -118,7 +118,7 @@
 
   // Else inside for.
   Expect.mapEquals(map,
-      <int, int>{for (var i in <int>[1, -2, 3, -4]) if (i < 0) -i else i: i});
+      <int, int>{for (var i in <int>[1, -2, 3, -4]) if (i < 0) -i: -i else i: i});
 
   // For inside for.
   Expect.mapEquals(map, <int, int>{
@@ -230,9 +230,9 @@
 void testRuntimeErrors() {
   // Non-bool condition expression.
   dynamic nonBool = 3;
-  Expect.throwsCastError(() => <int>[for (; nonBool;) 1]);
-  Expect.throwsCastError(() => <int, int>{for (; nonBool;) 1: 1});
-  Expect.throwsCastError(() => <int>{for (; nonBool;) 1});
+  Expect.throwsTypeError(() => <int>[for (; nonBool;) 1]);
+  Expect.throwsTypeError(() => <int, int>{for (; nonBool;) 1: 1});
+  Expect.throwsTypeError(() => <int>{for (; nonBool;) 1});
 
   // Null condition expression.
   bool nullBool = null;
@@ -242,15 +242,15 @@
 
   // Cast for variable.
   dynamic nonInt = "string";
-  Expect.throwsCastError(() => <int>[for (int i = nonInt; false;) 1]);
-  Expect.throwsCastError(() => <int, int>{for (int i = nonInt; false;) 1: 1});
-  Expect.throwsCastError(() => <int>{for (int i = nonInt; false;) 1});
+  Expect.throwsTypeError(() => <int>[for (int i = nonInt; false;) 1]);
+  Expect.throwsTypeError(() => <int, int>{for (int i = nonInt; false;) 1: 1});
+  Expect.throwsTypeError(() => <int>{for (int i = nonInt; false;) 1});
 
   // Cast for-in variable.
   dynamic nonIterable = 3;
-  Expect.throwsCastError(() => <int>[for (int i in nonIterable) 1]);
-  Expect.throwsCastError(() => <int, int>{for (int i in nonIterable) 1: 1});
-  Expect.throwsCastError(() => <int>{for (int i in nonIterable) 1});
+  Expect.throwsTypeError(() => <int>[for (int i in nonIterable) 1]);
+  Expect.throwsTypeError(() => <int, int>{for (int i in nonIterable) 1: 1});
+  Expect.throwsTypeError(() => <int>{for (int i in nonIterable) 1});
 
   // Null iterable.
   Iterable<int> nullIterable = null;
@@ -260,10 +260,10 @@
   Expect.throwsNoSuchMethodError(() => <int>{for (var i in nullIterable) 1});
 
   // Wrong element type.
-  Expect.throwsCastError(() => <int>[for (var i = 0; i < 1; i++) nonInt]);
-  Expect.throwsCastError(
+  Expect.throwsTypeError(() => <int>[for (var i = 0; i < 1; i++) nonInt]);
+  Expect.throwsTypeError(
       () => <int, int>{for (var i = 0; i < 1; i++) nonInt: 1});
-  Expect.throwsCastError(
+  Expect.throwsTypeError(
       () => <int, int>{for (var i = 0; i < 1; i++) 1: nonInt});
-  Expect.throwsCastError(() => <int>{for (var i = 0; i < 1; i++) nonInt});
+  Expect.throwsTypeError(() => <int>{for (var i = 0; i < 1; i++) nonInt});
 }
diff --git a/tests/language_2/control_flow_collections/for_variable_test.dart b/tests/language_2/control_flow_collections/for_variable_test.dart
index b7b4307..f866daf 100644
--- a/tests/language_2/control_flow_collections/for_variable_test.dart
+++ b/tests/language_2/control_flow_collections/for_variable_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,control-flow-collections,spread-collections
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
 
 /// Tests for how variables and scoping work with for elements.
 import 'package:expect/expect.dart';
diff --git a/tests/language_2/control_flow_collections/if_const_error_test.dart b/tests/language_2/control_flow_collections/if_const_error_test.dart
index 4e100a6..8f6acf9 100644
--- a/tests/language_2/control_flow_collections/if_const_error_test.dart
+++ b/tests/language_2/control_flow_collections/if_const_error_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,control-flow-collections
+// SharedOptions=--enable-experiment=control-flow-collections
 
 import 'dart:collection';
 
diff --git a/tests/language_2/control_flow_collections/if_const_test.dart b/tests/language_2/control_flow_collections/if_const_test.dart
index e30939cb..258a889 100644
--- a/tests/language_2/control_flow_collections/if_const_test.dart
+++ b/tests/language_2/control_flow_collections/if_const_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,control-flow-collections,spread-collections
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
 
 import 'package:expect/expect.dart';
 
@@ -70,12 +70,6 @@
 
   // Nested if in else.
   Expect.identical(const [1], const <int>[if (false) 9 else if (true) 1]);
-
-  // Nested for in then.
-  Expect.identical(list, const <int>[if (true) for (var i in list) i]);
-
-  // Nested for in else.
-  Expect.identical(list, const <int>[if (false) 9 else for (var i in list) i]);
 }
 
 void testMap() {
@@ -122,13 +116,6 @@
   // Nested if in else.
   Expect.identical(const {1: 1},
       const <int, int>{if (false) 9: 9 else if (true) 1: 1});
-
-  // Nested for in then.
-  Expect.identical(map, const <int, int>{if (true) for (var i in list) i: i});
-
-  // Nested for in else.
-  Expect.identical(map,
-      const <int, int>{if (false) 9: 9 else for (var i in list) i: i});
 }
 
 void testSet() {
@@ -142,7 +129,7 @@
   Expect.identical(set, const <int>{1, if (false) 9 else 2, 3});
 
   // Only if.
-  Expect.identical({1}, const <int>{if (true) 1});
+  Expect.identical(const <int>{1}, const <int>{if (true) 1});
 
   // If at beginning.
   Expect.identical(set, const <int>{if (true) 1, 2, 3});
@@ -177,12 +164,6 @@
 
   // Nested if in else.
   Expect.identical(const <int>{1}, const <int>{if (false) 9 else if (true) 1});
-
-  // Nested for in then.
-  Expect.identical(set, const <int>{if (true) for (var i in list) i});
-
-  // Nested for in else.
-  Expect.identical(set, const <int>{if (false) 9 else for (var i in list) i});
 }
 
 void testShortCircuit() {
@@ -220,7 +201,7 @@
   Expect.identical(const <int>[1, 2],
       const <int>[if (true) 1 else nonInt, if (false) nonInt else 2]);
 
-  Expect.identical(const <int>{1: 1}, const <int, int>{
+  Expect.identical(const <int, int>{1: 1}, const <int, int>{
     if (true) 1: 1,
     if (false) nonInt: 9,
     if (false) 9: nonInt
diff --git a/tests/language_2/control_flow_collections/if_inference_test.dart b/tests/language_2/control_flow_collections/if_inference_test.dart
index adc6e65..0c73618 100644
--- a/tests/language_2/control_flow_collections/if_inference_test.dart
+++ b/tests/language_2/control_flow_collections/if_inference_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,control-flow-collections,spread-collections
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
 
 // Test how control flow interacts with inference.
 import 'package:expect/expect.dart';
diff --git a/tests/language_2/control_flow_collections/if_test.dart b/tests/language_2/control_flow_collections/if_test.dart
index d420e16..4ffd515 100644
--- a/tests/language_2/control_flow_collections/if_test.dart
+++ b/tests/language_2/control_flow_collections/if_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,control-flow-collections,spread-collections
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
 
 import 'package:expect/expect.dart';
 
@@ -232,9 +232,9 @@
 
 void testRuntimeFailures() {
   dynamic nonBool = 3;
-  Expect.throwsCastError(() => <int>[if (nonBool) 1]);
-  Expect.throwsCastError(() => <int, int>{if (nonBool) 1: 1});
-  Expect.throwsCastError(() => <int>{if (nonBool) 1});
+  Expect.throwsTypeError(() => <int>[if (nonBool) 1]);
+  Expect.throwsTypeError(() => <int, int>{if (nonBool) 1: 1});
+  Expect.throwsTypeError(() => <int>{if (nonBool) 1});
 
   bool nullBool = null;
   Expect.throwsAssertionError(() => <int>[if (nullBool) 1]);
diff --git a/tests/language_2/control_flow_collections/map_set_ambiguity_error_test.dart b/tests/language_2/control_flow_collections/map_set_ambiguity_error_test.dart
index 5296956..452ac9b 100644
--- a/tests/language_2/control_flow_collections/map_set_ambiguity_error_test.dart
+++ b/tests/language_2/control_flow_collections/map_set_ambiguity_error_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,control-flow-collections,spread-collections
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
 
 // Test cases where the syntax is ambiguous between maps and sets when control
 // flow elements contain spreads.
diff --git a/tests/language_2/control_flow_collections/map_set_ambiguity_test.dart b/tests/language_2/control_flow_collections/map_set_ambiguity_test.dart
index abd6f58..271bb09 100644
--- a/tests/language_2/control_flow_collections/map_set_ambiguity_test.dart
+++ b/tests/language_2/control_flow_collections/map_set_ambiguity_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,control-flow-collections,spread-collections
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
 
 // Test cases where the syntax is ambiguous between maps and sets because of
 // spreads inside control flow.
diff --git a/tests/language_2/control_flow_collections/syntax_test.dart b/tests/language_2/control_flow_collections/syntax_test.dart
index c6de2d8..0810aec 100644
--- a/tests/language_2/control_flow_collections/syntax_test.dart
+++ b/tests/language_2/control_flow_collections/syntax_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,control-flow-collections
+// SharedOptions=--enable-experiment=control-flow-collections
 
 // Tests syntax edge cases.
 import 'package:expect/expect.dart';
diff --git a/tests/language_2/control_flow_collections/type_error_test.dart b/tests/language_2/control_flow_collections/type_error_test.dart
index ace6588..2656b7f 100644
--- a/tests/language_2/control_flow_collections/type_error_test.dart
+++ b/tests/language_2/control_flow_collections/type_error_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,control-flow-collections
+// SharedOptions=--enable-experiment=control-flow-collections
 
 void main() {
   Object obj = true;
diff --git a/tests/language_2/generic_methods_generic_function_result_test.dart b/tests/language_2/generic_methods_generic_function_result_test.dart
index cc583fe9..3a391ec 100644
--- a/tests/language_2/generic_methods_generic_function_result_test.dart
+++ b/tests/language_2/generic_methods_generic_function_result_test.dart
@@ -2,8 +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.
 
-// VMOptions=--error-on-bad-type
-
 // Verify that function type parameter S can be resolved in bar's result type.
 // Verify that generic function types are not allowed as type arguments.
 
diff --git a/tests/language_2/hello_dart_test.dart b/tests/language_2/hello_dart_test.dart
index 0af0005..d53705b 100644
--- a/tests/language_2/hello_dart_test.dart
+++ b/tests/language_2/hello_dart_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 // Simple test program invoked with an option to eagerly
 // compile all code that is loaded in the isolate.
-// VMOptions=--compile_all --error-on-bad-type
+// VMOptions=--compile_all
 
 class HelloDartTest {
   static testMain() {
diff --git a/tests/language_2/issue21957_test.dart b/tests/language_2/issue21957_double_test.dart
similarity index 100%
rename from tests/language_2/issue21957_test.dart
rename to tests/language_2/issue21957_double_test.dart
diff --git a/tests/language_2/issue21957_float32x4_test.dart b/tests/language_2/issue21957_float32x4_test.dart
new file mode 100644
index 0000000..f364261
--- /dev/null
+++ b/tests/language_2/issue21957_float32x4_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, 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.
+
+// Check slow path for PotentialUnboxedStore.
+// VMOptions=--optimization_counter_threshold=-1
+
+import "dart:typed_data";
+
+main() {
+  for (int i = 0; i < 1000000; i++) {
+    new A();
+  }
+}
+
+class A {
+  var a = new Float32x4(1.0, 2.0, 3.0, 4.0);
+}
diff --git a/tests/language_2/issue21957_float64x2_test.dart b/tests/language_2/issue21957_float64x2_test.dart
new file mode 100644
index 0000000..5b51722
--- /dev/null
+++ b/tests/language_2/issue21957_float64x2_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, 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.
+
+// Check slow path for PotentialUnboxedStore.
+// VMOptions=--optimization_counter_threshold=-1
+
+import "dart:typed_data";
+
+main() {
+  for (int i = 0; i < 1000000; i++) {
+    new A();
+  }
+}
+
+class A {
+  var a = new Float64x2(1.0, 2.0);
+}
diff --git a/tests/language_2/language_2.status b/tests/language_2/language_2.status
index 88da305..23788e5 100644
--- a/tests/language_2/language_2.status
+++ b/tests/language_2/language_2.status
@@ -53,6 +53,12 @@
 stacktrace_demangle_ctors_test: SkipByDesign # Names are not scrubbed.
 type_checks_in_factory_method_test: SkipByDesign # Requires checked mode.
 
+[ $runtime == vm ]
+spread_collections/const_error_test/05: Crash
+spread_collections/const_error_test/06: Crash
+spread_collections/const_error_test/07: Crash
+spread_collections/const_error_test/08: Crash
+
 [ $fasta ]
 partial_instantiation_static_bounds_check_test/01: MissingCompileTimeError # Issue 34327
 partial_instantiation_static_bounds_check_test/02: MissingCompileTimeError # Issue 34327
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 9bfaf74..804ad39 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -22,6 +22,7 @@
 config_import_test: RuntimeError # Test flag is not passed to the compiler.
 const_constructor_nonconst_param_test/01: MissingCompileTimeError
 const_dynamic_type_literal_test/03: Pass # but it shouldn't until we fix issue 17207
+control_flow_collections/*: Skip
 deopt_inlined_function_lazy_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 deopt_smi_op_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 double_identical_test: RuntimeError # Negative and positive zero are distinct, but not in dart2js; bug #11551.
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index b678948..b3372d6 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -184,6 +184,7 @@
 const_optional_args_test/01: MissingCompileTimeError
 const_syntax_test/05: MissingCompileTimeError
 constants_test/05: MissingCompileTimeError
+control_flow_collections/*: Skip
 covariant_subtyping_test: RuntimeError
 deferred_load_library_wrong_args_test/01: CompileTimeError
 double_identical_test: RuntimeError # Negative and positive zero are distinct, but not in ddk
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index bff609c..d20e287 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -37,18 +37,7 @@
 const_nested_test: RuntimeError
 const_string_test: RuntimeError
 constructor12_test: RuntimeError
-control_flow_collections/for_await_test: CompileTimeError
-control_flow_collections/for_inference_test: DartkCrash
-control_flow_collections/for_test: DartkCrash
-control_flow_collections/for_variable_test: DartkCrash
-control_flow_collections/if_await_test: CompileTimeError
-control_flow_collections/if_const_test: DartkCrash
-control_flow_collections/if_inference_test: CompileTimeError
-control_flow_collections/if_test: DartkCrash
-control_flow_collections/map_set_ambiguity_test: CompileTimeError
-control_flow_collections/syntax_error_test/09: DartkCrash
-control_flow_collections/syntax_error_test/10: DartkCrash
-control_flow_collections/syntax_test: CompileTimeError
+control_flow_collections/*: Skip
 covariant_subtyping_test: RuntimeError
 ct_const_test: RuntimeError
 cyclic_type2_test: CompileTimeError
@@ -166,17 +155,11 @@
 mixin_method_override_test/G5: Skip # Issue 34354
 private_method_tearoff_test: RuntimeError
 
+[ $compiler == dartk ]
+control_flow_collections/*: Skip
+
 [ $compiler == dartkp ]
-control_flow_collections/for_await_test: CompileTimeError
-control_flow_collections/for_inference_test: CompileTimeError
-control_flow_collections/for_test: CompileTimeError
-control_flow_collections/for_variable_test: CompileTimeError
-control_flow_collections/if_await_test: CompileTimeError
-control_flow_collections/if_const_test: CompileTimeError
-control_flow_collections/if_inference_test: CompileTimeError
-control_flow_collections/if_test: CompileTimeError
-control_flow_collections/map_set_ambiguity_test: CompileTimeError
-control_flow_collections/syntax_test: CompileTimeError
+control_flow_collections/*: Skip
 covariant_subtyping_test: RuntimeError
 generic_no_such_method_dispatcher_test: RuntimeError # Issue 31424
 spread_collections/await_test: CompileTimeError
@@ -221,14 +204,43 @@
 control_flow_collections/for_inference_test: CompileTimeError
 control_flow_collections/for_test: CompileTimeError
 control_flow_collections/for_variable_test: CompileTimeError
-control_flow_collections/if_await_test: CompileTimeError
+control_flow_collections/if_const_error_test/02: MissingCompileTimeError
+control_flow_collections/if_const_error_test/07: MissingCompileTimeError
+control_flow_collections/if_const_error_test/08: MissingCompileTimeError
+control_flow_collections/if_const_error_test/10: MissingCompileTimeError
+control_flow_collections/if_const_error_test/19: MissingCompileTimeError
+control_flow_collections/if_const_error_test/20: MissingCompileTimeError
+control_flow_collections/if_const_error_test/21: MissingCompileTimeError
+control_flow_collections/if_const_error_test/22: MissingCompileTimeError
+control_flow_collections/if_const_error_test/26: MissingCompileTimeError
+control_flow_collections/if_const_error_test/28: MissingCompileTimeError
+control_flow_collections/if_const_error_test/33: MissingCompileTimeError
+control_flow_collections/if_const_error_test/34: MissingCompileTimeError
+control_flow_collections/if_const_error_test/38: MissingCompileTimeError
+control_flow_collections/if_const_error_test/39: MissingCompileTimeError
 control_flow_collections/if_const_test: CompileTimeError
 control_flow_collections/if_inference_test: CompileTimeError
+control_flow_collections/if_promotion_test/04: MissingCompileTimeError
+control_flow_collections/if_promotion_test/05: MissingCompileTimeError
+control_flow_collections/if_promotion_test/06: MissingCompileTimeError
+control_flow_collections/if_promotion_test/07: MissingCompileTimeError
+control_flow_collections/if_promotion_test/08: MissingCompileTimeError
 control_flow_collections/if_test: CompileTimeError
 control_flow_collections/map_set_ambiguity_test: CompileTimeError
 control_flow_collections/syntax_error_test/09: Crash
 control_flow_collections/syntax_error_test/10: Crash
 control_flow_collections/syntax_test: CompileTimeError
+control_flow_collections/type_error_test/00: MissingCompileTimeError
+control_flow_collections/type_error_test/01: MissingCompileTimeError
+control_flow_collections/type_error_test/02: MissingCompileTimeError
+control_flow_collections/type_error_test/06: MissingCompileTimeError
+control_flow_collections/type_error_test/07: MissingCompileTimeError
+control_flow_collections/type_error_test/08: MissingCompileTimeError
+control_flow_collections/type_error_test/09: MissingCompileTimeError
+control_flow_collections/type_error_test/10: MissingCompileTimeError
+control_flow_collections/type_error_test/11: MissingCompileTimeError
+control_flow_collections/type_error_test/12: MissingCompileTimeError
+control_flow_collections/type_error_test/13: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e1: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e10: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e11: MissingCompileTimeError
@@ -260,26 +272,10 @@
 spread_collections/const_error_test/10: MissingCompileTimeError
 spread_collections/const_error_test/11: MissingCompileTimeError
 spread_collections/const_error_test/12: MissingCompileTimeError
-spread_collections/const_error_test/13: MissingCompileTimeError
+spread_collections/const_error_test/13: Crash
 spread_collections/const_error_test/14: MissingCompileTimeError
 spread_collections/const_error_test/15: MissingCompileTimeError
 spread_collections/const_error_test/16: MissingCompileTimeError
-spread_collections/const_test: CompileTimeError
-spread_collections/map_set_ambiguity_error_test/00: MissingCompileTimeError
-spread_collections/map_set_ambiguity_error_test/01: MissingCompileTimeError
-spread_collections/map_set_ambiguity_error_test/02: MissingCompileTimeError
-spread_collections/map_set_ambiguity_error_test/03: MissingCompileTimeError
-spread_collections/map_set_ambiguity_error_test/04: MissingCompileTimeError
-spread_collections/map_set_ambiguity_error_test/05: MissingCompileTimeError
-spread_collections/map_set_ambiguity_error_test/06: MissingCompileTimeError
-spread_collections/map_set_ambiguity_error_test/07: MissingCompileTimeError
-spread_collections/map_set_ambiguity_test: CompileTimeError
-spread_collections/spread_test: CompileTimeError
-spread_collections/syntax_test: CompileTimeError
-spread_collections/type_error_test/01: MissingCompileTimeError
-spread_collections/type_error_test/04: MissingCompileTimeError
-spread_collections/type_error_test/07: MissingCompileTimeError
-spread_collections/type_error_test/08: MissingCompileTimeError
 vm/regress_33469_test/01: MissingCompileTimeError
 vm/regress_33469_test/02: MissingCompileTimeError
 vm/regress_33469_test/03: MissingCompileTimeError
@@ -293,9 +289,6 @@
 async_return_types_test/nestedFuture: MissingCompileTimeError # Issue 33068
 const_cast2_test/01: CompileTimeError # Issue 32517
 const_cast2_test/none: CompileTimeError # Issue 32517
-control_flow_collections/for_await_test: CompileTimeError
-control_flow_collections/if_await_test: CompileTimeError
-control_flow_collections/if_promotion_test/none: CompileTimeError
 deferred_inheritance_constraints_test/extends: MissingCompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
 deferred_inheritance_constraints_test/implements: MissingCompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
 deferred_inheritance_constraints_test/mixin: MissingCompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
@@ -340,18 +333,6 @@
 vm/regress_27201_test: CompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
 
 [ $arch != simarm && $arch != simarm64 && $arch != simdbc64 && $compiler == dartk ]
-control_flow_collections/for_await_test: CompileTimeError
-control_flow_collections/for_inference_test: DartkCrash
-control_flow_collections/for_test: DartkCrash
-control_flow_collections/for_variable_test: DartkCrash
-control_flow_collections/if_await_test: CompileTimeError
-control_flow_collections/if_const_test: DartkCrash
-control_flow_collections/if_inference_test: CompileTimeError
-control_flow_collections/if_test: DartkCrash
-control_flow_collections/map_set_ambiguity_test: CompileTimeError
-control_flow_collections/syntax_error_test/09: DartkCrash
-control_flow_collections/syntax_error_test/10: DartkCrash
-control_flow_collections/syntax_test: CompileTimeError
 spread_collections/await_test: CompileTimeError
 spread_collections/const_test: CompileTimeError
 spread_collections/inference_test: CompileTimeError
@@ -360,16 +341,6 @@
 spread_collections/syntax_test: CompileTimeError
 
 [ $arch == simdbc64 && $compiler == dartk ]
-control_flow_collections/for_await_test: CompileTimeError
-control_flow_collections/for_inference_test: CompileTimeError
-control_flow_collections/for_test: CompileTimeError
-control_flow_collections/for_variable_test: CompileTimeError
-control_flow_collections/if_await_test: CompileTimeError
-control_flow_collections/if_const_test: CompileTimeError
-control_flow_collections/if_inference_test: CompileTimeError
-control_flow_collections/if_test: CompileTimeError
-control_flow_collections/map_set_ambiguity_test: CompileTimeError
-control_flow_collections/syntax_test: CompileTimeError
 spread_collections/await_test: CompileTimeError
 spread_collections/const_test: CompileTimeError
 spread_collections/inference_test: CompileTimeError
@@ -470,18 +441,6 @@
 assertion_initializer_const_error2_test/cc10: MissingCompileTimeError # Not reporting failed assert() at compile time.
 
 [ $compiler == dartk && ($arch == simarm || $arch == simarm64) ]
-control_flow_collections/for_await_test: CompileTimeError
-control_flow_collections/for_inference_test: CompileTimeError
-control_flow_collections/for_test: CompileTimeError
-control_flow_collections/for_variable_test: CompileTimeError
-control_flow_collections/if_await_test: CompileTimeError
-control_flow_collections/if_const_test: CompileTimeError
-control_flow_collections/if_inference_test: CompileTimeError
-control_flow_collections/if_test: CompileTimeError
-control_flow_collections/map_set_ambiguity_test: CompileTimeError
-control_flow_collections/syntax_error_test/09: Pass
-control_flow_collections/syntax_error_test/10: Pass
-control_flow_collections/syntax_test: CompileTimeError
 spread_collections/await_test: CompileTimeError
 spread_collections/const_test: CompileTimeError
 spread_collections/inference_test: CompileTimeError
@@ -495,16 +454,7 @@
 compile_time_constant_o_test/01: Pass
 compile_time_constant_o_test/02: Pass
 const_dynamic_type_literal_test/02: Pass
-control_flow_collections/for_await_test: CompileTimeError
-control_flow_collections/for_inference_test: CompileTimeError
-control_flow_collections/for_test: CompileTimeError
-control_flow_collections/for_variable_test: CompileTimeError
-control_flow_collections/if_await_test: CompileTimeError
-control_flow_collections/if_const_test: CompileTimeError
-control_flow_collections/if_inference_test: CompileTimeError
-control_flow_collections/if_test: CompileTimeError
-control_flow_collections/map_set_ambiguity_test: CompileTimeError
-control_flow_collections/syntax_test: CompileTimeError
+control_flow_collections/*: Skip
 map_literal3_test/01: Pass
 map_literal3_test/02: Pass
 spread_collections/await_test: CompileTimeError
diff --git a/tests/language_2/regress_25389_test.dart b/tests/language_2/regress_25389_test.dart
index f15bb0c..ad76eda 100644
--- a/tests/language_2/regress_25389_test.dart
+++ b/tests/language_2/regress_25389_test.dart
@@ -1,7 +1,6 @@
 // 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.
-// VMOptions=--error-on-bad-type
 
 library regress_25389;
 
diff --git a/tests/language_2/regress_25609_test.dart b/tests/language_2/regress_25609_test.dart
index 67b783c..2cd030a 100644
--- a/tests/language_2/regress_25609_test.dart
+++ b/tests/language_2/regress_25609_test.dart
@@ -2,8 +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.
 
-// VMOptions=--error-on-bad-type
-
 import 'regress_25609_lib1.dart';
 
 Foo baz() => null;
diff --git a/tests/language_2/set_literals/const_set_literal_test.dart b/tests/language_2/set_literals/const_set_literal_test.dart
index 0e59037..7b3cce2 100644
--- a/tests/language_2/set_literals/const_set_literal_test.dart
+++ b/tests/language_2/set_literals/const_set_literal_test.dart
@@ -2,8 +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.
 
-// SharedOptions=--enable-experiment=set-literals
-
 import 'dart:async';
 
 import "package:expect/expect.dart";
diff --git a/tests/language_2/set_literals/invalid_set_literal_test.dart b/tests/language_2/set_literals/invalid_set_literal_test.dart
index 2b6a790..912e65e 100644
--- a/tests/language_2/set_literals/invalid_set_literal_test.dart
+++ b/tests/language_2/set_literals/invalid_set_literal_test.dart
@@ -2,8 +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.
 
-// SharedOptions=--enable-experiment=set-literals
-
 import "dart:collection" show HashSet, LinkedHashSet;
 
 import "package:expect/expect.dart";
diff --git a/tests/language_2/set_literals/set_literal_test.dart b/tests/language_2/set_literals/set_literal_test.dart
index cc17fae..3cb57c0 100644
--- a/tests/language_2/set_literals/set_literal_test.dart
+++ b/tests/language_2/set_literals/set_literal_test.dart
@@ -2,8 +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.
 
-// SharedOptions=--enable-experiment=set-literals
-
 import 'dart:async';
 import "dart:collection" show LinkedHashSet;
 
diff --git a/tests/language_2/spread_collections/const_test.dart b/tests/language_2/spread_collections/const_test.dart
index 994e904..b36dff9 100644
--- a/tests/language_2/spread_collections/const_test.dart
+++ b/tests/language_2/spread_collections/const_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,spread-collections
+// SharedOptions=--enable-experiment=spread-collections
 
 import 'package:expect/expect.dart';
 
diff --git a/tests/language_2/spread_collections/experimental_flag_test.dart b/tests/language_2/spread_collections/experimental_flag_test.dart
index a1c8bf7..84135f1 100644
--- a/tests/language_2/spread_collections/experimental_flag_test.dart
+++ b/tests/language_2/spread_collections/experimental_flag_test.dart
@@ -4,9 +4,6 @@
 
 // Check that spread collections are not enabled without the experimental flag.
 
-// Do enable sets, just not spread inside them.
-// SharedOptions=--enable-experiment=set-literals
-
 // TODO(rnystrom): Remove this test when the feature is enabled without a flag.
 
 void main() {
diff --git a/tests/language_2/spread_collections/inference_test.dart b/tests/language_2/spread_collections/inference_test.dart
index 0b3d4e5..42e5686 100644
--- a/tests/language_2/spread_collections/inference_test.dart
+++ b/tests/language_2/spread_collections/inference_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,spread-collections
+// SharedOptions=--enable-experiment=spread-collections
 
 // Test how spread interacts with inference.
 import 'package:expect/expect.dart';
@@ -113,5 +113,5 @@
   Expect.setEquals(<int>{}, <int>{...expectIntSet()});
 
   // Bottom up-inference from elements is not pushed back down into spread.
-  Expect.setEquals(<int>{}, {1, ...expectDynamicSet()});
+  Expect.setEquals(<int>{1}, {1, ...expectDynamicSet()});
 }
diff --git a/tests/language_2/spread_collections/map_set_ambiguity_error_test.dart b/tests/language_2/spread_collections/map_set_ambiguity_error_test.dart
index ab9b822..5f6576d 100644
--- a/tests/language_2/spread_collections/map_set_ambiguity_error_test.dart
+++ b/tests/language_2/spread_collections/map_set_ambiguity_error_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,spread-collections
+// SharedOptions=--enable-experiment=spread-collections
 
 // Test cases where the syntax is ambiguous between maps and sets.
 import 'dart:collection';
diff --git a/tests/language_2/spread_collections/map_set_ambiguity_test.dart b/tests/language_2/spread_collections/map_set_ambiguity_test.dart
index 48ce5a7..9b3d537 100644
--- a/tests/language_2/spread_collections/map_set_ambiguity_test.dart
+++ b/tests/language_2/spread_collections/map_set_ambiguity_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,spread-collections
+// SharedOptions=--enable-experiment=spread-collections
 
 // Test cases where the syntax is ambiguous between maps and sets.
 import 'dart:collection';
@@ -19,7 +19,8 @@
 void testBottomUpInference() {
   Map<int, int> map = {};
   Set<int> set = Set();
-  dynamic dyn = map;
+  dynamic dynMap = map;
+  dynamic dynSet = set;
   Iterable<int> iterable = [];
   CustomSet customSet = CustomSet();
   CustomMap customMap = CustomMap();
@@ -31,25 +32,25 @@
   // Expect.type<...>({...dyn});
   Expect.type<Set<int>>({...iterable});
   Expect.type<Set<int>>({...customSet});
-  Expect.type<Map<int, int>>({...customMap});
+  Expect.type<Map<int, String>>({...customMap});
 
   Expect.type<Map<int, int>>({...map, ...map});
   // Expect.type<...>({...map, ...set});
-  Expect.type<Map<dynamic, dynamic>>({...map, ...dyn});
+  Expect.type<Map<dynamic, dynamic>>({...map, ...dynMap});
   // Expect.type<...>({...map, ...iterable});
   // Expect.type<...>({...map, ...customSet});
-  Expect.type<Map<int, int>>({...map, ...customMap});
+  Expect.type<Map<int, Object>>({...map, ...customMap});
 
   Expect.type<Set<int>>({...set, ...set});
-  Expect.type<Set<dynamic>>({...set, ...dyn});
+  Expect.type<Set<dynamic>>({...set, ...dynSet});
   Expect.type<Set<int>>({...set, ...iterable});
   Expect.type<Set<int>>({...set, ...customSet});
   // Expect.type<...>({...set, ...customMap});
 
   // Expect.type<...>({...dyn, ...dyn});
-  Expect.type<Set<dynamic>>({...dyn, ...iterable});
-  Expect.type<Set<dynamic>>({...dyn, ...customSet});
-  Expect.type<Map<dynamic, dynamic>>({...dyn, ...customMap});
+  Expect.type<Set<dynamic>>({...dynSet, ...iterable});
+  Expect.type<Set<dynamic>>({...dynSet, ...customSet});
+  Expect.type<Map<dynamic, dynamic>>({...dynMap, ...customMap});
 
   Expect.type<Set<int>>({...iterable, ...iterable});
   Expect.type<Set<int>>({...iterable, ...customSet});
@@ -58,7 +59,7 @@
   Expect.type<Set<int>>({...customSet, ...customSet});
   // Expect.type<...>({...customSet, ...customMap});
 
-  Expect.type<Map<int, int>>({...customMap, ...customMap});
+  Expect.type<Map<int, String>>({...customMap, ...customMap});
 }
 
 void testTopDownInference() {
diff --git a/tests/language_2/spread_collections/spread_test.dart b/tests/language_2/spread_collections/spread_test.dart
index 8b23a48..bd88880 100644
--- a/tests/language_2/spread_collections/spread_test.dart
+++ b/tests/language_2/spread_collections/spread_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,spread-collections
+// SharedOptions=--enable-experiment=spread-collections
 
 import 'package:expect/expect.dart';
 
@@ -200,24 +200,24 @@
 
 void testCastFailures() {
   dynamic nonIterable = 3;
-  Expect.throwsCastError(() => <int>[...nonIterable]);
-  Expect.throwsCastError(() => <int>{...nonIterable});
+  Expect.throwsTypeError(() => <int>[...nonIterable]);
+  Expect.throwsTypeError(() => <int>{...nonIterable});
 
   dynamic nonMap = 3;
-  Expect.throwsCastError(() => <int, int>{...nonMap});
+  Expect.throwsTypeError(() => <int, int>{...nonMap});
 
   dynamic wrongIterableType = <String>["s"];
-  Expect.throwsCastError(() => <int>[...wrongIterableType]);
-  Expect.throwsCastError(() => <int>{...wrongIterableType});
+  Expect.throwsTypeError(() => <int>[...wrongIterableType]);
+  Expect.throwsTypeError(() => <int>{...wrongIterableType});
 
   dynamic wrongKeyType = <String, int>{"s": 1};
   dynamic wrongValueType = <int, String>{1: "s"};
-  Expect.throwsCastError(() => <int, int>{...wrongKeyType});
-  Expect.throwsCastError(() => <int, int>{...wrongValueType});
+  Expect.throwsTypeError(() => <int, int>{...wrongKeyType});
+  Expect.throwsTypeError(() => <int, int>{...wrongValueType});
 
   // Mismatched collection types.
-  Expect.throwsCastError(() => <int>[...map]);
-  Expect.throwsCastError(() => <int, int>{...list});
-  Expect.throwsCastError(() => <int, int>{...set});
-  Expect.throwsCastError(() => <int>{...map});
+  Expect.throwsTypeError(() => <int>[...map]);
+  Expect.throwsTypeError(() => <int, int>{...list});
+  Expect.throwsTypeError(() => <int, int>{...set});
+  Expect.throwsTypeError(() => <int>{...map});
 }
diff --git a/tests/language_2/spread_collections/syntax_error_test.dart b/tests/language_2/spread_collections/syntax_error_test.dart
index 9f38d74..1ccea11 100644
--- a/tests/language_2/spread_collections/syntax_error_test.dart
+++ b/tests/language_2/spread_collections/syntax_error_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,spread-collections
+// SharedOptions=--enable-experiment=spread-collections
 
 void main() {
   // Spread nothing.
diff --git a/tests/language_2/spread_collections/syntax_test.dart b/tests/language_2/spread_collections/syntax_test.dart
index c46b589..7100394 100644
--- a/tests/language_2/spread_collections/syntax_test.dart
+++ b/tests/language_2/spread_collections/syntax_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,spread-collections
+// SharedOptions=--enable-experiment=spread-collections
 
 // Tests syntax edge cases.
 import 'package:expect/expect.dart';
diff --git a/tests/language_2/spread_collections/type_error_test.dart b/tests/language_2/spread_collections/type_error_test.dart
index 06f1cab..68cf98c 100644
--- a/tests/language_2/spread_collections/type_error_test.dart
+++ b/tests/language_2/spread_collections/type_error_test.dart
@@ -2,7 +2,7 @@
 // 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=--enable-experiment=set-literals,spread-collections
+// SharedOptions=--enable-experiment=spread-collections
 
 void main() {
   // Spread non-iterable or non-map.
diff --git a/tests/lib_2/math/random_secure_unsupported_test.dart b/tests/lib_2/math/random_secure_unsupported_test.dart
new file mode 100644
index 0000000..7e8744c
--- /dev/null
+++ b/tests/lib_2/math/random_secure_unsupported_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, 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 that `Random.secure()` throws `UnsupportedError` each time it fails.
+
+import "package:expect/expect.dart";
+import 'dart:math';
+
+main() {
+  var result1 = getRandom();
+  var result2 = getRandom();
+
+  Expect.isNotNull(result1);
+  Expect.isNotNull(result2); // This fired for http://dartbug.com/36206
+
+  Expect.equals(result1 is Random, result2 is Random);
+  Expect.equals(result1 is UnsupportedError, result2 is UnsupportedError);
+}
+
+dynamic getRandom() {
+  try {
+    return Random.secure();
+  } catch (e) {
+    return e;
+  }
+}
diff --git a/tests/standalone/io/process_environment_lib.dart b/tests/standalone/io/process_environment_lib.dart
new file mode 100644
index 0000000..7446236
--- /dev/null
+++ b/tests/standalone/io/process_environment_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, 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:io';
+
+void main() {
+  print(Platform.environment);
+}
diff --git a/tests/standalone/io/process_environment_test.dart b/tests/standalone/io/process_environment_test.dart
new file mode 100644
index 0000000..1a6767d
--- /dev/null
+++ b/tests/standalone/io/process_environment_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2019, 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:convert';
+import 'dart:io';
+import 'package:expect/expect.dart';
+import 'package:path/path.dart' as path;
+
+const String childFile = 'process_environment_lib.dart';
+const String fakeKey = 'Artificial';
+const String fakeValue = 'fakepath';
+
+void main() async {
+  Map<String, String> environ = Platform.environment;
+  String baseDirectory = path.dirname(Platform.script.path);
+  //DETACHED PROCESS WITHOUT includeParentEnvironment
+  var WithoutEnviron = await Process.start(
+      Platform.executable, [path.join(baseDirectory, childFile)],
+      mode: ProcessStartMode.detachedWithStdio,
+      includeParentEnvironment: false,
+      environment: <String, String>{fakeKey: fakeValue});
+
+  Map<String, String> notInclude = new Map();
+  await for (final line in WithoutEnviron.stdout
+      .transform(systemEncoding.decoder)
+      .transform(LineSplitter())) {
+    notInclude = RestoreToMap(line);
+  }
+
+  //Ensure the child process has the passed environment
+  Expect.isTrue(notInclude.length >= 1);
+  Expect.isTrue(notInclude.keys.contains(fakeKey));
+
+  //DETACHED PROCESS WITH includeParentEnvironment
+  var WithEnviron = await Process.start(
+      Platform.executable, [path.join(baseDirectory, childFile)],
+      mode: ProcessStartMode.detachedWithStdio,
+      includeParentEnvironment: true,
+      environment: <String, String>{fakeKey: fakeValue});
+
+  Map<String, String> include = new Map();
+  await for (final line in WithEnviron.stdout
+      .transform(systemEncoding.decoder)
+      .transform(LineSplitter())) {
+    include = RestoreToMap(line);
+  }
+
+  //Parent environment and one fake path
+  Expect.isTrue(include.length == environ.length + 1);
+  Expect.isTrue(include[fakeKey] == fakeValue);
+}
+
+Map<String, String> RestoreToMap(String s) {
+  s = s.substring(1, s.length - 1);
+  Map<String, String> result = new Map();
+  for (String line in s.split(", ")) {
+    var i = line.indexOf(": ");
+    result.putIfAbsent(line.substring(0, i), () => line.substring(i + 2));
+  }
+  return result;
+}
diff --git a/tests/standalone_2/ffi/dylib_utils.dart b/tests/standalone_2/ffi/dylib_utils.dart
index 1929961..1c924d4 100644
--- a/tests/standalone_2/ffi/dylib_utils.dart
+++ b/tests/standalone_2/ffi/dylib_utils.dart
@@ -9,6 +9,7 @@
   if (path == null) path = "";
   if (Platform.isLinux) return path + "lib" + name + ".so";
   if (Platform.isMacOS) return path + "lib" + name + ".dylib";
+  if (Platform.isWindows) return path + name + ".dll";
   throw Exception("Platform not implemented");
 }
 
diff --git a/tests/standalone_2/ffi/function_stress_test.dart b/tests/standalone_2/ffi/function_stress_test.dart
index 2f5f02c..fd3f0ec 100644
--- a/tests/standalone_2/ffi/function_stress_test.dart
+++ b/tests/standalone_2/ffi/function_stress_test.dart
@@ -2,10 +2,12 @@
 // 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.
 //
-// Dart test program for stress-testing boxing and GC.
 // VMOptions=--deterministic --optimization-counter-threshold=500 --verbose-gc
 // VMOptions=--deterministic --optimization-counter-threshold=-1 --verbose-gc
 //
+// Dart test program for stress-testing boxing and GC in return paths from FFI
+// trampolines.
+//
 // NOTE: This test does not produce useful stderr when it fails because the
 // stderr is redirected to a file for reflection.
 
@@ -32,14 +34,15 @@
 }
 
 main() async {
-  final watcher = GCWatcher();
+  final watcher = GCWatcher.ifAvailable();
   try {
     await test(watcher, testBoxInt64);
     // On 64-bit platforms this won't trigger GC because the result fits into a
     // Smi.
     await test(watcher, testBoxInt32, mustTriggerGC: false);
     await test(watcher, testBoxDouble);
-    await test(watcher, testBoxPointer);
+    await test(watcher, testBoxSmallPointer);
+    await test(watcher, testBoxLargePointer);
   } finally {
     watcher.dispose();
   }
@@ -56,9 +59,12 @@
 typedef NullaryOpDbl = double Function();
 typedef NullaryOpPtr = ffi.Pointer<ffi.Void> Function();
 
+//// These functions return values that require boxing into different types.
+
 final minInt64 =
     ffiTestFunctions.lookupFunction<NativeNullaryOp64, NullaryOp>("MinInt64");
 
+// Forces boxing into Mint on all platforms.
 void testBoxInt64() {
   Expect.equals(0x8000000000000000, minInt64());
 }
@@ -66,13 +72,15 @@
 NullaryOp minInt32 =
     ffiTestFunctions.lookupFunction<NativeNullaryOp32, NullaryOp>("MinInt32");
 
+// Forces boxing into Mint on 32-bit platforms only.
 void testBoxInt32() {
-  Expect.equals(0x80000000, minInt32());
+  Expect.equals(-0x80000000, minInt32());
 }
 
 final smallDouble = ffiTestFunctions
     .lookupFunction<NativeNullaryOpDouble, NullaryOpDbl>("SmallDouble");
 
+// Forces boxing into Double.
 void testBoxDouble() {
   Expect.equals(0x80000000 * -1.0, smallDouble());
 }
@@ -80,6 +88,16 @@
 final smallPointer = ffiTestFunctions
     .lookupFunction<NativeNullaryOpPtr, NullaryOpPtr>("SmallPointer");
 
-void testBoxPointer() {
+// Forces boxing into ffi.Pointer. On 32-bit platforms, also forces boxing into
+// Mint inside of ffi.Pointer.
+void testBoxSmallPointer() {
   Expect.equals(-0x80000000, smallPointer().address);
 }
+
+final largePointer = ffiTestFunctions
+    .lookupFunction<NativeNullaryOpPtr, NullaryOpPtr>("LargePointer");
+
+// Forces boxing into ffi.Pointer and ffi.Mint on all platforms.
+void testBoxLargePointer() {
+  Expect.equals(-0x8000000000000000, largePointer().address);
+}
diff --git a/tests/standalone_2/ffi/function_test.dart b/tests/standalone_2/ffi/function_test.dart
index c2019f7..d22f771 100644
--- a/tests/standalone_2/ffi/function_test.dart
+++ b/tests/standalone_2/ffi/function_test.dart
@@ -3,6 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 //
 // Dart test program for testing dart:ffi function pointers.
+//
+// VMOptions=
+// VMOptions=--deterministic --optimization-counter-threshold=10
 
 library FfiTest;
 
@@ -13,23 +16,26 @@
 import "package:expect/expect.dart";
 
 void main() {
-  testNativeFunctionFromCast();
-  testNativeFunctionFromLookup();
-  test64bitInterpretations();
-  testTruncation();
-  testNativeFunctionDoubles();
-  testNativeFunctionFloats();
-  testNativeFunctionManyArguments1();
-  testNativeFunctionManyArguments2();
-  testNativeFunctionManyArguments3();
-  testNativeFunctionPointer();
-  testNullInt();
-  testNullDouble();
-  testNullManyArgs();
-  testNullPointers();
-  testFloatRounding();
-  testVoidReturn();
-  testNoArgs();
+  for (int i = 0; i < 100; ++i) {
+    testNativeFunctionFromCast();
+    testNativeFunctionFromLookup();
+    test64bitInterpretations();
+    testExtension();
+    testTruncation();
+    testNativeFunctionDoubles();
+    testNativeFunctionFloats();
+    testNativeFunctionManyArguments1();
+    testNativeFunctionManyArguments2();
+    testNativeFunctionManyArguments3();
+    testNativeFunctionPointer();
+    testNullInt();
+    testNullDouble();
+    testNullManyArgs();
+    testNullPointers();
+    testFloatRounding();
+    testVoidReturn();
+    testNoArgs();
+  }
 }
 
 ffi.DynamicLibrary ffiTestFunctions =
@@ -43,8 +49,8 @@
 void testNativeFunctionFromCast() {
   ffi.Pointer<ffi.IntPtr> p1 = ffi.allocate();
   ffi.Pointer<ffi.NativeFunction<NativeBinaryOp>> p2 = p1.cast();
-  BinaryOp f = p2.asFunction<BinaryOp>();
-  BinaryOp f2 = p2.asFunction<GenericBinaryOp<int>>();
+  p2.asFunction<BinaryOp>();
+  p2.asFunction<GenericBinaryOp<int>>();
   p1.free();
 }
 
@@ -54,13 +60,15 @@
 typedef NativeQuadOpUnsigned = ffi.Uint64 Function(
     ffi.Uint64, ffi.Uint32, ffi.Uint16, ffi.Uint8);
 
+BinaryOp sumPlus42 =
+    ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
+
+QuadOp intComputation = ffiTestFunctions
+    .lookupFunction<NativeQuadOpSigned, QuadOp>("IntComputation");
+
 void testNativeFunctionFromLookup() {
-  BinaryOp sumPlus42 =
-      ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
   Expect.equals(49, sumPlus42(3, 4));
 
-  QuadOp intComputation = ffiTestFunctions
-      .lookupFunction<NativeQuadOpSigned, QuadOp>("IntComputation");
   Expect.equals(625, intComputation(125, 250, 500, 1000));
 
   Expect.equals(
@@ -69,10 +77,29 @@
       -0x8000000000000000, intComputation(0, 0, 0, -0x8000000000000000));
 }
 
-void test64bitInterpretations() {
-  QuadOp uintComputation = ffiTestFunctions
-      .lookupFunction<NativeQuadOpUnsigned, QuadOp>("UintComputation");
+typedef NativeNullaryOpSigned = ffi.Int32 Function();
+typedef NativeNullaryOpUnsigned = ffi.Uint32 Function();
 
+int Function() unsignedOp = ffiTestFunctions
+    .lookup("TestExtension")
+    .cast<ffi.Pointer<ffi.NativeFunction<NativeNullaryOpUnsigned>>>()
+    .asFunction();
+
+int Function() signedOp = ffiTestFunctions
+    .lookup("TestExtension")
+    .cast<ffi.Pointer<ffi.NativeFunction<NativeNullaryOpSigned>>>()
+    .asFunction();
+
+// Test 32-bit (int32_t) -> 64-bit (Dart int) sign extension and truncation.
+void testExtension() {
+  Expect.equals(unsignedOp(), 0x80000000);
+  Expect.equals(signedOp(), 0xffffffff80000000);
+}
+
+QuadOp uintComputation = ffiTestFunctions
+    .lookupFunction<NativeQuadOpUnsigned, QuadOp>("UintComputation");
+
+void test64bitInterpretations() {
   // 2 ^ 63 - 1
   Expect.equals(
       0x7FFFFFFFFFFFFFFF, uintComputation(0, 0, 0, 0x7FFFFFFFFFFFFFFF));
@@ -87,10 +114,10 @@
     ffi.Int8, ffi.Int16, ffi.Int32, ffi.Uint8, ffi.Uint16, ffi.Uint32);
 typedef SenaryOp = int Function(int, int, int, int, int, int);
 
-void testTruncation() {
-  SenaryOp sumSmallNumbers = ffiTestFunctions
-      .lookupFunction<NativeSenaryOp, SenaryOp>("SumSmallNumbers");
+SenaryOp sumSmallNumbers = ffiTestFunctions
+    .lookupFunction<NativeSenaryOp, SenaryOp>("SumSmallNumbers");
 
+void testTruncation() {
   // TODO(dacoharkes): implement truncation and sign extension in trampolines
   // for values smaller than 32 bits.
   sumSmallNumbers(128, 0, 0, 0, 0, 0);
@@ -113,17 +140,19 @@
 typedef NativeDoubleUnaryOp = ffi.Double Function(ffi.Double);
 typedef DoubleUnaryOp = double Function(double);
 
+DoubleUnaryOp times1_337Double = ffiTestFunctions
+    .lookupFunction<NativeDoubleUnaryOp, DoubleUnaryOp>("Times1_337Double");
+
 void testNativeFunctionDoubles() {
-  DoubleUnaryOp times1_337Double = ffiTestFunctions
-      .lookupFunction<NativeDoubleUnaryOp, DoubleUnaryOp>("Times1_337Double");
   Expect.approxEquals(2.0 * 1.337, times1_337Double(2.0));
 }
 
 typedef NativeFloatUnaryOp = ffi.Float Function(ffi.Float);
 
+DoubleUnaryOp times1_337Float = ffiTestFunctions
+    .lookupFunction<NativeFloatUnaryOp, DoubleUnaryOp>("Times1_337Float");
+
 void testNativeFunctionFloats() {
-  DoubleUnaryOp times1_337Float = ffiTestFunctions
-      .lookupFunction<NativeFloatUnaryOp, DoubleUnaryOp>("Times1_337Float");
   Expect.approxEquals(1337.0, times1_337Float(1000.0));
 }
 
@@ -141,9 +170,10 @@
 typedef OctenaryOp = int Function(
     int, int, int, int, int, int, int, int, int, int);
 
+OctenaryOp sumManyInts = ffiTestFunctions
+    .lookupFunction<NativeOctenaryOp, OctenaryOp>("SumManyInts");
+
 void testNativeFunctionManyArguments1() {
-  OctenaryOp sumManyInts = ffiTestFunctions
-      .lookupFunction<NativeOctenaryOp, OctenaryOp>("SumManyInts");
   Expect.equals(55, sumManyInts(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
 }
 
@@ -161,10 +191,10 @@
 typedef DoubleOctenaryOp = double Function(double, double, double, double,
     double, double, double, double, double, double);
 
+DoubleOctenaryOp sumManyDoubles = ffiTestFunctions
+    .lookupFunction<NativeDoubleOctenaryOp, DoubleOctenaryOp>("SumManyDoubles");
+
 void testNativeFunctionManyArguments2() {
-  DoubleOctenaryOp sumManyDoubles =
-      ffiTestFunctions.lookupFunction<NativeDoubleOctenaryOp, DoubleOctenaryOp>(
-          "SumManyDoubles");
   Expect.approxEquals(
       55.0, sumManyDoubles(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0));
 }
@@ -212,9 +242,10 @@
     int,
     double);
 
+VigesimalOp sumManyNumbers = ffiTestFunctions
+    .lookupFunction<NativeVigesimalOp, VigesimalOp>("SumManyNumbers");
+
 void testNativeFunctionManyArguments3() {
-  VigesimalOp sumManyNumbers = ffiTestFunctions
-      .lookupFunction<NativeVigesimalOp, VigesimalOp>("SumManyNumbers");
   Expect.approxEquals(
       210.0,
       sumManyNumbers(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11, 12.0, 13,
@@ -224,9 +255,10 @@
 typedef Int64PointerUnOp = ffi.Pointer<ffi.Int64> Function(
     ffi.Pointer<ffi.Int64>);
 
+Int64PointerUnOp assign1337Index1 = ffiTestFunctions
+    .lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("Assign1337Index1");
+
 void testNativeFunctionPointer() {
-  Int64PointerUnOp assign1337Index1 = ffiTestFunctions
-      .lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("Assign1337Index1");
   ffi.Pointer<ffi.Int64> p2 = ffi.allocate(count: 2);
   p2.store(42);
   p2.elementAt(1).store(1000);
@@ -245,23 +277,18 @@
 }
 
 void testNullDouble() {
-  DoubleUnaryOp times1_337Double = ffiTestFunctions
-      .lookupFunction<NativeDoubleUnaryOp, DoubleUnaryOp>("Times1_337Double");
   Expect.throws(() => times1_337Double(null));
 }
 
 void testNullManyArgs() {
-  VigesimalOp sumManyNumbers = ffiTestFunctions
-      .lookupFunction<NativeVigesimalOp, VigesimalOp>("SumManyNumbers");
   Expect.throws(() => sumManyNumbers(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0,
       11, 12.0, 13, 14.0, 15, 16.0, 17, 18.0, null, 20.0));
 }
 
-void testNullPointers() {
-  Int64PointerUnOp nullableInt64ElemAt1 =
-      ffiTestFunctions.lookupFunction<Int64PointerUnOp, Int64PointerUnOp>(
-          "NullableInt64ElemAt1");
+Int64PointerUnOp nullableInt64ElemAt1 = ffiTestFunctions
+    .lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("NullableInt64ElemAt1");
 
+void testNullPointers() {
   ffi.Pointer<ffi.Int64> result = nullableInt64ElemAt1(null);
   Expect.isNull(result);
 
@@ -274,10 +301,10 @@
 typedef NativeFloatPointerToBool = ffi.Uint8 Function(ffi.Pointer<ffi.Float>);
 typedef FloatPointerToBool = int Function(ffi.Pointer<ffi.Float>);
 
-void testFloatRounding() {
-  FloatPointerToBool isRoughly1337 = ffiTestFunctions.lookupFunction<
-      NativeFloatPointerToBool, FloatPointerToBool>("IsRoughly1337");
+FloatPointerToBool isRoughly1337 = ffiTestFunctions.lookupFunction<
+    NativeFloatPointerToBool, FloatPointerToBool>("IsRoughly1337");
 
+void testFloatRounding() {
   ffi.Pointer<ffi.Float> p2 = ffi.allocate();
   p2.store(1337.0);
 
@@ -290,10 +317,10 @@
 typedef NativeFloatToVoid = ffi.Void Function(ffi.Float);
 typedef DoubleToVoid = void Function(double);
 
-void testVoidReturn() {
-  DoubleToVoid devNullFloat = ffiTestFunctions
-      .lookupFunction<NativeFloatToVoid, DoubleToVoid>("DevNullFloat");
+DoubleToVoid devNullFloat = ffiTestFunctions
+    .lookupFunction<NativeFloatToVoid, DoubleToVoid>("DevNullFloat");
 
+void testVoidReturn() {
   devNullFloat(1337.0);
 
   dynamic loseSignature = devNullFloat;
@@ -304,10 +331,10 @@
 typedef NativeVoidToFloat = ffi.Float Function();
 typedef VoidToDouble = double Function();
 
-void testNoArgs() {
-  VoidToDouble inventFloatValue = ffiTestFunctions
-      .lookupFunction<NativeVoidToFloat, VoidToDouble>("InventFloatValue");
+VoidToDouble inventFloatValue = ffiTestFunctions
+    .lookupFunction<NativeVoidToFloat, VoidToDouble>("InventFloatValue");
 
+void testNoArgs() {
   double result = inventFloatValue();
   Expect.approxEquals(1337.0, result);
 }
diff --git a/tests/standalone_2/ffi/gc_helper.dart b/tests/standalone_2/ffi/gc_helper.dart
index 084a0ce..5e9431d 100644
--- a/tests/standalone_2/ffi/gc_helper.dart
+++ b/tests/standalone_2/ffi/gc_helper.dart
@@ -3,25 +3,48 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io';
-import 'dart:convert';
 import 'dylib_utils.dart';
 import 'dart:ffi';
+import 'dart:io' show Platform;
 
 DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
 
+abstract class GCWatcher {
+  factory GCWatcher() => _GCWatcherImpl();
+  factory GCWatcher.dummy() => _MockGCWatcher();
+  factory GCWatcher.ifAvailable() =>
+      Platform.isWindows ? GCWatcher.dummy() : GCWatcher();
+
+  Future<int> size();
+  void dispose();
+}
+
 // Requires --verbose-gc.
-class GCWatcher {
+class _GCWatcherImpl implements GCWatcher {
   int _suffix;
 
   Future<int> size() async {
     return await File("/tmp/captured_stderr_$_suffix").length();
   }
 
-  GCWatcher() {
+  _GCWatcherImpl() {
     print("Starting...");
     _suffix = ffiTestFunctions
         .lookupFunction<Int32 Function(), int Function()>("RedirectStderr")();
   }
 
-  dispose() => File("/tmp/captured_stderr_$_suffix").deleteSync();
+  dispose() {
+    try {
+      File("/tmp/captured_stderr_$_suffix").deleteSync();
+    } catch (e) {
+      print("deleting file failed");
+    }
+  }
+}
+
+class _MockGCWatcher implements GCWatcher {
+  int _ctr = 0;
+
+  Future<int> size() async => ++_ctr;
+  dispose() {}
 }
diff --git a/tests/standalone_2/ffi/negative_function_test.dart b/tests/standalone_2/ffi/negative_function_test.dart
index f716ca5..a529d67 100644
--- a/tests/standalone_2/ffi/negative_function_test.dart
+++ b/tests/standalone_2/ffi/negative_function_test.dart
@@ -19,8 +19,8 @@
 typedef NativeBinaryOp = ffi.Int32 Function(ffi.Int32, ffi.Int32);
 typedef BinaryOp = int Function(int, int);
 
-typedef NativeUnaryOp = ffi.Int64 Function(ffi.Int64);
-typedef UnaryOp = int Function(int);
+typedef NativeUnaryOp = ffi.Int64 Function(ffi.Pointer<ffi.Int64>);
+typedef UnaryOp = int Function(ffi.Pointer<ffi.Int64>);
 
 void testWrongArity() {
   {
@@ -44,18 +44,18 @@
   {
     dynamic sumPlus42 =
         ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
-    Expect.throwsNoSuchMethodError(() => sumPlus42("abc", "def"));
+    Expect.throwsTypeError(() => sumPlus42("abc", "def"));
   }
 
   {
     Function sumPlus42 =
         ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
-    Expect.throwsNoSuchMethodError(() => sumPlus42("abc", "def"));
+    Expect.throwsTypeError(() => sumPlus42("abc", "def"));
   }
 
   {
     dynamic pointerOp = ffiTestFunctions
         .lookupFunction<NativeUnaryOp, UnaryOp>("Assign1337Index1");
-    Expect.throwsNoSuchMethodError(() => pointerOp(0));
+    Expect.throwsTypeError(() => pointerOp(0));
   }
 }
diff --git a/tests/standalone_2/ffi/subtype_test.dart b/tests/standalone_2/ffi/subtype_test.dart
index dd466ae..22dbe13 100644
--- a/tests/standalone_2/ffi/subtype_test.dart
+++ b/tests/standalone_2/ffi/subtype_test.dart
@@ -39,7 +39,7 @@
   CString cs = ffi.fromAddress<CString>(11);
   bar = cs;
   foo = "";
-  final watcher = GCWatcher();
+  final watcher = GCWatcher.ifAvailable();
   int counts = await watcher.size();
   for (int i = 0; i < 1000000; ++i) {
     foo = new X(i);
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index a68bdd7..2e1dc6a 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -8,6 +8,7 @@
 io/process_sync_test: Pass, Slow # Spawns synchronously subprocesses in sequence.
 
 [ $builder_tag == asan ]
+ffi/data_not_asan_test: Skip # this test tries to allocate too much memory on purpose
 io/file_test: Fail # Issue 34724
 io/http_server_response_test: Fail # Issue 34724
 io/process_sync_test: Pass, Fail # https://github.com/dart-lang/sdk/issues/34724
@@ -15,6 +16,11 @@
 io/test_extension_fail_test: Fail # Issue 32187
 
 [ $compiler == app_jitk ]
+ffi/dynamic_library_test: Skip # https://github.com/dart-lang/sdk/issues/35934
+ffi/function_callbacks_test: Skip # https://github.com/dart-lang/sdk/issues/35934
+ffi/function_structs_test: Skip # https://github.com/dart-lang/sdk/issues/35934
+ffi/function_test: Skip # https://github.com/dart-lang/sdk/issues/35934
+ffi/negative_function_test: Skip # https://github.com/dart-lang/sdk/issues/35934
 io/file_error_test: RuntimeError
 io/file_test: RuntimeError
 io/http_auth_digest_test: RuntimeError
@@ -42,6 +48,9 @@
 io/arguments_test: Fail # Test harness passes runtime arguments to the compiler
 io/test_runner_test: SkipByDesign # Is not relevant for AOT.
 
+[ $runtime == dart_precompiled ]
+ffi: Skip # https://github.com/dart-lang/sdk/issues/35765
+
 [ $system == android ]
 entrypoints_verification_test: Skip # Requires shared objects which the test script doesn't "adb push".
 
@@ -157,6 +166,9 @@
 [ $mode == debug && $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
 io/web_socket_ping_test: Crash, Pass
 
+[ $runtime != dart_precompiled && $runtime != vm ]
+ffi: SkipByDesign # ffi is only supported on vm
+
 [ $runtime == vm && $strong && ($compiler == dartk || $compiler == dartkb) ]
 io/http_client_request_test: Pass, Timeout
 io/secure_builtin_roots_test: Pass, Timeout
@@ -229,12 +241,12 @@
 io/web_socket_compression_test: Skip # Timeout
 io/web_socket_test: Skip # Timeout
 
-[ $arch != x64 || $compiler != dartk || $mode == product || $system != linux && $system != macos]
+[ $arch != x64 || $compiler != dartk || $mode == product || $system != linux && $system != macos && $system != windows ]
 ffi/function_stress_test: SkipByDesign # FFI must be supported. Also requires --verbose-gc, which isn't included in product.
 ffi/subtype_test: SkipByDesign # FFI must be supported. Also requires --verbose-gc, which isn't included in product.
 
-[ $mode == product || $mode != product ]
-ffi/negative_function_test: Skip # Issues 36033, 36034
+[ $arch != x64 || $system != linux && $system != macos && $system != windows ]
+ffi: Skip # ffi not yet supported on other systems than linux/macos/windows x64
 
 [ $compiler != dartk && $compiler != dartkb && $compiler != dartkp || $compiler == dartkp && $system == windows ]
 entrypoints_verification_test: SkipByDesign # Requires VM to run. Cannot run in precompiled Windows because the DLL is linked against dart.exe instead of dart_precompiled_runtime.exe.
diff --git a/tests/standalone_2/standalone_2_vm.status b/tests/standalone_2/standalone_2_vm.status
index 49b61dc..bc23a30 100644
--- a/tests/standalone_2/standalone_2_vm.status
+++ b/tests/standalone_2/standalone_2_vm.status
@@ -6,9 +6,6 @@
 link_natives_lazily_test: SkipByDesign # Not supported.
 no_allow_absolute_addresses_test: SkipByDesign # Not supported.
 
-[ $builder_tag == asan ]
-ffi/data_not_asan_test: Skip # this test tries to allocate too much memory on purpose
-
 [ $compiler == app_jit ]
 full_coverage_test: Skip # Platform.executable
 io/code_collection_test: Skip # Platform.executable
@@ -25,15 +22,6 @@
 io/test_runner_test: RuntimeError # Issue 33168
 regress_26031_test: Skip # Platform.resolvedExecutable
 
-[ $compiler == app_jitk ]
-ffi/dynamic_library_test: Skip # https://github.com/dart-lang/sdk/issues/35934
-ffi/function_callbacks_test: Skip # https://github.com/dart-lang/sdk/issues/35934
-ffi/function_structs_test: Skip # https://github.com/dart-lang/sdk/issues/35934
-ffi/function_test: Skip # https://github.com/dart-lang/sdk/issues/35934
-
-[ $runtime == dart_precompiled ]
-ffi: Skip # https://github.com/dart-lang/sdk/issues/35765
-
 [ $runtime == vm ]
 io/test_runner_test: Skip # Spawns a process which runs in Dart2 mode.
 
@@ -85,15 +73,9 @@
 [ $arch == x64 && $compiler == dartkb && $runtime == vm && $system == linux ]
 io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 35192
 
-[ $arch == x64 && $mode == debug && $system == linux && $hot_reload ]
-ffi/subtype_test: Skip # https://github.com/dart-lang/sdk/issues/35933
-
 [ $compiler != dart2analyzer && $system == windows ]
 io/platform_resolved_executable_test/06: RuntimeError # Issue 23641
 
-[ $compiler == dartkb && $mode == debug ]
-ffi/subtype_test: Skip # https://github.com/dart-lang/sdk/issues/35935
-
 [ $mode == release && $runtime == vm && $system == linux && ($arch == simdbc64 || $arch == x64) ]
 io/http_bind_test: Pass, Timeout # Issue 35192
 
@@ -107,9 +89,6 @@
 [ $runtime == dart_precompiled && $system == linux && ($arch == simarm || $arch == simarm64 || $arch == x64) ]
 io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 35192
 
-[ $runtime != dart_precompiled && $runtime != vm ]
-ffi: SkipByDesign # ffi is only supported on vm
-
 [ $runtime == vm && !$checked && !$strong ]
 io/file_constructor_test: RuntimeError
 
@@ -132,6 +111,3 @@
 full_coverage_test: Skip # TODO(vegorov) SIMDBC interpreter doesn't support coverage yet.
 link_natives_lazily_test: SkipByDesign # SIMDBC interpreter doesn't support lazy linking of natives.
 no_lazy_dispatchers_test: SkipByDesign # SIMDBC interpreter doesn't support --no_lazy_dispatchers
-
-[ $arch != x64 || $system != linux && $system != macos ]
-ffi: Skip # ffi not yet supported on other systems than linux/macos 64
diff --git a/tools/VERSION b/tools/VERSION
index 6ba184f..2096130 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -33,7 +33,7 @@
 MAJOR 2
 MINOR 2
 PATCH 1
-PRERELEASE 1
-PRERELEASE_PATCH 1
+PRERELEASE 2
+PRERELEASE_PATCH 0
 ABI_VERSION 0
 OLDEST_SUPPORTED_ABI_VERSION 0
diff --git a/tools/abiversions/.gitignore b/tools/abiversions/.gitignore
new file mode 100644
index 0000000..3e2c1ba
--- /dev/null
+++ b/tools/abiversions/.gitignore
@@ -0,0 +1,4 @@
+# This directory is populated by gclient sync. But we still need the directory
+# to be checked in, and git doesn't track empty directories, hence this file.
+*
+!.gitignore
diff --git a/tools/approve_results.dart b/tools/approve_results.dart
index 2279db2..9d11f48 100755
--- a/tools/approve_results.dart
+++ b/tools/approve_results.dart
@@ -8,6 +8,7 @@
 /// green.
 
 import 'dart:async';
+import 'dart:collection';
 import 'dart:convert';
 import 'dart:io';
 import 'dart:math';
@@ -73,25 +74,45 @@
         ? loadResultsMap(path)
         : <String, Map<String, dynamic>>{};
 
+/// Exception for when the results for a builder can't be found.
+class NoResultsException implements Exception {
+  final String message;
+  final String buildUrl;
+
+  NoResultsException(this.message, this.buildUrl);
+
+  String toString() => message;
+}
+
 /// Loads a log from logdog.
 Future<String> loadLog(String id, String step) async {
+  final buildUrl = "https://ci.chromium.org/b/$id";
   final logUrl = Uri.parse("https://logs.chromium.org/"
       "logs/dart/buildbucket/cr-buildbucket.appspot.com/"
       "$id/+/steps/$step?format=raw");
   final client = new HttpClient();
-  final request =
-      await client.getUrl(logUrl).timeout(const Duration(seconds: 60));
-  final response = await request.close().timeout(const Duration(seconds: 60));
-  if (response.statusCode != HttpStatus.ok) {
-    throw new Exception("The log at $logUrl doesn't exist");
+  try {
+    final request =
+        await client.getUrl(logUrl).timeout(const Duration(seconds: 60));
+    final response = await request.close().timeout(const Duration(seconds: 60));
+    if (response.statusCode == HttpStatus.notFound) {
+      await response.drain();
+      throw new NoResultsException(
+          "The log at $logUrl doesn't exist: ${response.statusCode}", buildUrl);
+    }
+    if (response.statusCode != HttpStatus.ok) {
+      await response.drain();
+      throw new Exception("Failed to download $logUrl: ${response.statusCode}");
+    }
+    final contents = (await response
+            .transform(new Utf8Decoder())
+            .timeout(const Duration(seconds: 60))
+            .toList())
+        .join("");
+    return contents;
+  } finally {
+    client.close();
   }
-  final contents = (await response
-          .transform(new Utf8Decoder())
-          .timeout(const Duration(seconds: 60))
-          .toList())
-      .join("");
-  client.close();
-  return contents;
 }
 
 /// TODO(https://github.com/dart-lang/sdk/issues/36015): The step name changed
@@ -305,6 +326,12 @@
     return;
   }
 
+  if (options.rest.isNotEmpty) {
+    stderr.writeln("Unexpected extra argument: ${options.rest.first}");
+    exitCode = 1;
+    return;
+  }
+
   // Locate gsutil.py.
   gsutilPy =
       Platform.script.resolve("../third_party/gsutil/gsutil.py").toFilePath();
@@ -487,10 +514,19 @@
   // Load all the latest results for the selected bots, as well as flakiness
   // data, and the set of currently approved results. Each bot's latest build
   // is downloaded in parallel to make this phase faster.
-  final testListFutures = <Future>[];
+  final testListFutures = <Future<List<Test>>>[];
+  final noResultsBuilds = new SplayTreeMap<String, String>();
   for (final String bot in bots) {
-    testListFutures
-        .add(loadResultsFromBot(bot, options, changelistBuilds[bot]));
+    testListFutures.add(new Future(() async {
+      try {
+        return await loadResultsFromBot(bot, options, changelistBuilds[bot]);
+      } on NoResultsException catch (e) {
+        print(
+            "Error: Failed to find results for $bot build <${e.buildUrl}>: $e");
+        noResultsBuilds[bot] = e.buildUrl;
+        return <Test>[];
+      }
+    }));
   }
 
   // Collect all the tests from the synchronous downloads.
@@ -625,6 +661,17 @@
   statistic(brokenTests.length, tests.length,
       "tests were broken since last approval");
 
+  // Warn about any builders where results weren't available.
+  if (noResultsBuilds.isNotEmpty) {
+    print("");
+    noResultsBuilds.forEach((String builder, String buildUrl) {
+      print("Warning: No results were found for $builder: <$buildUrl>");
+    });
+    print("Warning: Builders without results are usually due to infrastructure "
+        "issues, please have a closer look at the affected builders and try "
+        "the build again.");
+  }
+
   // Stop if there's nothing to do.
   if (unapprovedBots.isEmpty) {
     print("\nEvery test result has already been approved.");
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 0dc5fc2..bcf66e7 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -195,7 +195,7 @@
         "timeout": 240,
         "use-sdk": true
     }},
-    "unittest-asserts-(release|debug)-(linux|mac|win)": {
+    "unittest-asserts-(debug|product|release)-(linux|mac|win)": {
       "options": {
         "compiler": "dartk",
         "enable-asserts": true,
@@ -211,7 +211,7 @@
         "runtime": "vm",
         "timeout": 240
     }},
-    "unittest-analyzer_use_fasta-linux": {
+    "unittest-analyzer_use_fasta-(linux|mac|win)": {
       "options": {
         "compiler": "none",
         "runtime": "vm",
@@ -220,7 +220,7 @@
         "vm-options": ["-DuseFastaParser=true"],
         "builder-tag": "analyzer_use_fasta"
     }},
-    "dartk-asan-linux-release-(ia32|x64)": {
+    "dartk-asan-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
       "options": {
         "builder-tag": "asan",
         "timeout": 240
@@ -241,96 +241,103 @@
       "options": {
         "use-sdk": true
     }},
-    "dart2js-minified-csp-linux-chrome": {
+    "dart2js-minified-csp-(linux|mac|win)-chrome": {
       "options": {
         "minified": true,
         "csp": true,
         "use-sdk": true
     }},
-    "dart2js-minified-linux-d8": {
+    "dart2js-minified-(linux|mac|win)-d8": {
       "options": {
         "minified": true,
         "use-sdk": true
     }},
-    "dart2js-hostasserts-linux-ia32-d8": {
+    "dart2js-production-(linux|mac|win)-d8": {
+      "options": {
+        "use-sdk": true,
+        "dart2js-options": ["-O3"]
+    }},
+    "dart2js-hostasserts-(linux|mac|win)-(ia32|x64)-d8": {
       "options": {
         "host-checked": true
     }},
-    "dartkp-android-release-arm": {
+    "dartkp-android-(debug|product|release)-arm": {
       "options": {
         "use-blobs": true
     }},
-    "dartkp-linux-release-(simarm|simarm64)": {
+    "dartkp-linux-(debug|product|release)-(simarm|simarm64)": {
       "options": {
         "use-blobs": true
     }},
-    "dartkp-(win|mac)-release-simarm64": {
+    "dartkp-(win|mac)-(debug|product|release)-(simarm|simarm64)": {
       "options": {
         "use-blobs": true
     }},
-    "dartkp-win-release-x64": {
+    "dartkp-win-(product|release)-x64": {
       "options": {
         "use-blobs": true
     }},
-    "dartkp-linux-(product|release)-x64": { },
-    "dartkp-obfuscate-linux-release-x64": {
+    "dartkp-win-debug-x64": {
+      "options": {
+        "use-blobs": true,
+        "vm-options": ["--no-enable-malloc-hooks"]
+    }},
+    "dartkp-(linux|mac)-(product|release)-x64": { },
+    "dartkp-obfuscate-(linux|mac|win)-(debug|product|release)-x64": {
       "options": {
         "builder-tag": "obfuscated",
         "vm-options": ["--obfuscate"]
     }},
-    "dartkp-linux-debug-x64": {
+    "dartkp-(linux|mac)-debug-x64": {
       "options": {
         "vm-options": ["--no-enable-malloc-hooks"]
     }},
-    "dartkp-no-bare-linux-(debug|release)-x64": {
+    "dartkp-no-bare-(linux|mac|win)-(debug|product|release)-x64": {
       "options": {
         "vm-options": ["--no-enable-malloc-hooks", "--no-use-bare-instructions"]
     }},
-    "dartkp-no-bare-linux-(debug|release)-(simarm|simarm64)": {
+    "dartkp-no-bare-(linux|mac|win)-(debug|product|release)-(simarm|simarm64)": {
       "options": {
         "vm-options": ["--no-enable-malloc-hooks", "--no-use-bare-instructions"],
         "use-blobs": true
     }},
-    "dartk-(linux|mac)-(debug|release)-(ia32|x64)": { },
-    "dartk-checked-linux-release-x64": {
+    "dartk-(linux|mac|win)-(debug|product|release)-(ia32|x64)": { },
+    "dartk-checked-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
       "options": {
         "checked": true
     }},
-    "dartk-win-(debug|release)-(ia32|x64)": { },
-    "dartk-(linux|mac|win)-product-x64": { },
-    "dartk-(linux|mac)-(debug|release)-simdbc64": { },
-    "dartk-linux-release-(arm64|simarm|simarm64)": { },
-    "dartk-optcounter-linux-release-(ia32|x64)": {
+    "dartk-(linux|mac|win)-(debug|product|release)-(arm64|simarm|simarm64|simdbc64)": { },
+    "dartk-optcounter-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
       "options": {
         "builder-tag": "optimization_counter_threshold",
         "vm-options": ["--optimization-counter-threshold=5"]
     }},
-    "dartk-reload-linux-(debug|release)-x64": {
+    "dartk-reload-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
       "options": {
         "hot-reload": true
     }},
-    "dartk-reload-mac-(debug|release)-simdbc64": {
+    "dartk-reload-mac-(debug|product|release)-simdbc64": {
       "options": {
         "hot-reload": true
     }},
-    "dartk-reload-rollback-linux-(debug|release)-x64": {
+    "dartk-reload-rollback-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
       "options": {
         "hot-reload-rollback": true
     }},
-    "app_jitk-linux-(debug|product|release)-x64": { },
-    "dartkb-interpret-linux-(debug|release)-x64": {
+    "app_jitk-(linux|mac|win)-(debug|product|release)-(ia32|x64)": { },
+    "dartkb-interpret-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
       "options": {
         "vm-options": ["--enable_interpreter", "--compilation-counter-threshold=-1"]
     }},
-    "dartkb-mixed-linux-(debug|release)-x64": {
+    "dartkb-mixed-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
       "options": {
         "vm-options": ["--enable_interpreter"]
     }},
-    "dartkb-compile-linux-(debug|release)-x64": {
+    "dartkb-compile-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
       "options": {
         "vm-options": ["--use_bytecode_compiler"]
     }},
-    "(dartdevc|dartdevk)-checked-(linux|mac|win)-release-chrome": {
+    "(dartdevc|dartdevk)-checked-(linux|mac|win)-(debug|product|release)-chrome": {
       "options": {
         "checked": true,
         "use-sdk": true
@@ -614,7 +621,7 @@
           "arguments": [
             "-ndartk-asan-linux-release-${arch}"],
           "environment": {
-            "ASAN_OPTIONS": "handle_segv=0:detect_stack_use_after_return=0",
+            "ASAN_OPTIONS": "handle_segv=0:detect_stack_use_after_return=0:disable_coredump=0",
             "ASAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
           }
         }
@@ -1181,6 +1188,25 @@
             "dart2js_extra",
             "dart2js_native"
           ]
+        },
+        {
+          "name": "dart2js production tests",
+          "arguments": [
+            "-ndart2js-production-linux-d8",
+            "--dart2js-batch",
+            "--exclude_suite=observatory_ui"
+          ],
+          "shards": 6,
+          "fileset": "dart2js"
+        },
+        {
+          "name": "dart2js production extra tests",
+          "arguments": [
+            "-ndart2js-production-linux-d8",
+            "--dart2js-batch",
+            "dart2js_extra",
+            "dart2js_native"
+          ]
         }
       ]
     },
@@ -1385,7 +1411,7 @@
         {
           "name": "analyze tests co19_2",
           "arguments": [
-            "-nanalyzer-${system}",
+            "-nanalyzer-asserts-${system}",
             "co19_2"
           ]
         }
diff --git a/tools/download_abi_dills.py b/tools/download_abi_dills.py
index e45b2ce..fb77a55 100644
--- a/tools/download_abi_dills.py
+++ b/tools/download_abi_dills.py
@@ -1,5 +1,6 @@
 # Downloads dill files from CIPD for each supported ABI version.
 
+import os
 import subprocess
 import sys
 import utils
@@ -8,12 +9,19 @@
 def main():
   abi_version = int(utils.GetAbiVersion())
   oldest_abi_version = int(utils.GetOldestSupportedAbiVersion())
+  cmd = ['cipd', 'ensure', '-root', 'tools/abiversions', '-ensure-file', '-']
+  ensure_file = ''
   for i in xrange(oldest_abi_version, abi_version):
-    cmd = ['cipd', 'install', 'dart/abiversions/%d' % i, 'latest']
-    result = subprocess.call(cmd)
-    if result != 0:
-      return 1
-  return 0
+    ensure_file += '@Subdir %d\ndart/abiversions/%d latest\n\n' % (i, i)
+  if not ensure_file:
+    return 0
+  p = subprocess.Popen(cmd,
+                       stdin = subprocess.PIPE,
+                       shell = utils.IsWindows(),
+                       cwd = utils.DART_DIR)
+  p.communicate(ensure_file)
+  p.stdin.close()
+  return p.wait()
 
 
 if __name__ == '__main__':
diff --git a/tools/gardening/bin/results_list.dart b/tools/gardening/bin/results_list.dart
index 2e9322c..e0baa1b 100644
--- a/tools/gardening/bin/results_list.dart
+++ b/tools/gardening/bin/results_list.dart
@@ -17,9 +17,6 @@
   argParser.addOption("compiler", allowed: Compiler.names);
   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);
   argParser.addFlag("host-checked", negatable: false);
@@ -54,8 +51,6 @@
       argResults["builder-tag"],
       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 53da74d..9f35774 100644
--- a/tools/gardening/lib/src/results/configuration_environment.dart
+++ b/tools/gardening/lib/src/results/configuration_environment.dart
@@ -27,8 +27,6 @@
   "checked": new _Variable.bool((c) => c.checked),
   "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 954b1c52..7a55a89 100644
--- a/tools/gardening/lib/src/results/result_json_models.dart
+++ b/tools/gardening/lib/src/results/result_json_models.dart
@@ -23,8 +23,6 @@
   final String builderTag;
   final bool fastStartup;
   final int timeout;
-  final bool dart2JsWithKernel;
-  final bool dart2JsOldFrontend;
   final bool enableAsserts;
   final bool hotReload;
   final bool hotReloadRollback;
@@ -48,8 +46,6 @@
       this.builderTag,
       this.fastStartup,
       this.timeout,
-      this.dart2JsWithKernel,
-      this.dart2JsOldFrontend,
       this.enableAsserts,
       this.hotReload,
       this.hotReloadRollback,
@@ -75,8 +71,6 @@
         json["builder_tag"],
         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,
@@ -103,8 +97,6 @@
       _boolToArg("use-sdk", useSdk),
       _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),
@@ -119,7 +111,7 @@
   String toCsvString() {
     return "$mode;$arch;$compiler;$runtime;$checked;$strong;$hostChecked;"
         "$minified;$csp;$fasta;$system;$vmOptions;$useSdk;$builderTag;$fastStartup;"
-        "$dart2JsWithKernel;$dart2JsOldFrontend;$enableAsserts;$hotReload;"
+        "$enableAsserts;$hotReload;"
         "$hotReloadRollback;$noPreviewDart2;$selectors";
   }
 
diff --git a/tools/patches/flutter-engine/7418238239f885ba92093c44a1768f8ec93b121f.patch b/tools/patches/flutter-engine/7418238239f885ba92093c44a1768f8ec93b121f.patch
new file mode 100644
index 0000000..69336e8
--- /dev/null
+++ b/tools/patches/flutter-engine/7418238239f885ba92093c44a1768f8ec93b121f.patch
@@ -0,0 +1,31 @@
+diff --git a/DEPS b/DEPS
+index 442e2d912..cb079bde9 100644
+--- a/DEPS
++++ b/DEPS
+@@ -37,7 +37,7 @@ vars = {
+   # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py
+   'dart_args_tag': '1.4.4',
+   'dart_async_tag': '2.0.8',
+-  'dart_bazel_worker_tag': '0.1.14',
++  'dart_bazel_worker_tag': 'bazel_worker-v0.1.20',
+   'dart_boolean_selector_tag': '1.0.4',
+   'dart_boringssl_gen_rev': 'bbf52f18f425e29b1185f2f6753bec02ed8c5880',
+   'dart_boringssl_rev': '702e2b6d3831486535e958f262a05c75a5cb312e',
+@@ -48,7 +48,7 @@ vars = {
+   'dart_crypto_tag': '2.0.6',
+   'dart_csslib_tag': '0.14.4+1',
+   'dart_dart2js_info_tag': '0.6.0',
+-  'dart_dart_style_tag': '1.2.2',
++  'dart_dart_style_tag': '1.2.4',
+   'dart_dartdoc_tag': 'v0.28.2',
+   'dart_fixnum_tag': '0.10.9',
+   'dart_glob_tag': '1.1.7',
+@@ -74,7 +74,7 @@ vars = {
+   'dart_path_tag': '1.6.2',
+   'dart_plugin_tag': 'f5b4b0e32d1406d62daccea030ba6457d14b1c47',
+   'dart_pool_tag': '1.3.6',
+-  'dart_protobuf_tag': '0.9.0',
++  'dart_protobuf_tag': '0c77167b16d00b561a6055bfe26690af7f26ae88',
+   'dart_pub_rev': '3c060aae47985e9a248b850f1d0450304a5c97e3',
+   'dart_pub_semver_tag': '1.4.2',
+   'dart_quiver_tag': '2.0.0+1',
diff --git a/tools/patches/flutter-engine/apply.sh b/tools/patches/flutter-engine/apply.sh
index d1105a5..9c2bd33 100755
--- a/tools/patches/flutter-engine/apply.sh
+++ b/tools/patches/flutter-engine/apply.sh
@@ -53,7 +53,7 @@
   # DEPS file might have been patched with new version of packages that
   # Dart SDK depends on. Get information about dependencies from the
   # DEPS file and forcefully update checkouts of those dependencies.
-  gclient revinfo | grep 'src/third_party/dart/' | while read -r line; do
+  gclient.py revinfo | grep 'src/third_party/dart/' | while read -r line; do
     # revinfo would produce lines in the following format:
     #     path: git-url@tag-or-hash
     # Where no spaces occur inside path, git-url or tag-or-hash.
@@ -82,5 +82,5 @@
     fi
     popd > /dev/null
   done
-  gclient runhooks
+  gclient.py runhooks
 fi
diff --git a/tools/patches/flutter-engine/c92d5ca288da15b54b04c0a40ffe5d94a8883d77.patch b/tools/patches/flutter-engine/c92d5ca288da15b54b04c0a40ffe5d94a8883d77.patch
deleted file mode 100644
index dc6194c..0000000
--- a/tools/patches/flutter-engine/c92d5ca288da15b54b04c0a40ffe5d94a8883d77.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/DEPS b/DEPS
-index 2af26b012..cd98d79f0 100644
---- a/DEPS
-+++ b/DEPS
-@@ -47,7 +47,7 @@ vars = {
-   'dart_convert_tag': '2.0.2',
-   'dart_crypto_tag': '2.0.6',
-   'dart_csslib_tag': '0.14.4+1',
--  'dart_dart2js_info_tag': '0.5.15',
-+  'dart_dart2js_info_tag': '0.6.0',
-   'dart_dart_style_tag': '1.2.2',
-   'dart_dartdoc_tag': 'v0.28.1+2',
-   'dart_fixnum_tag': '0.10.9',
diff --git a/tools/patches/flutter-flutter/502c9c4002a6b456f829f79bfbd2ff61d075d1d7.patch b/tools/patches/flutter-flutter/502c9c4002a6b456f829f79bfbd2ff61d075d1d7.patch
deleted file mode 100644
index 50eb1f4ea..0000000
--- a/tools/patches/flutter-flutter/502c9c4002a6b456f829f79bfbd2ff61d075d1d7.patch
+++ /dev/null
@@ -1,166 +0,0 @@
-diff --git a/packages/flutter_tools/lib/src/base/build.dart b/packages/flutter_tools/lib/src/base/build.dart
-index 7be3b8c20..8e6012042 100644
---- a/packages/flutter_tools/lib/src/base/build.dart
-+++ b/packages/flutter_tools/lib/src/base/build.dart
-@@ -46,13 +46,11 @@ class GenSnapshot {
- 
-   Future<int> run({
-     @required SnapshotType snapshotType,
--    @required String packagesPath,
-     IOSArch iosArch,
-     Iterable<String> additionalArgs = const <String>[],
-   }) {
-     final List<String> args = <String>[
-       '--causal_async_stacks',
--      '--packages=$packagesPath',
-     ]..addAll(additionalArgs);
- 
-     final String snapshotterPath = getSnapshotterPath(snapshotType);
-@@ -193,7 +191,6 @@ class AOTSnapshotter {
-     final SnapshotType snapshotType = SnapshotType(platform, buildMode);
-     final int genSnapshotExitCode = await genSnapshot.run(
-       snapshotType: snapshotType,
--      packagesPath: packageMap.packagesPath,
-       additionalArgs: genSnapshotArgs,
-       iosArch: iosArch,
-     );
-@@ -537,7 +534,6 @@ class JITSnapshotter {
-     final SnapshotType snapshotType = SnapshotType(platform, buildMode);
-     final int genSnapshotExitCode = await genSnapshot.run(
-       snapshotType: snapshotType,
--      packagesPath: packagesPath,
-       additionalArgs: genSnapshotArgs,
-     );
-     if (genSnapshotExitCode != 0) {
-diff --git a/packages/flutter_tools/test/base/build_test.dart b/packages/flutter_tools/test/base/build_test.dart
-index 81653aded..4d245a33d 100644
---- a/packages/flutter_tools/test/base/build_test.dart
-+++ b/packages/flutter_tools/test/base/build_test.dart
-@@ -190,7 +190,6 @@ void main() {
-       expect(genSnapshot.callCount, 1);
-       expect(genSnapshot.snapshotType.platform, TargetPlatform.ios);
-       expect(genSnapshot.snapshotType.mode, BuildMode.profile);
--      expect(genSnapshot.packagesPath, '.packages');
-       expect(genSnapshot.additionalArgs, <String>[
-         '--deterministic',
-         '--snapshot_kind=app-aot-assembly',
-@@ -229,7 +228,6 @@ void main() {
-       expect(genSnapshot.callCount, 1);
-       expect(genSnapshot.snapshotType.platform, TargetPlatform.ios);
-       expect(genSnapshot.snapshotType.mode, BuildMode.profile);
--      expect(genSnapshot.packagesPath, '.packages');
-       expect(genSnapshot.additionalArgs, <String>[
-         '--deterministic',
-         '--snapshot_kind=app-aot-assembly',
-@@ -268,7 +266,6 @@ void main() {
-       expect(genSnapshot.callCount, 1);
-       expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm);
-       expect(genSnapshot.snapshotType.mode, BuildMode.profile);
--      expect(genSnapshot.packagesPath, '.packages');
-       expect(genSnapshot.additionalArgs, <String>[
-         '--deterministic',
-         '--snapshot_kind=app-aot-blobs',
-@@ -312,7 +309,6 @@ void main() {
-       expect(genSnapshot.callCount, 1);
-       expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm64);
-       expect(genSnapshot.snapshotType.mode, BuildMode.profile);
--      expect(genSnapshot.packagesPath, '.packages');
-       expect(genSnapshot.additionalArgs, <String>[
-         '--deterministic',
-         '--snapshot_kind=app-aot-blobs',
-@@ -352,7 +348,6 @@ void main() {
-       expect(genSnapshot.callCount, 1);
-       expect(genSnapshot.snapshotType.platform, TargetPlatform.ios);
-       expect(genSnapshot.snapshotType.mode, BuildMode.release);
--      expect(genSnapshot.packagesPath, '.packages');
-       expect(genSnapshot.additionalArgs, <String>[
-         '--deterministic',
-         '--snapshot_kind=app-aot-assembly',
-@@ -391,7 +386,6 @@ void main() {
-       expect(genSnapshot.callCount, 1);
-       expect(genSnapshot.snapshotType.platform, TargetPlatform.ios);
-       expect(genSnapshot.snapshotType.mode, BuildMode.release);
--      expect(genSnapshot.packagesPath, '.packages');
-       expect(genSnapshot.additionalArgs, <String>[
-         '--deterministic',
-         '--snapshot_kind=app-aot-assembly',
-@@ -448,7 +442,6 @@ void main() {
-       expect(genSnapshot.callCount, 1);
-       expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm);
-       expect(genSnapshot.snapshotType.mode, BuildMode.release);
--      expect(genSnapshot.packagesPath, '.packages');
-       expect(genSnapshot.additionalArgs, <String>[
-         '--deterministic',
-         '--snapshot_kind=app-aot-blobs',
-@@ -492,7 +485,6 @@ void main() {
-       expect(genSnapshot.callCount, 1);
-       expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm64);
-       expect(genSnapshot.snapshotType.mode, BuildMode.release);
--      expect(genSnapshot.packagesPath, '.packages');
-       expect(genSnapshot.additionalArgs, <String>[
-         '--deterministic',
-         '--snapshot_kind=app-aot-blobs',
-@@ -581,7 +573,6 @@ void main() {
-       expect(genSnapshot.callCount, 1);
-       expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm);
-       expect(genSnapshot.snapshotType.mode, BuildMode.debug);
--      expect(genSnapshot.packagesPath, '.packages');
-       expect(genSnapshot.additionalArgs, <String>[
-         '--deterministic',
-         '--enable_asserts',
-@@ -622,7 +613,6 @@ void main() {
-       expect(genSnapshot.callCount, 1);
-       expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm64);
-       expect(genSnapshot.snapshotType.mode, BuildMode.debug);
--      expect(genSnapshot.packagesPath, '.packages');
-       expect(genSnapshot.additionalArgs, <String>[
-         '--deterministic',
-         '--enable_asserts',
-@@ -674,7 +664,6 @@ void main() {
-       expect(genSnapshot.callCount, 1);
-       expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm);
-       expect(genSnapshot.snapshotType.mode, BuildMode.profile);
--      expect(genSnapshot.packagesPath, '.packages');
-       expect(genSnapshot.additionalArgs, <String>[
-         '--deterministic',
-         '--snapshot_kind=app-jit',
-@@ -714,7 +703,6 @@ void main() {
-       expect(genSnapshot.callCount, 1);
-       expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm64);
-       expect(genSnapshot.snapshotType.mode, BuildMode.profile);
--      expect(genSnapshot.packagesPath, '.packages');
-       expect(genSnapshot.additionalArgs, <String>[
-         '--deterministic',
-         '--snapshot_kind=app-jit',
-@@ -765,7 +753,6 @@ void main() {
-       expect(genSnapshot.callCount, 1);
-       expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm);
-       expect(genSnapshot.snapshotType.mode, BuildMode.release);
--      expect(genSnapshot.packagesPath, '.packages');
-       expect(genSnapshot.additionalArgs, <String>[
-         '--deterministic',
-         '--snapshot_kind=app-jit',
-@@ -805,7 +792,6 @@ void main() {
-       expect(genSnapshot.callCount, 1);
-       expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm64);
-       expect(genSnapshot.snapshotType.mode, BuildMode.release);
--      expect(genSnapshot.packagesPath, '.packages');
-       expect(genSnapshot.additionalArgs, <String>[
-         '--deterministic',
-         '--snapshot_kind=app-jit',
-@@ -860,7 +846,6 @@ void main() {
-       expect(genSnapshot.callCount, 1);
-       expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm);
-       expect(genSnapshot.snapshotType.mode, BuildMode.release);
--      expect(genSnapshot.packagesPath, '.packages');
-       expect(genSnapshot.additionalArgs, <String>[
-         '--deterministic',
-         '--snapshot_kind=app-jit',
-@@ -917,7 +902,6 @@ void main() {
-       expect(genSnapshot.callCount, 1);
-       expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm);
-       expect(genSnapshot.snapshotType.mode, BuildMode.release);
--      expect(genSnapshot.packagesPath, '.packages');
-       expect(genSnapshot.additionalArgs, <String>[
-         '--deterministic',
-         '--snapshot_kind=app-jit',
diff --git a/tools/patches/flutter-flutter/cad97fe7467c60de645d47acffd0e00cd83178ab.patch b/tools/patches/flutter-flutter/cad97fe7467c60de645d47acffd0e00cd83178ab.patch
new file mode 100644
index 0000000..6cc2a6b
--- /dev/null
+++ b/tools/patches/flutter-flutter/cad97fe7467c60de645d47acffd0e00cd83178ab.patch
@@ -0,0 +1,190 @@
+diff --git a/packages/flutter_tools/lib/src/compile.dart b/packages/flutter_tools/lib/src/compile.dart
+index 12c0770ab..7787bd4ca 100644
+--- a/packages/flutter_tools/lib/src/compile.dart
++++ b/packages/flutter_tools/lib/src/compile.dart
+@@ -57,12 +57,15 @@ class TargetModel {
+ }
+ 
+ class CompilerOutput {
+-  const CompilerOutput(this.outputFilename, this.errorCount);
++  const CompilerOutput(this.outputFilename, this.errorCount, this.sources);
+ 
+   final String outputFilename;
+   final int errorCount;
++  final List<Uri> sources;
+ }
+ 
++enum StdoutState { CollectDiagnostic, CollectDependencies }
++
+ /// Handles stdin/stdout communication with the frontend server.
+ class StdoutHandler {
+   StdoutHandler({this.consumer = printError}) {
+@@ -72,30 +75,54 @@ class StdoutHandler {
+   bool compilerMessageReceived = false;
+   final CompilerMessageConsumer consumer;
+   String boundaryKey;
++  StdoutState state = StdoutState.CollectDiagnostic;
+   Completer<CompilerOutput> compilerOutput;
++  final List<Uri> sources = <Uri>[];
+ 
+   bool _suppressCompilerMessages;
+ 
+   void handler(String message) {
++    printTrace('-> $message');
+     const String kResultPrefix = 'result ';
+     if (boundaryKey == null && message.startsWith(kResultPrefix)) {
+       boundaryKey = message.substring(kResultPrefix.length);
+     } else if (message.startsWith(boundaryKey)) {
+-      if (message.length <= boundaryKey.length) {
+-        compilerOutput.complete(null);
+-        return;
++      if (state == StdoutState.CollectDiagnostic) {
++        state = StdoutState.CollectDependencies;
++      } else {
++        if (message.length <= boundaryKey.length) {
++          compilerOutput.complete(null);
++          return;
++        }
++        final int spaceDelimiter = message.lastIndexOf(' ');
++        compilerOutput.complete(
++            CompilerOutput(
++                message.substring(boundaryKey.length + 1, spaceDelimiter),
++                int.parse(message.substring(spaceDelimiter + 1).trim()),
++                sources));
+       }
+-      final int spaceDelimiter = message.lastIndexOf(' ');
+-      compilerOutput.complete(
+-        CompilerOutput(
+-          message.substring(boundaryKey.length + 1, spaceDelimiter),
+-          int.parse(message.substring(spaceDelimiter + 1).trim())));
+-    } else if (!_suppressCompilerMessages) {
+-      if (compilerMessageReceived == false) {
+-        consumer('\nCompiler message:');
+-        compilerMessageReceived = true;
++    } else {
++      if (state == StdoutState.CollectDiagnostic) {
++        if (!_suppressCompilerMessages) {
++          if (compilerMessageReceived == false) {
++            consumer('\nCompiler message:');
++            compilerMessageReceived = true;
++          }
++          consumer(message);
++        }
++      } else {
++        assert(state == StdoutState.CollectDependencies);
++        switch (message[0]) {
++          case '+':
++            sources.add(Uri.parse(message.substring(1)));
++            break;
++          case '-':
++            sources.remove(Uri.parse(message.substring(1)));
++            break;
++          default:
++            printTrace('Unexpected prefix for $message uri - ignoring');
++        }
+       }
+-      consumer(message);
+     }
+   }
+ 
+@@ -106,6 +133,7 @@ class StdoutHandler {
+     compilerMessageReceived = false;
+     compilerOutput = Completer<CompilerOutput>();
+     _suppressCompilerMessages = suppressCompilerMessages;
++    state = StdoutState.CollectDiagnostic;
+   }
+ }
+ 
+@@ -200,7 +228,7 @@ class KernelCompiler {
+ 
+       if (await fingerprinter.doesFingerprintMatch()) {
+         printTrace('Skipping kernel compilation. Fingerprint match.');
+-        return CompilerOutput(outputFilePath, 0);
++        return CompilerOutput(outputFilePath, 0, /* sources */ null);
+       }
+     }
+ 
+@@ -453,10 +481,13 @@ class ResidentCompiler {
+         ? _mapFilename(request.mainPath, packageUriMapper) + ' '
+         : '';
+     _server.stdin.writeln('recompile $mainUri$inputKey');
++    printTrace('<- recompile $mainUri$inputKey');
+     for (String fileUri in request.invalidatedFiles) {
+       _server.stdin.writeln(_mapFileUri(fileUri, packageUriMapper));
++      printTrace('<- ${_mapFileUri(fileUri, packageUriMapper)}');
+     }
+     _server.stdin.writeln(inputKey);
++    printTrace('<- $inputKey');
+ 
+     return _stdoutHandler.compilerOutput.future;
+   }
+@@ -545,6 +576,7 @@ class ResidentCompiler {
+       .listen((String message) { printError(message); });
+ 
+     _server.stdin.writeln('compile $scriptUri');
++    printTrace('<- compile $scriptUri');
+ 
+     return _stdoutHandler.compilerOutput.future;
+   }
+@@ -597,6 +629,7 @@ class ResidentCompiler {
+   void accept() {
+     if (_compileRequestNeedsConfirmation) {
+       _server.stdin.writeln('accept');
++      printTrace('<- accept');
+     }
+     _compileRequestNeedsConfirmation = false;
+   }
+@@ -620,6 +653,7 @@ class ResidentCompiler {
+     }
+     _stdoutHandler.reset();
+     _server.stdin.writeln('reject');
++    printTrace('<- reject');
+     _compileRequestNeedsConfirmation = false;
+     return _stdoutHandler.compilerOutput.future;
+   }
+@@ -629,6 +663,7 @@ class ResidentCompiler {
+   /// kernel file.
+   void reset() {
+     _server?.stdin?.writeln('reset');
++    printTrace('<- reset');
+   }
+ 
+   String _mapFilename(String filename, PackageUriMapper packageUriMapper) {
+diff --git a/packages/flutter_tools/lib/src/devfs.dart b/packages/flutter_tools/lib/src/devfs.dart
+index 7940e8bb0..9e8b9bd45 100644
+--- a/packages/flutter_tools/lib/src/devfs.dart
++++ b/packages/flutter_tools/lib/src/devfs.dart
+@@ -557,6 +557,8 @@ class DevFS {
+       outputPath:  dillOutputPath ?? getDefaultApplicationKernelPath(trackWidgetCreation: trackWidgetCreation),
+       packagesFilePath : _packagesFilePath,
+     );
++    // list of sources that needs to be monitored are in [compilerOutput.sources]
++    //
+     // Don't send full kernel file that would overwrite what VM already
+     // started loading from.
+     if (!bundleFirstUpload) {
+diff --git a/packages/flutter_tools/test/src/mocks.dart b/packages/flutter_tools/test/src/mocks.dart
+index 52c5fc907..36d63f2d5 100644
+--- a/packages/flutter_tools/test/src/mocks.dart
++++ b/packages/flutter_tools/test/src/mocks.dart
+@@ -496,6 +496,6 @@ class MockResidentCompiler extends BasicMock implements ResidentCompiler {
+   Future<CompilerOutput> recompile(String mainPath, List<String> invalidatedFiles, { String outputPath, String packagesFilePath }) async {
+     fs.file(outputPath).createSync(recursive: true);
+     fs.file(outputPath).writeAsStringSync('compiled_kernel_output');
+-    return CompilerOutput(outputPath, 0);
++    return CompilerOutput(outputPath, 0, <Uri>[]);
+   }
+ }
+diff --git a/packages/flutter_tools/test/tester/flutter_tester_test.dart b/packages/flutter_tools/test/tester/flutter_tester_test.dart
+index a78f70f4f..b6524bd5d 100644
+--- a/packages/flutter_tools/test/tester/flutter_tester_test.dart
++++ b/packages/flutter_tools/test/tester/flutter_tester_test.dart
+@@ -177,7 +177,7 @@ Hello!
+           packagesPath: anyNamed('packagesPath'),
+         )).thenAnswer((_) async {
+           fs.file('$mainPath.dill').createSync(recursive: true);
+-          return CompilerOutput('$mainPath.dill', 0);
++          return CompilerOutput('$mainPath.dill', 0, <Uri>[]);
+         });
+ 
+         final LaunchResult result = await device.startApp(null,
diff --git a/tools/test.dart b/tools/test.dart
index 9842a06..ae5213c 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -205,11 +205,6 @@
         "named configuration $requestedNamedConfiguration");
     return false;
   }
-  if (requestedNamedConfiguration != null && outputNamedConfiguration.isEmpty) {
-    stderr.writeln("error: The named configuration "
-        "$requestedNamedConfiguration doesn't exist");
-    return false;
-  }
   if (requestedNamedConfiguration != null && outputBuilders.isEmpty) {
     stderr.writeln("error: The named configuration "
         "$requestedNamedConfiguration isn't tested on any builders");
@@ -236,9 +231,26 @@
   return LineSplitter.split(result.stdout).first;
 }
 
+/// Exception thrown when looking up the build for a commit failed.
+class CommitNotBuiltException implements Exception {
+  final String reason;
+
+  CommitNotBuiltException(this.reason);
+
+  String toString() => reason;
+}
+
+/// The result after searching for a build of a commit.
+class BuildSearchResult {
+  final int build;
+  final String commit;
+
+  BuildSearchResult(this.build, this.commit);
+}
+
 /// Locates the build number of the [commit] on the [builder], or throws an
 /// exception if the builder hasn't built the commit.
-Future<int> buildNumberOfCommit(String builder, String commit) async {
+Future<BuildSearchResult> searchForBuild(String builder, String commit) async {
   final requestUrl = Uri.parse(
       "https://cr-buildbucket.appspot.com/_ah/api/buildbucket/v1/search"
       "?bucket=luci.dart.ci.sandbox"
@@ -255,7 +267,8 @@
   client.close();
   final builds = object["builds"];
   if (builds == null || builds.isEmpty) {
-    throw new Exception("Builder $builder hasn't built commit $commit");
+    throw new CommitNotBuiltException(
+        "Builder $builder hasn't built commit $commit");
   }
   final build = builds.last;
   final tags = (build["tags"] as List).cast<String>();
@@ -263,9 +276,44 @@
       tags.firstWhere((tag) => tag.startsWith("build_address:"));
   final buildAddress = buildAddressTag.substring("build_address:".length);
   if (build["status"] != "COMPLETED") {
-    throw new Exception("Build $buildAddress isn't completed yet");
+    throw new CommitNotBuiltException(
+        "Build $buildAddress isn't completed yet");
   }
-  return int.parse(buildAddress.split("/").last);
+  return new BuildSearchResult(int.parse(buildAddress.split("/").last), commit);
+}
+
+Future<BuildSearchResult> searchForApproximateBuild(
+    String builder, String commit) async {
+  try {
+    return await searchForBuild(builder, commit);
+  } on CommitNotBuiltException catch (e) {
+    print("Warning: $e, searching for an inexact previous build...");
+    final int limit = 25;
+    final arguments = [
+      "rev-list",
+      "$commit~$limit..$commit~1",
+      "--first-parent",
+      "--topo-order"
+    ];
+    final processResult = await Process.run("git", arguments, runInShell: true);
+    if (processResult.exitCode != 0) {
+      throw new Exception("Failed to list potential commits: git $arguments\n"
+          "exitCode: ${processResult.exitCode}\n"
+          "stdout: ${processResult.stdout}\n"
+          "stdout: ${processResult.stderr}\n");
+    }
+    for (final fallbackCommit in LineSplitter.split(processResult.stdout)) {
+      try {
+        return await searchForBuild(builder, fallbackCommit);
+      } catch (e) {
+        print(
+            "Warning: Searching for inexact baseline build: $e, continuing...");
+      }
+    }
+    throw new CommitNotBuiltException(
+        "Failed to locate approximate baseline results for "
+        "$commit in past $limit commits");
+  }
 }
 
 void main(List<String> args) async {
@@ -277,10 +325,18 @@
       help: "Select the builders building this branch",
       defaultsTo: "master");
   parser.addOption("commit", abbr: "C", help: "Compare with this commit");
+  parser.addFlag("list-configurations",
+      help: "Output list of configurations.", negatable: false);
   parser.addOption("named-configuration",
       abbr: "n",
       help: "The named test configuration that supplies the\nvalues for all "
           "test options, specifying how tests\nshould be run.");
+  parser.addOption("local-configuration",
+      abbr: "N",
+      help: "Use a different named configuration for local\ntesting than the "
+          "named configuration the baseline\nresults were downloaded for. The "
+          "results may be\ninexact if the baseline configuration is "
+          "different.");
   parser.addOption("remote",
       abbr: "R",
       help: "Compare with this remote and git branch",
@@ -289,7 +345,9 @@
 
   final options = parser.parse(args);
   if (options["help"] ||
-      (options["builder"] == null && options["named-configuration"] == null)) {
+      (options["builder"] == null &&
+          options["named-configuration"] == null &&
+          !options["list-configurations"])) {
     print("""
 Usage: test.dart -b [BUILDER] -n [CONFIGURATION] [OPTION]... [--]
                  [TEST.PY OPTION]... [SELECTOR]...
@@ -309,6 +367,14 @@
     return;
   }
 
+  if (options["list-configurations"]) {
+    final process = await Process.start(
+        "python", ["tools/test.py", "--list-configurations"],
+        mode: ProcessStartMode.inheritStdio, runInShell: Platform.isWindows);
+    exitCode = await process.exitCode;
+    return;
+  }
+
   // Locate gsutil.py.
   gsutilPy =
       Platform.script.resolve("../third_party/gsutil/gsutil.py").toFilePath();
@@ -351,9 +417,16 @@
     return;
   }
   final namedConfiguration = namedConfigurations.single;
+  final localConfiguration =
+      options["local-configuration"] ?? namedConfiguration;
   for (final builder in builders) {
-    print("Testing the named configuration $namedConfiguration "
-        "compared with builder $builder");
+    if (localConfiguration != namedConfiguration) {
+      print("Testing the named configuration $localConfiguration "
+          "compared with builder $builder's configuration $namedConfiguration");
+    } else {
+      print("Testing the named configuration $localConfiguration "
+          "compared with builder $builder");
+    }
   }
 
   // Find out where the current HEAD branched.
@@ -368,10 +441,18 @@
     final mergedFlaky = <String, Map<String, dynamic>>{};
 
     // Use the buildbucket API to search for builds of the right commit.
+    final inexactBuilds = new SplayTreeMap<String, String>();
     for (final builder in builders) {
       // Download the previous results and flakiness info from cloud storage.
       print("Finding build on builder $builder to compare with...");
-      final buildNumber = await buildNumberOfCommit(builder, commit);
+      final buildSearchResult =
+          await searchForApproximateBuild(builder, commit);
+      if (buildSearchResult.commit != commit) {
+        print("Warning: Using commit ${buildSearchResult.commit} "
+            "as baseline instead of $commit for $builder");
+        inexactBuilds[builder] = buildSearchResult.commit;
+      }
+      final buildNumber = buildSearchResult.build;
       print("Downloading results from builder $builder build $buildNumber...");
       await cpGsutil(
           buildFileCloudPath(builder, buildNumber.toString(), "results.json"),
@@ -391,16 +472,31 @@
 
     // Write out the merged results for the builders.
     if (2 <= builders.length) {
-      print("Merging downloaded results from the builders...");
       await new File("${outDirectory.path}/previous.json").writeAsString(
           mergedResults.values.map((data) => jsonEncode(data) + "\n").join(""));
       await new File("${outDirectory.path}/flaky.json").writeAsString(
           mergedFlaky.values.map((data) => jsonEncode(data) + "\n").join(""));
     }
 
+    // Override the named configuration in the baseline data if needed.
+    if (namedConfiguration != localConfiguration) {
+      for (final path in [
+        "${outDirectory.path}/previous.json",
+        "${outDirectory.path}/flaky.json"
+      ]) {
+        final results = await loadResultsMap(path);
+        final records = results.values
+            .where((r) => r["configuration"] == namedConfiguration)
+            .toList()
+              ..forEach((r) => r["configuration"] = localConfiguration);
+        await new File(path).writeAsString(
+            records.map((data) => jsonEncode(data) + "\n").join(""));
+      }
+    }
+
     // Run the tests.
     final arguments = [
-      "--named-configuration=$namedConfiguration",
+      "--named-configuration=$localConfiguration",
       "--output-directory=${outDirectory.path}",
       "--clean-exit",
       "--silent-failures",
@@ -438,7 +534,7 @@
       final deflakeDirectory = new Directory("${outDirectory.path}/$i");
       await deflakeDirectory.create();
       final deflakeArguments = <String>[
-        "--named-configuration=$namedConfiguration",
+        "--named-configuration=$localConfiguration",
         "--output-directory=${deflakeDirectory.path}",
         "--clean-exit",
         "--silent-failures",
@@ -483,6 +579,12 @@
     } else {
       stdout.write(compareOutput.stdout);
     }
+    if (inexactBuilds.isNotEmpty) {
+      print("");
+      inexactBuilds.forEach((String builder, String inexactCommit) => print(
+          "Warning: Results may be inexact because commit ${inexactCommit} "
+          "was used as the baseline for $builder instead of $commit"));
+    }
   } finally {
     await outDirectory.delete(recursive: true);
   }
diff --git a/tools/testing/dart/configuration.dart b/tools/testing/dart/configuration.dart
index 89ba917..59399f3a 100644
--- a/tools/testing/dart/configuration.dart
+++ b/tools/testing/dart/configuration.dart
@@ -59,7 +59,6 @@
       this.testDriverErrorPort,
       this.localIP,
       this.keepGeneratedFiles,
-      this.dart2jsOptions,
       this.sharedOptions,
       String packages,
       this.packageRoot,
@@ -117,8 +116,6 @@
   bool get useBlobs => configuration.useBlobs;
   bool get useSdk => configuration.useSdk;
   bool get useEnableAsserts => configuration.enableAsserts;
-  bool get useDart2JSWithKernel => configuration.useDart2JSWithKernel;
-  bool get useDart2JSOldFrontend => configuration.useDart2JSOldFrontEnd;
 
   // Various file paths.
 
@@ -143,7 +140,7 @@
   final bool keepGeneratedFiles;
 
   /// Extra dart2js options passed to the testing script.
-  final List<String> dart2jsOptions;
+  List<String> get dart2jsOptions => configuration.dart2jsOptions;
 
   /// Extra VM options passed to the testing script.
   List<String> get vmOptions => configuration.vmOptions;
@@ -187,9 +184,9 @@
       Compiler.dartkb,
       Compiler.dartkp,
       Compiler.fasta,
+      Compiler.dart2js,
     ];
-    return fastaCompilers.contains(compiler) ||
-        (compiler == Compiler.dart2js && !useDart2JSOldFrontend);
+    return fastaCompilers.contains(compiler);
   }
 
   /// The base directory named for this configuration, like:
@@ -236,19 +233,12 @@
       return const ["--ignore-unrecognized-flags"];
     }
 
-    var args = ['--generate-code-with-compile-time-errors', '--test-mode'];
+    var args = ['--test-mode'];
     if (isChecked) args.add('--enable-checked-mode');
 
-    if (!runtime.isBrowser) {
-      args.add("--allow-mock-compilation");
-      args.add("--categories=all");
-    }
-
     if (isMinified) args.add("--minify");
     if (isCsp) args.add("--csp");
     if (useEnableAsserts) args.add("--enable-asserts");
-    if (useDart2JSWithKernel) args.add("--use-kernel");
-    if (useDart2JSOldFrontend) args.add("--use-old-frontend");
     return args;
   }
 
@@ -446,6 +436,7 @@
         'csp': isCsp,
         'system': system.name,
         'vm_options': vmOptions,
+        'dart2js_options': dart2jsOptions,
         'fasta': usesFasta,
         'use_sdk': useSdk,
         'builder_tag': builderTag,
@@ -453,8 +444,6 @@
         'no_preview_dart_2': noPreviewDart2,
         'use_cfe': useAnalyzerCfe,
         'analyzer_use_fasta_parser': useAnalyzerFastaParser,
-        '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 720c72d..5245977 100644
--- a/tools/testing/dart/environment.dart
+++ b/tools/testing/dart/environment.dart
@@ -21,8 +21,6 @@
   "checked": new _Variable.bool((c) => c.isChecked),
   "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),
   "fasta": new _Variable.bool((c) => c.usesFasta),
   "host_checked": new _Variable.bool((c) => c.isHostChecked),
diff --git a/tools/testing/dart/multitest.dart b/tools/testing/dart/multitest.dart
index 258ed6d..c0c6d7d 100644
--- a/tools/testing/dart/multitest.dart
+++ b/tools/testing/dart/multitest.dart
@@ -201,9 +201,11 @@
       TestUtils.mkdirRecursive(targetDir, importDir);
     }
 
-    // Copy file.
-    futureCopies.add(TestUtils.copyFile(
-        sourceDir.join(importPath), targetDir.join(importPath)));
+    // Copy file. Because some test suites may be read-only, we don't
+    // want to copy the permissions, so we create the copy by writing.
+    final source = File(sourceDir.join(importPath).toNativePath()).openRead();
+    final target = File(targetDir.join(importPath).toNativePath()).openWrite();
+    futureCopies.add(source.pipe(target));
   }
 
   // Wait until all imports are copied before scheduling test cases.
diff --git a/tools/testing/dart/options.dart b/tools/testing/dart/options.dart
index e462b42..cafab24 100644
--- a/tools/testing/dart/options.dart
+++ b/tools/testing/dart/options.dart
@@ -174,13 +174,6 @@
         'Pass the --use-fasta-parser flag to analyzer',
         hide: true),
 
-    // TODO(sigmund): replace dart2js_with_kernel with preview-dart-2.
-    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.',
@@ -219,6 +212,7 @@
     new _Option.bool('no-tree-shake', 'Disable kernel IR tree shaking.',
         hide: true),
     new _Option.bool('list', 'List tests only, do not run them.'),
+    new _Option.bool('list-configurations', 'Output list of configurations.'),
     new _Option.bool('list_status_files',
         'List status files for test-suites. Do not run any test suites.',
         hide: true),
@@ -383,6 +377,17 @@
           verbose: arguments.contains("--verbose") || arguments.contains("-v"));
       return null;
     }
+    if (arguments.contains("--list-configurations")) {
+      final testMatrixFile = "tools/bots/test_matrix.json";
+      TestMatrix testMatrix = TestMatrix.fromPath(testMatrixFile);
+      for (final configuration in testMatrix.configurations
+          .map((configuration) => configuration.name)
+          .toList()
+            ..sort()) {
+        print(configuration);
+      }
+      return null;
+    }
     // Dart1 mode has been deprecated.
     if (arguments.contains("--no-preview-dart-2")) {
       return null;
@@ -683,8 +688,6 @@
                         data["analyzer_use_fasta_parser"] as bool,
                     useBlobs: data["use_blobs"] as bool,
                     useSdk: data["use_sdk"] as bool,
-                    useDart2JSWithKernel: data["dart2js_with_kernel"] as bool,
-                    useDart2JSOldFrontEnd: data["dart2js_old_frontend"] as bool,
                     useHotReload: data["hot_reload"] as bool,
                     useHotReloadRollback: data["hot_reload_rollback"] as bool,
                     isChecked: data["checked"] as bool,
@@ -692,6 +695,7 @@
                     isCsp: data["csp"] as bool,
                     isMinified: data["minified"] as bool,
                     vmOptions: vmOptions,
+                    dart2jsOptions: dart2jsOptions,
                     builderTag: data["builder_tag"] as String,
                     previewDart2: true);
             var configuration = new TestConfiguration(
@@ -734,7 +738,6 @@
                     data['test_server_cross_origin_port'] as int,
                 testDriverErrorPort: data["test_driver_error_port"] as int,
                 localIP: data["local_ip"] as String,
-                dart2jsOptions: dart2jsOptions,
                 sharedOptions: sharedOptions,
                 packages: data["packages"] as String,
                 packageRoot: data["package_root"] as String,
diff --git a/tools/utils.py b/tools/utils.py
index a6db548..a3657f2 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -880,11 +880,11 @@
         missing.append(crash)
     if self._output_directory is not None and self._is_shard():
       print (
-          "INFO: Copying collected dumps and binaries into output directory\n"
+          "INFO: Moving collected dumps and binaries into output directory\n"
           "INFO: They will be uploaded to isolate server. Look for \"isolated"
           " out\" under the failed step on the build page.\n"
           "INFO: For more information see runtime/docs/infra/coredumps.md")
-      self._copy(files)
+      self._move(files)
     else:
       print (
           "INFO: Uploading collected dumps and binaries into Cloud Storage\n"
@@ -910,13 +910,7 @@
     if throw:
       raise Exception('Missing crash dumps for: %s' % missing_as_string)
 
-  def _copy(self, files):
-    for file in files:
-      tarname = self._tar(file)
-      print '+++ Copying %s to output_directory (%s)' % (tarname, self._output_directory)
-      shutil.copy(tarname, self._output_directory)
-
-  def _tar(self, file):
+  def _get_file_name(self, file):
     # Sanitize the name: actual cores follow 'core.%d' pattern, crashed
     # binaries are copied next to cores and named
     # 'binary.<mode>_<arch>_<binary_name>'.
@@ -927,7 +921,21 @@
     if is_binary:
       (mode, arch, binary_name) = suffix.split('_', 2)
       name = binary_name
+    return (name, is_binary)
 
+  def _move(self, files):
+    for file in files:
+      print '+++ Moving %s to output_directory (%s)' % (file, self._output_directory)
+      (name, is_binary) = self._get_file_name(file)
+      destination = os.path.join(self._output_directory, name)
+      shutil.move(file, destination)
+      if is_binary and os.path.exists(file + '.pdb'):
+        # Also move a PDB file if there is one.
+        pdb = os.path.join(self._output_directory, name + '.pdb')
+        shutil.move(file + '.pdb', pdb)
+
+  def _tar(self, file):
+    (name, is_binary) = self._get_file_name(file)
     tarname = '%s.tar.gz' % name
 
     # Compress the file.
diff --git a/utils/bazel/kernel_worker.dart b/utils/bazel/kernel_worker.dart
index a9a0145..86a2eb8 100644
--- a/utils/bazel/kernel_worker.dart
+++ b/utils/bazel/kernel_worker.dart
@@ -15,10 +15,12 @@
 import 'package:args/args.dart';
 import 'package:bazel_worker/bazel_worker.dart';
 import 'package:build_integration/file_system/multi_root.dart';
+import 'package:dev_compiler/src/kernel/target.dart';
 import 'package:front_end/src/api_unstable/bazel_worker.dart' as fe;
 import 'package:kernel/ast.dart' show Component, Library;
 import 'package:kernel/target/targets.dart';
 import 'package:vm/target/vm.dart';
+import 'package:compiler/src/kernel/dart2js_target.dart';
 
 main(List<String> args) async {
   args = preprocessArgs(args);
@@ -83,7 +85,7 @@
 
 /// An [ArgParser] for generating kernel summaries.
 final summaryArgsParser = new ArgParser()
-  ..addFlag('help', negatable: false)
+  ..addFlag('help', negatable: false, abbr: 'h')
   ..addFlag('exclude-non-sources',
       negatable: false,
       help: 'Whether source files loaded implicitly should be included as '
@@ -92,11 +94,15 @@
       defaultsTo: true,
       negatable: true,
       help: 'Whether to only build summary files.')
+  ..addOption('target',
+      allowed: const ['vm', 'dart2js', 'devcompiler'],
+      help: 'Build kernel for the vm, dart2js, or devcompiler')
   ..addOption('dart-sdk-summary')
   ..addMultiOption('input-summary')
   ..addMultiOption('input-linked')
   ..addMultiOption('multi-root')
   ..addOption('multi-root-scheme', defaultsTo: 'org-dartlang-multi-root')
+  ..addOption('libraries-file')
   ..addOption('packages-file')
   ..addMultiOption('source')
   ..addOption('output');
@@ -128,20 +134,54 @@
   if (multiRoots.isEmpty) multiRoots.add(Uri.base);
   var fileSystem = new MultiRootFileSystem(parsedArgs['multi-root-scheme'],
       multiRoots, fe.StandardFileSystem.instance);
-  var sources = (parsedArgs['source'] as List<String>).map(Uri.parse).toList();
-  Target target;
-  var summaryOnly = parsedArgs['summary-only'] as bool;
+  var sources =
+      (parsedArgs['source'] as List<String>).map(Uri.base.resolve).toList();
   var excludeNonSources = parsedArgs['exclude-non-sources'] as bool;
+
+  var summaryOnly = parsedArgs['summary-only'] as bool;
+  // TODO(sigmund,jakemac): make target mandatory. We allow null to be backwards
+  // compatible while we migrate existing clients of this tool.
+  var targetName =
+      (parsedArgs['target'] as String) ?? (summaryOnly ? 'devcompiler' : 'vm');
   var targetFlags = new TargetFlags();
-  if (summaryOnly) {
-    target = new SummaryTarget(sources, excludeNonSources, targetFlags);
-  } else {
-    target = new VmTarget(targetFlags);
+  Target target;
+  switch (targetName) {
+    case 'vm':
+      target = new VmTarget(targetFlags);
+      if (summaryOnly) {
+        out.writeln('error: --summary-only not supported for the vm target');
+      }
+      break;
+    case 'dart2js':
+      target = new Dart2jsTarget('dart2js', targetFlags);
+      if (summaryOnly) {
+        out.writeln(
+            'error: --summary-only not supported for the dart2js target');
+      }
+      break;
+    case 'devcompiler':
+      // TODO(jakemac):If `generateKernel` changes to return a summary
+      // component, process the component instead.
+      target = new DevCompilerSummaryTarget(sources, excludeNonSources);
+      if (!summaryOnly) {
+        out.writeln('error: --no-summary-only not supported for the '
+            'devcompiler target');
+      }
+      break;
+    default:
+      out.writeln('error: unsupported target: $targetName');
   }
+
+  // TODO(sigmund,jakemac): make it mandatory. We allow null while we migrate
+  // existing clients of this tool.
+  var librariesSpec = parsedArgs['libraries-file'] == null
+      ? null
+      : Uri.base.resolve(parsedArgs['libraries-file']);
   var state = await fe.initializeCompiler(
       // TODO(sigmund): pass an old state once we can make use of it.
       null,
       Uri.base.resolve(parsedArgs['dart-sdk-summary']),
+      librariesSpec,
       Uri.base.resolve(parsedArgs['packages-file']),
       (parsedArgs['input-summary'] as List<String>)
           .map(Uri.base.resolve)
@@ -171,8 +211,8 @@
   return succeeded;
 }
 
-/// A target that transforms outlines to meet the requirements of summaries in
-/// bazel and package-build.
+/// Extends the DevCompilerTarget to transform outlines to meet the requirements
+/// of summaries in bazel and package-build.
 ///
 /// Build systems like package-build may provide the same input file twice to
 /// the summary worker, but only intends to have it in one output summary.  The
@@ -183,15 +223,15 @@
 ///
 /// Note: this transformation is destructive and is only intended to be used
 /// when generating summaries.
-class SummaryTarget extends NoneTarget {
+class DevCompilerSummaryTarget extends DevCompilerTarget {
   final List<Uri> sources;
   final bool excludeNonSources;
 
-  SummaryTarget(this.sources, this.excludeNonSources, TargetFlags flags)
-      : super(flags);
+  DevCompilerSummaryTarget(this.sources, this.excludeNonSources);
 
   @override
   void performOutlineTransformations(Component component) {
+    super.performOutlineTransformations(component);
     if (!excludeNonSources) return;
 
     List<Library> libraries = new List.from(component.libraries);