Version 2.0.0-dev.50.0

Merge commit '9eb09d825b1bb0dc4312e8c7fe16bbdf1a7f567c' into dev
diff --git a/BUILD.gn b/BUILD.gn
index b2dc62f..6d24c82 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -80,7 +80,7 @@
 }
 
 group("create_sdk") {
-  deps = [
+  public_deps = [
     "sdk:create_sdk",
   ]
 }
diff --git a/CHANGELOG.md b/CHANGELOG.md
index de609346..83e13f6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,5 @@
+## 2.0.0-dev.50.0
+
 ## 2.0.0-dev.49.0
 
 ### Tool Changes
@@ -11,6 +13,28 @@
 
 ## 2.0.0-dev.48.0
 
+### Language
+
+#### Strong Mode
+
+### Core library changes
+
+### Dart VM
+
+### Tool Changes
+
+#### Pub
+
+#### Other Tools
+
+## 2.0.0-dev.49.0
+
+## 2.0.0-dev.47.0
+
+### Tool Changes
+
+## 2.0.0-dev.48.0
+
 ### Core library changes
 
 * `dart:core`
diff --git a/DEPS b/DEPS
index 4ba2514..163bf8d 100644
--- a/DEPS
+++ b/DEPS
@@ -98,7 +98,7 @@
   "intl_tag": "@0.15.2",
   "jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "@2.0.6",
-  "linter_tag": "@0.1.48",
+  "linter_tag": "@0.1.49",
   "logging_tag": "@0.11.3+1",
   "markdown_tag": "@1.1.1",
   "matcher_tag": "@0.12.1+4",
diff --git a/build/config/sysroot.gni b/build/config/sysroot.gni
index ddee618..b1acdf6 100644
--- a/build/config/sysroot.gni
+++ b/build/config/sysroot.gni
@@ -16,17 +16,17 @@
 
 if (is_linux && dart_use_wheezy_sysroot) {
   if (current_cpu == "x86") {
-    target_sysroot = rebase_path("//build/linux/debian_wheezy_i386-sysroot")
+    target_sysroot = rebase_path("//build/linux/debian_wheezy_i386-sysroot", root_build_dir)
   } else if (current_cpu == "x64") {
     if (is_asan || is_lsan || is_msan || is_tsan) {
-      target_sysroot = rebase_path("//build/linux/debian_jessie_amd64-sysroot")
+      target_sysroot = rebase_path("//build/linux/debian_jessie_amd64-sysroot", root_build_dir)
     } else {
-      target_sysroot = rebase_path("//build/linux/debian_wheezy_amd64-sysroot")
+      target_sysroot = rebase_path("//build/linux/debian_wheezy_amd64-sysroot", root_build_dir)
     }
   } else if (current_cpu == "arm") {
-    target_sysroot = rebase_path("//build/linux/debian_wheezy_arm-sysroot")
+    target_sysroot = rebase_path("//build/linux/debian_wheezy_arm-sysroot", root_build_dir)
   } else if (current_cpu == "arm64") {
-    target_sysroot = rebase_path("//build/linux/debian_jessie_arm64-sysroot")
+    target_sysroot = rebase_path("//build/linux/debian_jessie_arm64-sysroot", root_build_dir)
   } else {
     print("There is no Debian wheezy sysroot present for $current_cpu")
     assert(false)
@@ -38,13 +38,13 @@
 } else if (is_android) {
   import("//build/config/android/config.gni")
   if (current_cpu == "x86") {
-    sysroot = rebase_path("$android_ndk_root/$x86_android_sysroot_subdir")
+    sysroot = rebase_path("$android_ndk_root/$x86_android_sysroot_subdir", root_build_dir)
   } else if (current_cpu == "arm") {
-    sysroot = rebase_path("$android_ndk_root/$arm_android_sysroot_subdir")
+    sysroot = rebase_path("$android_ndk_root/$arm_android_sysroot_subdir", root_build_dir)
   } else if (current_cpu == "x64") {
-    sysroot = rebase_path("$android_ndk_root/$x86_64_android_sysroot_subdir")
+    sysroot = rebase_path("$android_ndk_root/$x86_64_android_sysroot_subdir", root_build_dir)
   } else if (current_cpu == "arm64") {
-    sysroot = rebase_path("$android_ndk_root/$arm64_android_sysroot_subdir")
+    sysroot = rebase_path("$android_ndk_root/$arm64_android_sysroot_subdir", root_build_dir)
   } else {
     sysroot = ""
   }
diff --git a/pkg/analysis_server/benchmark/perf/flutter_analyze_benchmark.dart b/pkg/analysis_server/benchmark/perf/flutter_analyze_benchmark.dart
index 620c032..90fab47 100644
--- a/pkg/analysis_server/benchmark/perf/flutter_analyze_benchmark.dart
+++ b/pkg/analysis_server/benchmark/perf/flutter_analyze_benchmark.dart
@@ -70,6 +70,9 @@
       deleteServerCache();
     }
 
+    final String dartSdkPath =
+        path.dirname(path.dirname(Platform.resolvedExecutable));
+
     final Stopwatch stopwatch = new Stopwatch()..start();
 
     await _runProcess(
@@ -78,6 +81,8 @@
         'packages/flutter_tools/bin/flutter_tools.dart',
         'analyze',
         '--flutter-repo',
+        '--dart-sdk',
+        dartSdkPath,
       ],
       cwd: flutterDir.path,
       failOnError: false,
diff --git a/pkg/analysis_server/lib/plugin/edit/assist/assist_core.dart b/pkg/analysis_server/lib/plugin/edit/assist/assist_core.dart
index 1265b6b..06bbf6b 100644
--- a/pkg/analysis_server/lib/plugin/edit/assist/assist_core.dart
+++ b/pkg/analysis_server/lib/plugin/edit/assist/assist_core.dart
@@ -2,10 +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 'dart:async';
-
-import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     show SourceChange;
 import 'package:analyzer_plugin/utilities/assist/assist.dart';
@@ -17,11 +13,6 @@
  */
 class Assist {
   /**
-   * An empty list of assists.
-   */
-  static const List<Assist> EMPTY_LIST = const <Assist>[];
-
-  /**
    * A comparator that can be used to sort assists by their relevance. The most
    * relevant assists will be sorted before assists with a lower relevance.
    * Assists with the same relevance are sorted alphabetically.
@@ -53,42 +44,3 @@
     return 'Assist(kind=$kind, change=$change)';
   }
 }
-
-/**
- * An object used to provide context information for [AssistContributor]s.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class AssistContext {
-  /**
-   * The analysis driver used to access analysis results.
-   */
-  AnalysisDriver get analysisDriver;
-
-  /**
-   * The length of the selection.
-   */
-  int get selectionLength;
-
-  /**
-   * The start of the selection.
-   */
-  int get selectionOffset;
-
-  /**
-   * The source to get assists in.
-   */
-  Source get source;
-}
-
-/**
- * An object used to produce assists for a specific location.
- *
- * Clients may implement this class when implementing plugins.
- */
-abstract class AssistContributor {
-  /**
-   * Completes with a list of assists for the given [context].
-   */
-  Future<List<Assist>> computeAssists(AssistContext context);
-}
diff --git a/pkg/analysis_server/lib/plugin/edit/assist/assist_dart.dart b/pkg/analysis_server/lib/plugin/edit/assist/assist_dart.dart
index 44198cd..6e7020e 100644
--- a/pkg/analysis_server/lib/plugin/edit/assist/assist_dart.dart
+++ b/pkg/analysis_server/lib/plugin/edit/assist/assist_dart.dart
@@ -2,18 +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.
 
-import 'dart:async';
-
-import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/dart/element/ast_provider.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 
 /**
- * An object used to provide context information for [DartAssistContributor]s.
+ * An object used to provide context information for Dart assist contributors.
  *
  * Clients may not extend, implement or mix-in this class.
  */
@@ -24,11 +18,6 @@
   AnalysisDriver get analysisDriver;
 
   /**
-   * The provider for parsed or resolved ASTs.
-   */
-  AstProvider get astProvider;
-
-  /**
    * The length of the selection.
    */
   int get selectionLength;
@@ -48,60 +37,3 @@
    */
   CompilationUnit get unit;
 }
-
-/**
- * An [AssistContributor] that can be used to contribute assists for Dart files.
- *
- * Clients may extend this class when implementing plugins.
- */
-abstract class DartAssistContributor implements AssistContributor {
-  @override
-  Future<List<Assist>> computeAssists(AssistContext context) async {
-    AnalysisDriver driver = context.analysisDriver;
-    Source source = context.source;
-    if (!AnalysisEngine.isDartFileName(source.fullName)) {
-      return Assist.EMPTY_LIST;
-    }
-    CompilationUnit unit = (await driver.getResult(source.fullName)).unit;
-    if (unit == null) {
-      return Assist.EMPTY_LIST;
-    }
-    DartAssistContext dartContext = new _DartAssistContextImpl(
-        new AstProviderForDriver(driver), context, unit);
-    return internalComputeAssists(dartContext);
-  }
-
-  /**
-   * Completes with a list of assists for the given [context].
-   */
-  Future<List<Assist>> internalComputeAssists(DartAssistContext context);
-}
-
-/**
- * The implementation of [DartAssistContext].
- *
- * Clients may not extend, implement or mix-in this class.
- */
-class _DartAssistContextImpl implements DartAssistContext {
-  @override
-  final AstProvider astProvider;
-
-  final AssistContext _context;
-
-  @override
-  final CompilationUnit unit;
-
-  _DartAssistContextImpl(this.astProvider, this._context, this.unit);
-
-  @override
-  AnalysisDriver get analysisDriver => _context.analysisDriver;
-
-  @override
-  int get selectionLength => _context.selectionLength;
-
-  @override
-  int get selectionOffset => _context.selectionOffset;
-
-  @override
-  Source get source => _context.source;
-}
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 9b4578e..1e6b8d0 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -49,7 +49,6 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/context/context_root.dart';
 import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart';
@@ -63,6 +62,7 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
+import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:analyzer/src/source/pub_package_map_provider.dart';
 import 'package:analyzer/src/util/glob.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
@@ -294,7 +294,7 @@
    * The controller for [onAnalysisSetChanged].
    */
   StreamController _onAnalysisSetChangedController =
-      new StreamController.broadcast();
+      new StreamController.broadcast(sync: true);
 
   /**
    * This exists as a temporary stopgap for plugins, until the official plugin
@@ -774,7 +774,8 @@
    * This means that it is absolute and normalized.
    */
   bool isValidFilePath(String path) {
-    return resourceProvider.absolutePathContext.isValid(path);
+    return resourceProvider.pathContext.isAbsolute(path) &&
+        resourceProvider.pathContext.normalize(path) == path;
   }
 
   /**
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index a1ad9b6..e949c17 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -11,27 +11,27 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/plugin/resolver_provider.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/context/context_root.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/java_io.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:analyzer/src/pubspec/pubspec_validator.dart';
 import 'package:analyzer/src/source/package_map_provider.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer/src/source/path_filter.dart';
 import 'package:analyzer/src/source/pub_package_map_provider.dart';
 import 'package:analyzer/src/source/sdk_ext.dart';
 import 'package:analyzer/src/task/options.dart';
-import 'package:analyzer/src/util/absolute_path.dart';
 import 'package:analyzer/src/util/glob.dart';
 import 'package:analyzer/src/util/yaml.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol;
@@ -441,13 +441,6 @@
   final DartSdkManager sdkManager;
 
   /**
-   * The context used to work with absolute file system paths.
-   *
-   * TODO(scheglov) remove [pathContext].
-   */
-  AbsolutePathContext absolutePathContext;
-
-  /**
    * The context used to work with file system paths.
    */
   pathos.Context pathContext;
@@ -532,7 +525,6 @@
       this.analyzedFilesGlobs,
       this._instrumentationService,
       this.defaultContextOptions) {
-    absolutePathContext = resourceProvider.absolutePathContext;
     pathContext = resourceProvider.pathContext;
   }
 
@@ -953,7 +945,7 @@
       String path, ContextInfo info, Folder folder) {
     // Check to see if this is the .packages file for this context and if so,
     // update the context's source factory.
-    if (absolutePathContext.basename(path) == PACKAGE_SPEC_NAME) {
+    if (pathContext.basename(path) == PACKAGE_SPEC_NAME) {
       String contextRoot = info.folder.path;
       ContextBuilder builder =
           callbacks.createContextBuilder(info.folder, defaultContextOptions);
@@ -1052,8 +1044,7 @@
       callbacks.computingPackageMap(true);
       try {
         // Try .packages first.
-        if (absolutePathContext.basename(packagespecFile.path) ==
-            PACKAGE_SPEC_NAME) {
+        if (pathContext.basename(packagespecFile.path) == PACKAGE_SPEC_NAME) {
           Packages packages = _readPackagespec(packagespecFile);
           return new PackagesFileDisposition(packages);
         }
@@ -1384,7 +1375,7 @@
       case ChangeType.ADD:
         Resource resource = resourceProvider.getResource(path);
 
-        String directoryPath = absolutePathContext.dirname(path);
+        String directoryPath = pathContext.dirname(path);
 
         // Check to see if we need to create a new context.
         if (info.isTopLevel) {
@@ -1394,8 +1385,7 @@
             if (_isPubspec(path)) {
               // Check for a sibling .packages file.
               if (!resourceProvider
-                  .getFile(absolutePathContext.append(
-                      directoryPath, PACKAGE_SPEC_NAME))
+                  .getFile(pathContext.join(directoryPath, PACKAGE_SPEC_NAME))
                   .exists) {
                 _extractContext(info, resource);
                 return;
@@ -1404,8 +1394,7 @@
             if (_isPackagespec(path)) {
               // Check for a sibling pubspec.yaml file.
               if (!resourceProvider
-                  .getFile(
-                      absolutePathContext.append(directoryPath, PUBSPEC_NAME))
+                  .getFile(pathContext.join(directoryPath, PUBSPEC_NAME))
                   .exists) {
                 _extractContext(info, resource);
                 return;
@@ -1429,15 +1418,14 @@
         // Note that it's important to verify that there is NEITHER a .packages nor a
         // lingering pubspec.yaml before merging.
         if (!info.isTopLevel) {
-          String directoryPath = absolutePathContext.dirname(path);
+          String directoryPath = pathContext.dirname(path);
 
           // Only merge if this is the same directory described by our info object.
           if (info.folder.path == directoryPath) {
             if (_isPubspec(path)) {
               // Check for a sibling .packages file.
               if (!resourceProvider
-                  .getFile(absolutePathContext.append(
-                      directoryPath, PACKAGE_SPEC_NAME))
+                  .getFile(pathContext.join(directoryPath, PACKAGE_SPEC_NAME))
                   .exists) {
                 _mergeContext(info);
                 return;
@@ -1446,8 +1434,7 @@
             if (_isPackagespec(path)) {
               // Check for a sibling pubspec.yaml file.
               if (!resourceProvider
-                  .getFile(
-                      absolutePathContext.append(directoryPath, PUBSPEC_NAME))
+                  .getFile(pathContext.join(directoryPath, PUBSPEC_NAME))
                   .exists) {
                 _mergeContext(info);
                 return;
@@ -1479,16 +1466,14 @@
    * context root [root], contains a folder whose name starts with '.'.
    */
   bool _isContainedInDotFolder(String root, String path) {
-    String pathDir = absolutePathContext.dirname(path);
-    String suffixPath = absolutePathContext.suffix(root, pathDir);
-    if (suffixPath == null) {
-      return false;
-    }
-    for (String pathComponent in absolutePathContext.split(suffixPath)) {
-      if (pathComponent.startsWith('.') &&
-          pathComponent != '.' &&
-          pathComponent != '..') {
-        return true;
+    String pathDir = pathContext.dirname(path);
+    String rootPrefix = root + pathContext.separator;
+    if (pathDir.startsWith(rootPrefix)) {
+      String suffixPath = pathDir.substring(rootPrefix.length);
+      for (String pathComponent in pathContext.split(suffixPath)) {
+        if (pathComponent.startsWith('.')) {
+          return true;
+        }
       }
     }
     return false;
@@ -1504,7 +1489,7 @@
    */
   bool _isExcludedBy(List<String> excludedPaths, String path) {
     return excludedPaths.any((excludedPath) {
-      if (absolutePathContext.isWithin(excludedPath, path)) {
+      if (pathContext.isWithin(excludedPath, path)) {
         return true;
       }
       return path == excludedPath;
@@ -1516,19 +1501,19 @@
    * context root [root].
    */
   bool _isInTopLevelDocDir(String root, String path) {
-    String suffixPath = absolutePathContext.suffix(root, path);
-    if (suffixPath == null) {
-      return false;
+    String rootPrefix = root + pathContext.separator;
+    if (path.startsWith(rootPrefix)) {
+      String suffix = path.substring(rootPrefix.length);
+      return suffix == DOC_DIR_NAME ||
+          suffix.startsWith(DOC_DIR_NAME + pathContext.separator);
     }
-    return suffixPath == DOC_DIR_NAME ||
-        suffixPath.startsWith(DOC_DIR_NAME + absolutePathContext.separator);
+    return false;
   }
 
   bool _isPackagespec(String path) =>
-      absolutePathContext.basename(path) == PACKAGE_SPEC_NAME;
+      pathContext.basename(path) == PACKAGE_SPEC_NAME;
 
-  bool _isPubspec(String path) =>
-      absolutePathContext.basename(path) == PUBSPEC_NAME;
+  bool _isPubspec(String path) => pathContext.basename(path) == PUBSPEC_NAME;
 
   /**
    * Merges [info] context into its parent.
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 22b7f36..77fd41b 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -169,12 +169,7 @@
       CompilationUnitElement compilationUnitElement =
           resolutionMap.elementDeclaredByCompilationUnit(unit);
       DartAssistContext dartAssistContext = new _DartAssistContextForValues(
-          compilationUnitElement.source,
-          offset,
-          length,
-          driver,
-          new AstProviderForDriver(driver),
-          unit);
+          compilationUnitElement.source, offset, length, driver, unit);
       try {
         AssistProcessor processor = new AssistProcessor(dartAssistContext);
         List<Assist> assists = await processor.compute();
@@ -652,13 +647,10 @@
   final AnalysisDriver analysisDriver;
 
   @override
-  final AstProvider astProvider;
-
-  @override
   final CompilationUnit unit;
 
   _DartAssistContextForValues(this.source, this.selectionOffset,
-      this.selectionLength, this.analysisDriver, this.astProvider, this.unit);
+      this.selectionLength, this.analysisDriver, this.unit);
 }
 
 /**
diff --git a/pkg/analysis_server/lib/src/plugin/plugin_watcher.dart b/pkg/analysis_server/lib/src/plugin/plugin_watcher.dart
index 5d050de..6a96170 100644
--- a/pkg/analysis_server/lib/src/plugin/plugin_watcher.dart
+++ b/pkg/analysis_server/lib/src/plugin/plugin_watcher.dart
@@ -7,7 +7,6 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/context_root.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/util/absolute_path.dart';
 import 'package:front_end/src/base/source.dart';
 import 'package:path/src/context.dart';
 
@@ -99,10 +98,9 @@
    * [driver].
    */
   String _getSdkPath(AnalysisDriver driver) {
-    AbsolutePathContext context = resourceProvider.absolutePathContext;
     String sdkRoot = driver.sourceFactory.forUri('dart:core').fullName;
-    while (context.basename(sdkRoot) != 'lib') {
-      String parent = context.dirname(sdkRoot);
+    while (resourceProvider.pathContext.basename(sdkRoot) != 'lib') {
+      String parent = resourceProvider.pathContext.dirname(sdkRoot);
       if (parent == sdkRoot) {
         break;
       }
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 8ae5367..e111a67 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -17,11 +17,11 @@
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/instrumentation/file_instrumentation.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
+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';
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index 8902596..7767e39 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -2,37 +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.
 
-import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/utilities/assist/assist.dart';
 
 /**
- * The implementation of [AssistContext].
- */
-class AssistContextImpl implements AssistContext {
-  @override
-  final AnalysisDriver analysisDriver;
-
-  @override
-  final Source source;
-
-  @override
-  final int selectionOffset;
-
-  @override
-  final int selectionLength;
-
-  AssistContextImpl(this.analysisDriver, this.source, this.selectionOffset,
-      this.selectionLength);
-}
-
-/**
  * An enumeration of possible assist kinds.
  */
 class DartAssistKind {
-  static const ADD_PART_DIRECTIVE = const AssistKind(
-      'dart.assist.addPartDirective', 30, "Add 'part' directive");
   static const ADD_TYPE_ANNOTATION = const AssistKind(
       'dart.assist.addTypeAnnotation', 30, "Add type annotation");
   static const ASSIGN_TO_LOCAL_VARIABLE = const AssistKind(
@@ -87,8 +62,6 @@
       const AssistKind('dart.assist.encapsulateField', 30, "Encapsulate field");
   static const EXCHANGE_OPERANDS =
       const AssistKind('dart.assist.exchangeOperands', 30, "Exchange operands");
-  static const EXTRACT_CLASS = const AssistKind(
-      'dart.assist.extractClass', 30, "Extract class into file '{0}'");
   static const FLUTTER_CONVERT_TO_CHILDREN = const AssistKind(
       'dart.assist.flutter.convert.childToChildren',
       30,
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 d7b5b78..d9ae917 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -64,8 +64,6 @@
   CompilationUnitElement unitElement;
 
   LibraryElement unitLibraryElement;
-  String unitLibraryFile;
-  String unitLibraryFolder;
 
   int selectionOffset;
   int selectionLength;
@@ -93,8 +91,6 @@
     unitLibraryElement = resolutionMap
         .elementDeclaredByCompilationUnit(dartContext.unit)
         .library;
-    unitLibraryFile = unitLibraryElement.source.fullName;
-    unitLibraryFolder = dirname(unitLibraryFile);
     // selection
     selectionOffset = dartContext.selectionOffset;
     selectionLength = dartContext.selectionLength;
@@ -1237,17 +1233,39 @@
           }
         }
       }
-      // add accessors
-      String eol2 = eol + eol;
-      String typeNameCode = variableList.type != null
-          ? _getNodeText(variableList.type) + ' '
-          : '';
-      String getterCode = '$eol2  ${typeNameCode}get $name => _$name;';
-      String setterCode = '$eol2'
-          '  void set $name($typeNameCode$name) {$eol'
-          '    _$name = $name;$eol'
-          '  }';
-      builder.addSimpleInsertion(fieldDeclaration.end, getterCode + setterCode);
+
+      // Write getter and setter.
+      builder.addInsertion(fieldDeclaration.end, (builder) {
+        String docCode;
+        if (fieldDeclaration.documentationComment != null) {
+          docCode = utils.getNodeText(fieldDeclaration.documentationComment);
+        }
+
+        String typeCode = '';
+        if (variableList.type != null) {
+          typeCode = _getNodeText(variableList.type) + ' ';
+        }
+
+        // Write getter.
+        builder.writeln();
+        builder.writeln();
+        if (docCode != null) {
+          builder.write('  ');
+          builder.writeln(docCode);
+        }
+        builder.write('  ${typeCode}get $name => _$name;');
+
+        // Write setter.
+        builder.writeln();
+        builder.writeln();
+        if (docCode != null) {
+          builder.write('  ');
+          builder.writeln(docCode);
+        }
+        builder.writeln('  set $name($typeCode$name) {');
+        builder.writeln('    _$name = $name;');
+        builder.write('  }');
+      });
     });
     _addAssistFromBuilder(changeBuilder, DartAssistKind.ENCAPSULATE_FIELD);
   }
@@ -3132,21 +3150,6 @@
   }
 }
 
-/**
- * An [AssistContributor] that provides the default set of assists.
- */
-class DefaultAssistContributor extends DartAssistContributor {
-  @override
-  Future<List<Assist>> internalComputeAssists(DartAssistContext context) async {
-    try {
-      AssistProcessor processor = new AssistProcessor(context);
-      return processor.compute();
-    } on CancelCorrectionException {
-      return Assist.EMPTY_LIST;
-    }
-  }
-}
-
 class _SimpleIdentifierRecursiveAstVisitor extends RecursiveAstVisitor {
   final _SimpleIdentifierVisitor visitor;
 
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 3cdcf21..869f385 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -2393,7 +2393,7 @@
     final thisExpression = node is ThisExpression
         ? node
         : node.getAncestor((node) => node is ThisExpression);
-    final parent = thisExpression.parent;
+    final parent = thisExpression?.parent;
     if (parent is PropertyAccess) {
       DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
       await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
diff --git a/pkg/analysis_server/lib/src/socket_server.dart b/pkg/analysis_server/lib/src/socket_server.dart
index d138f3e..f64cecb 100644
--- a/pkg/analysis_server/lib/src/socket_server.dart
+++ b/pkg/analysis_server/lib/src/socket_server.dart
@@ -9,8 +9,8 @@
 import 'package:analysis_server/src/server/diagnostic_server.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:analyzer/src/source/pub_package_map_provider.dart';
 
 /**
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index b3050c4..ac435fd 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -22,7 +22,6 @@
 import 'package:analysis_server/src/utilities/profiling.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/context_root.dart';
 import 'package:analyzer/src/context/source.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
@@ -35,6 +34,7 @@
 import 'package:analyzer/src/lint/linter.dart';
 import 'package:analyzer/src/lint/registry.dart';
 import 'package:analyzer/src/services/lint.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer/src/source/sdk_ext.dart';
 import 'package:path/path.dart' as pathPackage;
 
diff --git a/pkg/analysis_server/lib/starter.dart b/pkg/analysis_server/lib/starter.dart
index cca06da..5059a59 100644
--- a/pkg/analysis_server/lib/starter.dart
+++ b/pkg/analysis_server/lib/starter.dart
@@ -5,7 +5,7 @@
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/server/driver.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/plugin/resolver_provider.dart';
+import 'package:analyzer/src/plugin/resolver_provider.dart';
 
 /**
  * An object that can be used to start an analysis server. This class exists so
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index 8e99e48..dccf6a6 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -9,14 +9,15 @@
 import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/context_root.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/engine.dart' as engine;
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:front_end/src/api_prototype/byte_store.dart';
 import 'package:front_end/src/base/performance_logger.dart';
diff --git a/pkg/analysis_server/lib/src/constants.dart b/pkg/analysis_server/test/constants.dart
similarity index 100%
rename from pkg/analysis_server/lib/src/constants.dart
rename to pkg/analysis_server/test/constants.dart
diff --git a/pkg/analysis_server/test/domain_completion_util.dart b/pkg/analysis_server/test/domain_completion_util.dart
index 0a6a543..996b070 100644
--- a/pkg/analysis_server/test/domain_completion_util.dart
+++ b/pkg/analysis_server/test/domain_completion_util.dart
@@ -7,13 +7,13 @@
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_constants.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
-import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/domain_completion.dart';
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test/test.dart';
 
 import 'analysis_abstract.dart';
+import 'constants.dart';
 
 class AbstractCompletionDomainTest extends AbstractAnalysisTest {
   String completionId;
diff --git a/pkg/analysis_server/test/domain_server_test.dart b/pkg/analysis_server/test/domain_server_test.dart
index c4aeebd..06d1c3e 100644
--- a/pkg/analysis_server/test/domain_server_test.dart
+++ b/pkg/analysis_server/test/domain_server_test.dart
@@ -6,13 +6,13 @@
 import 'package:analysis_server/protocol/protocol_constants.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/domain_server.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:test/test.dart';
 
+import 'constants.dart';
 import 'mocks.dart';
 
 main() {
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart
index 0019aa2..421000a 100644
--- a/pkg/analysis_server/test/protocol_server_test.dart
+++ b/pkg/analysis_server/test/protocol_server_test.dart
@@ -4,7 +4,6 @@
 
 import 'dart:mirrors';
 
-import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analyzer/dart/ast/ast.dart' as engine;
@@ -17,6 +16,7 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'constants.dart';
 import 'mocks.dart';
 
 main() {
diff --git a/pkg/analysis_server/test/protocol_test.dart b/pkg/analysis_server/test/protocol_test.dart
index 7d7e995..af72494 100644
--- a/pkg/analysis_server/test/protocol_test.dart
+++ b/pkg/analysis_server/test/protocol_test.dart
@@ -6,11 +6,12 @@
 
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
-import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/protocol/protocol_internal.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'constants.dart';
+
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NotificationTest);
diff --git a/pkg/analysis_server/test/services/correction/assist_test.dart b/pkg/analysis_server/test/services/correction/assist_test.dart
index cb974b3..6600839e 100644
--- a/pkg/analysis_server/test/services/correction/assist_test.dart
+++ b/pkg/analysis_server/test/services/correction/assist_test.dart
@@ -11,9 +11,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/dart/element/ast_provider.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
@@ -2564,6 +2562,33 @@
     await assertNoAssistAt('test =', DartAssistKind.ENCAPSULATE_FIELD);
   }
 
+  test_encapsulateField_OK_documentation() async {
+    await resolveTestUnit('''
+class A {
+  /// AAA
+  /// BBB
+  int test;
+}
+''');
+    await assertHasAssistAt('test;', DartAssistKind.ENCAPSULATE_FIELD, '''
+class A {
+  /// AAA
+  /// BBB
+  int _test;
+
+  /// AAA
+  /// BBB
+  int get test => _test;
+
+  /// AAA
+  /// BBB
+  set test(int test) {
+    _test = test;
+  }
+}
+''');
+  }
+
   test_encapsulateField_OK_hasType() async {
     await resolveTestUnit('''
 class A {
@@ -2580,7 +2605,7 @@
 
   int get test => _test;
 
-  void set test(int test) {
+  set test(int test) {
     _test = test;
   }
   A(this._test);
@@ -2606,7 +2631,7 @@
 
   get test => _test;
 
-  void set test(test) {
+  set test(test) {
     _test = test;
   }
 }
@@ -5769,8 +5794,8 @@
     CompilationUnitElement testUnitElement =
         resolutionMap.elementDeclaredByCompilationUnit(testUnit);
     DartAssistContext assistContext;
-    assistContext = new _DartAssistContextForValues(testUnitElement.source,
-        offset, length, driver, new AstProviderForDriver(driver), testUnit);
+    assistContext = new _DartAssistContextForValues(
+        testUnitElement.source, offset, length, driver, testUnit);
     AssistProcessor processor = new AssistProcessor(assistContext);
     return await processor.compute();
   }
@@ -5809,11 +5834,8 @@
   final AnalysisDriver analysisDriver;
 
   @override
-  final AstProvider astProvider;
-
-  @override
   final CompilationUnit unit;
 
   _DartAssistContextForValues(this.source, this.selectionOffset,
-      this.selectionLength, this.analysisDriver, this.astProvider, this.unit);
+      this.selectionLength, this.analysisDriver, this.unit);
 }
diff --git a/pkg/analysis_server/test/services/correction/change_test.dart b/pkg/analysis_server/test/services/correction/change_test.dart
index 0dc019b..d11aabd 100644
--- a/pkg/analysis_server/test/services/correction/change_test.dart
+++ b/pkg/analysis_server/test/services/correction/change_test.dart
@@ -2,12 +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:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../constants.dart';
+
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ChangeTest);
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index 9903039..426ff09 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -12,13 +12,13 @@
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/element/ast_provider.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     hide AnalysisError;
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
@@ -6901,6 +6901,17 @@
 ''');
   }
 
+  test_removeThisExpression_notAThisExpression() async {
+    String src = '''
+void foo() {
+  final /*LINT*/this.id;
+}
+''';
+    await findLint(src, LintNames.unnecessary_this);
+
+    await assertNoFix(DartFixKind.REMOVE_THIS_EXPRESSION);
+  }
+
   test_removeThisExpression_propertyAccess_oneCharacterOperator() async {
     String src = '''
 class A {
diff --git a/pkg/analysis_server/test/services/search/search_engine_test.dart b/pkg/analysis_server/test/services/search/search_engine_test.dart
index 1e93e6a..bfa202a 100644
--- a/pkg/analysis_server/test/services/search/search_engine_test.dart
+++ b/pkg/analysis_server/test/services/search/search_engine_test.dart
@@ -7,13 +7,13 @@
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analysis_server/src/services/search/search_engine_internal.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.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/source/package_map_resolver.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:front_end/src/api_prototype/byte_store.dart';
 import 'package:front_end/src/base/performance_logger.dart';
diff --git a/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart b/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart
index 8b7669b..8c372a6 100644
--- a/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart
+++ b/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart
@@ -10,13 +10,13 @@
 import 'package:analysis_server/src/plugin/plugin_watcher.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/context_root.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:front_end/src/api_prototype/byte_store.dart';
 import 'package:front_end/src/base/performance_logger.dart';
diff --git a/pkg/analyzer/benchmark/errors_in_all_libraries.dart b/pkg/analyzer/benchmark/errors_in_all_libraries.dart
index d46edba..57b512b 100644
--- a/pkg/analyzer/benchmark/errors_in_all_libraries.dart
+++ b/pkg/analyzer/benchmark/errors_in_all_libraries.dart
@@ -11,14 +11,14 @@
 
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer/src/source/source_resource.dart';
 import 'package:path/path.dart' as p;
 
diff --git a/pkg/analyzer/example/resolver_driver.dart b/pkg/analyzer/example/resolver_driver.dart
index cf68857..6c972a8 100755
--- a/pkg/analyzer/example/resolver_driver.dart
+++ b/pkg/analyzer/example/resolver_driver.dart
@@ -8,15 +8,15 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/file_system/file_system.dart' hide File;
 import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer/src/source/source_resource.dart';
 
 void main(List<String> args) {
diff --git a/pkg/analyzer/lib/analyzer.dart b/pkg/analyzer/lib/analyzer.dart
index 303cc88..ab46a8d 100644
--- a/pkg/analyzer/lib/analyzer.dart
+++ b/pkg/analyzer/lib/analyzer.dart
@@ -2,18 +2,16 @@
 // 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 analyzer;
-
 import 'dart:io';
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/file_system/file_system.dart' hide File;
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/error.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/string_source.dart';
diff --git a/pkg/analyzer/lib/context/context_root.dart b/pkg/analyzer/lib/context/context_root.dart
new file mode 100644
index 0000000..7625503
--- /dev/null
+++ b/pkg/analyzer/lib/context/context_root.dart
@@ -0,0 +1,8 @@
+// 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.
+
+@deprecated
+library context.context_root;
+
+export 'package:analyzer/src/context/context_root.dart';
diff --git a/pkg/analyzer/lib/file_system/file_system.dart b/pkg/analyzer/lib/file_system/file_system.dart
index 687380f..89da122 100644
--- a/pkg/analyzer/lib/file_system/file_system.dart
+++ b/pkg/analyzer/lib/file_system/file_system.dart
@@ -2,15 +2,14 @@
 // 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 analyzer.file_system.file_system;
-
 import 'dart:async';
 
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/util/absolute_path.dart';
 import 'package:path/path.dart';
 import 'package:watcher/watcher.dart';
 
+export 'package:analyzer/src/file_system/file_system.dart';
+
 /**
  * [File]s are leaf [Resource]s which contain data.
  */
@@ -226,11 +225,6 @@
  */
 abstract class ResourceProvider {
   /**
-   * Get the absolute path context used by this resource provider.
-   */
-  AbsolutePathContext get absolutePathContext;
-
-  /**
    * Get the path context used by this resource provider.
    */
   Context get pathContext;
@@ -271,41 +265,3 @@
    */
   Folder getStateLocation(String pluginId);
 }
-
-/**
- * A [UriResolver] for [Resource]s.
- */
-class ResourceUriResolver extends UriResolver {
-  /**
-   * The name of the `file` scheme.
-   */
-  static final String FILE_SCHEME = "file";
-
-  final ResourceProvider _provider;
-
-  ResourceUriResolver(this._provider);
-
-  ResourceProvider get provider => _provider;
-
-  @override
-  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
-    if (!isFileUri(uri)) {
-      return null;
-    }
-    String path = _provider.pathContext.fromUri(uri);
-    Resource resource = _provider.getResource(path);
-    if (resource is File) {
-      return resource.createSource(actualUri ?? uri);
-    }
-    return null;
-  }
-
-  @override
-  Uri restoreAbsolute(Source source) =>
-      _provider.pathContext.toUri(source.fullName);
-
-  /**
-   * Return `true` if the given [uri] is a `file` URI.
-   */
-  static bool isFileUri(Uri uri) => uri.scheme == FILE_SCHEME;
-}
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index 4c05644..0c5c8b6 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -12,7 +12,6 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/source/source_resource.dart';
-import 'package:analyzer/src/util/absolute_path.dart';
 import 'package:path/path.dart' as pathos;
 import 'package:watcher/watcher.dart';
 
@@ -31,9 +30,6 @@
 
   final pathos.Context _pathContext;
 
-  @override
-  final AbsolutePathContext absolutePathContext;
-
   MemoryResourceProvider(
       {pathos.Context context, @deprecated bool isWindows: false})
       : _pathContext = (context ??= pathos.style == pathos.Style.windows
@@ -41,9 +37,7 @@
             // the drive inserted by MemoryResourceProvider.convertPath
             // so that packages are mapped to the correct drive
             ? new pathos.Context(current: 'C:\\')
-            : pathos.context),
-        absolutePathContext =
-            new AbsolutePathContext(context.style == pathos.Style.windows);
+            : pathos.context);
 
   @override
   pathos.Context get pathContext => _pathContext;
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index a5d2a99..db86404 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -11,11 +11,28 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/source/source_resource.dart';
-import 'package:analyzer/src/util/absolute_path.dart';
 import 'package:path/path.dart';
 import 'package:watcher/watcher.dart';
 
 /**
+ * The name of the directory containing plugin specific subfolders used to
+ * store data across sessions.
+ */
+const String _SERVER_DIR = ".dartServer";
+
+/**
+ * Returns the path to the user's home directory.
+ */
+String _getStandardStateLocation() {
+  final home = io.Platform.isWindows
+      ? io.Platform.environment['LOCALAPPDATA']
+      : io.Platform.environment['HOME'];
+  return home != null && io.FileSystemEntity.isDirectorySync(home)
+      ? join(home, _SERVER_DIR)
+      : null;
+}
+
+/**
  * Return modification times for every file path in [paths].
  *
  * If a path is `null`, the modification time is also `null`.
@@ -39,28 +56,10 @@
 }
 
 /**
- * The name of the directory containing plugin specific subfolders used to
- * store data across sessions.
- */
-const String _SERVER_DIR = ".dartServer";
-
-/**
- * Returns the path to the user's home directory.
- */
-String _getStandardStateLocation() {
-  final home = io.Platform.isWindows
-      ? io.Platform.environment['LOCALAPPDATA']
-      : io.Platform.environment['HOME'];
-  return home != null && io.FileSystemEntity.isDirectorySync(home)
-      ? join(home, _SERVER_DIR)
-      : null;
-}
-
-/**
  * A `dart:io` based implementation of [ResourceProvider].
  */
 class PhysicalResourceProvider implements ResourceProvider {
-  static final FileReadMode NORMALIZE_EOL_ALWAYS =
+  static final String Function(String) NORMALIZE_EOL_ALWAYS =
       (String string) => string.replaceAll(new RegExp('\r\n?'), '\n');
 
   static final PhysicalResourceProvider INSTANCE =
@@ -71,11 +70,8 @@
    */
   final String _stateLocation;
 
-  @override
-  final AbsolutePathContext absolutePathContext =
-      new AbsolutePathContext(io.Platform.isWindows);
-
-  PhysicalResourceProvider(FileReadMode fileReadMode, {String stateLocation})
+  PhysicalResourceProvider(String Function(String) fileReadMode,
+      {String stateLocation})
       : _stateLocation = stateLocation ?? _getStandardStateLocation() {
     if (fileReadMode != null) {
       FileBasedSource.fileReadMode = fileReadMode;
@@ -256,7 +252,7 @@
 
   @override
   bool contains(String path) {
-    return absolutePathContext.isWithin(this.path, path);
+    return pathContext.isWithin(this.path, path);
   }
 
   @override
@@ -345,9 +341,6 @@
 
   _PhysicalResource(this._entry);
 
-  AbsolutePathContext get absolutePathContext =>
-      PhysicalResourceProvider.INSTANCE.absolutePathContext;
-
   @override
   bool get exists => _entry.existsSync();
 
@@ -356,7 +349,7 @@
 
   @override
   Folder get parent {
-    String parentPath = absolutePathContext.dirname(path);
+    String parentPath = pathContext.dirname(path);
     if (parentPath == path) {
       return null;
     }
@@ -372,7 +365,7 @@
   Context get pathContext => io.Platform.isWindows ? windows : posix;
 
   @override
-  String get shortName => absolutePathContext.basename(path);
+  String get shortName => pathContext.basename(path);
 
   @override
   bool operator ==(other) {
diff --git a/pkg/analyzer/lib/plugin/resolver_provider.dart b/pkg/analyzer/lib/plugin/resolver_provider.dart
index 33bb366..3c22554 100644
--- a/pkg/analyzer/lib/plugin/resolver_provider.dart
+++ b/pkg/analyzer/lib/plugin/resolver_provider.dart
@@ -2,14 +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.
 
+@deprecated
 library analyzer.plugin.resolver_provider;
 
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/generated/source.dart';
-
-/**
- * A function that will return a [UriResolver] that can be used to resolve a
- * specific kind of URI within the analysis context rooted at the given
- * [folder].
- */
-typedef UriResolver ResolverProvider(Folder folder);
+export 'package:analyzer/src/plugin/resolver_provider.dart';
diff --git a/pkg/analyzer/lib/source/line_info.dart b/pkg/analyzer/lib/source/line_info.dart
index 38ac611..47661a2 100644
--- a/pkg/analyzer/lib/source/line_info.dart
+++ b/pkg/analyzer/lib/source/line_info.dart
@@ -62,8 +62,13 @@
 
   /**
    * Return the location information for the character at the given [offset].
+   *
+   * A future version of this API will return a [CharacterLocation] rather than
+        // ignore: deprecated_member_use
+   * a [LineInfo_Location].
    */
-  CharacterLocation getLocation(int offset) {
+  // ignore: deprecated_member_use
+  LineInfo_Location getLocation(int offset) {
     var min = 0;
     var max = lineStarts.length - 1;
 
diff --git a/pkg/analyzer/lib/source/package_map_resolver.dart b/pkg/analyzer/lib/source/package_map_resolver.dart
index 3eeda21..6a1d230 100644
--- a/pkg/analyzer/lib/source/package_map_resolver.dart
+++ b/pkg/analyzer/lib/source/package_map_resolver.dart
@@ -2,100 +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.
 
-library analyzer.source.package_map_resolver;
+@deprecated
+library src.source.package_map_provider;
 
-import 'dart:core';
-
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/util/asserts.dart' as asserts;
-import 'package:path/path.dart' as pathos;
-
-/**
- * A [UriResolver] implementation for the `package:` scheme that uses a map of
- * package names to their directories.
- */
-class PackageMapUriResolver extends UriResolver {
-  /**
-   * The name of the `package` scheme.
-   */
-  static const String PACKAGE_SCHEME = "package";
-
-  /**
-   * A table mapping package names to the path of the directories containing
-   * the package.
-   */
-  final Map<String, List<Folder>> packageMap;
-
-  /**
-   * The [ResourceProvider] for this resolver.
-   */
-  final ResourceProvider resourceProvider;
-
-  /**
-   * Create a new [PackageMapUriResolver].
-   *
-   * [packageMap] is a table mapping package names to the paths of the
-   * directories containing the package
-   */
-  PackageMapUriResolver(this.resourceProvider, this.packageMap) {
-    asserts.notNull(resourceProvider);
-    asserts.notNull(packageMap);
-    packageMap.forEach((name, folders) {
-      if (folders.length != 1) {
-        throw new ArgumentError(
-            'Exactly one folder must be specified for a package.'
-            'Found $name = $folders');
-      }
-    });
-  }
-
-  @override
-  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
-    if (!isPackageUri(uri)) {
-      return null;
-    }
-    // Prepare path.
-    String path = uri.path;
-    // Prepare path components.
-    int index = path.indexOf('/');
-    if (index == -1 || index == 0) {
-      return null;
-    }
-    // <pkgName>/<relPath>
-    String pkgName = path.substring(0, index);
-    String relPath = path.substring(index + 1);
-    // If the package is known, return the corresponding file.
-    List<Folder> packageDirs = packageMap[pkgName];
-    if (packageDirs != null) {
-      Folder packageDir = packageDirs.single;
-      File file = packageDir.getChildAssumingFile(relPath);
-      return file.createSource(uri);
-    }
-    return null;
-  }
-
-  @override
-  Uri restoreAbsolute(Source source) {
-    String sourcePath = source.fullName;
-    pathos.Context pathContext = resourceProvider.pathContext;
-    for (String pkgName in packageMap.keys) {
-      Folder pkgFolder = packageMap[pkgName][0];
-      String pkgFolderPath = pkgFolder.path;
-      if (sourcePath.startsWith(pkgFolderPath + pathContext.separator)) {
-        String relPath = sourcePath.substring(pkgFolderPath.length + 1);
-        List<String> relPathComponents = pathContext.split(relPath);
-        String relUriPath = pathos.posix.joinAll(relPathComponents);
-        return Uri.parse('$PACKAGE_SCHEME:$pkgName/$relUriPath');
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Returns `true` if [uri] is a `package` URI.
-   */
-  static bool isPackageUri(Uri uri) {
-    return uri.scheme == PACKAGE_SCHEME;
-  }
-}
+export 'package:analyzer/src/source/package_map_resolver.dart';
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index 2aee1c4..5b3e1db 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -7,8 +7,6 @@
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/plugin/resolver_provider.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
 import 'package:analyzer/src/command_line/arguments.dart'
     show
@@ -21,6 +19,7 @@
     show AnalysisDriver, AnalysisDriverScheduler;
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/bazel.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/gn.dart';
@@ -28,7 +27,9 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/workspace.dart';
 import 'package:analyzer/src/lint/registry.dart';
+import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:analyzer/src/services/lint.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer/src/summary/summary_sdk.dart';
 import 'package:analyzer/src/task/options.dart';
 import 'package:analyzer/src/util/sdk.dart';
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index a70c50e5..4ccf4cd 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -9,7 +9,6 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/src/cancelable_future.dart';
 import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator;
 import 'package:analyzer/src/context/cache.dart';
@@ -20,6 +19,7 @@
 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';
diff --git a/pkg/analyzer/lib/src/context/source.dart b/pkg/analyzer/lib/src/context/source.dart
index 9ea1d7d..ad7bdaa 100644
--- a/pkg/analyzer/lib/src/context/source.dart
+++ b/pkg/analyzer/lib/src/context/source.dart
@@ -2,19 +2,17 @@
 // 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 analyzer.src.context.source;
-
 import 'dart:collection';
 import 'dart:math' show min;
 
 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/package_map_resolver.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/generated/utilities_dart.dart' as utils;
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:package_config/packages.dart';
 
 /**
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 91c19a8..d48b1d6 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -95,7 +95,7 @@
   /**
    * The version of data format, should be incremented on every format change.
    */
-  static const int DATA_VERSION = 56;
+  static const int DATA_VERSION = 57;
 
   /**
    * The number of exception contexts allowed to write. Once this field is
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 89b8073..e16375c 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -675,7 +675,7 @@
     // TODO(scheglov) remove EnumMemberBuilder class
 
     new TypeParameterBoundsResolver(
-            _typeProvider, _libraryElement, source, errorListener)
+            _context.typeSystem, _libraryElement, source, errorListener)
         .resolveTypeBounds(unit);
 
     unit.accept(new TypeResolverVisitor(
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 56eb475..c3dba9c 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -1792,7 +1792,7 @@
         isEqualTokens(node.modifierKeyword, other.modifierKeyword) &&
         isEqualNodes(node.returnType, other.returnType) &&
         isEqualTokens(node.propertyKeyword, other.propertyKeyword) &&
-        isEqualTokens(node.propertyKeyword, other.propertyKeyword) &&
+        isEqualTokens(node.operatorKeyword, other.operatorKeyword) &&
         isEqualNodes(node.name, other.name) &&
         isEqualNodes(node.parameters, other.parameters) &&
         isEqualNodes(node.body, other.body);
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index a651d07..5d91528 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -16,6 +16,8 @@
 import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/generated/utilities_collection.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/summary/resynthesize.dart'
+    show RecursiveInstantiateToBounds;
 
 /**
  * Type of callbacks used by [DeferredFunctionTypeImpl].
@@ -1691,7 +1693,11 @@
   @override
   List<DartType> get typeArguments {
     if (_typeArguments == null) {
-      _typeArguments = _typeArgumentsComputer();
+      try {
+        _typeArguments = _typeArgumentsComputer();
+      } on RecursiveInstantiateToBounds {
+        _hasTypeParameterReferenceInBound = true;
+      }
       _typeArgumentsComputer = null;
     }
     return _typeArguments;
@@ -2597,6 +2603,11 @@
   final String name;
 
   /**
+   * The cached value for [hasTypeParameterReferenceInBound].
+   */
+  bool _hasTypeParameterReferenceInBound;
+
+  /**
    * Initialize a newly created type to be declared by the given [element] and
    * to have the given [name].
    */
@@ -2608,6 +2619,46 @@
   @override
   Element get element => _element;
 
+  /**
+   * Return `true` if the type is parameterized and has a type parameter with
+   * the bound that references a type parameter.
+   */
+  bool get hasTypeParameterReferenceInBound {
+    if (_hasTypeParameterReferenceInBound == null) {
+      bool hasTypeParameterReference(DartType type) {
+        if (type == this) {
+          // Cycle detection -- and cycles should be considered unboundable.
+          return true;
+        } else if (type is TypeImpl &&
+            type._hasTypeParameterReferenceInBound == true) {
+          return true;
+        } else if (type is TypeParameterType) {
+          return true;
+        } else if (type is FunctionType) {
+          return (type as TypeImpl).hasTypeParameterReferenceInBound;
+        } else if (type is ParameterizedType) {
+          return type.typeArguments.any(hasTypeParameterReference);
+        } else {
+          return false;
+        }
+      }
+
+      Element element = this.element;
+      if (element is FunctionTypedElement) {
+        _hasTypeParameterReferenceInBound = element.parameters.any(
+                (parameter) => hasTypeParameterReference(parameter.type)) ||
+            (element.returnType != null &&
+                hasTypeParameterReference(element.returnType));
+      } else if (element is TypeParameterizedElement) {
+        _hasTypeParameterReferenceInBound = element.typeParameters
+            .any((parameter) => hasTypeParameterReference(parameter.bound));
+      } else {
+        _hasTypeParameterReferenceInBound = false;
+      }
+    }
+    return _hasTypeParameterReferenceInBound;
+  }
+
   @override
   bool get isBottom => false;
 
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 997767c..bb67cb9 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -22,7 +22,12 @@
 import 'package:front_end/src/fasta/scanner.dart' hide StringToken;
 import 'package:front_end/src/scanner/errors.dart' show translateErrorToken;
 import 'package:front_end/src/scanner/token.dart'
-    show StringToken, SyntheticBeginToken, SyntheticStringToken, SyntheticToken;
+    show
+        BeginToken,
+        StringToken,
+        SyntheticBeginToken,
+        SyntheticStringToken,
+        SyntheticToken;
 
 import 'package:front_end/src/fasta/problems.dart' show unhandled;
 import 'package:front_end/src/fasta/messages.dart'
@@ -2250,26 +2255,25 @@
     }
 
     if (parameters == null && (getOrSet == null || optional('set', getOrSet))) {
-      Token previous = typeParameters?.endToken;
-      if (previous == null) {
+      Token token = typeParameters?.endToken;
+      if (token == null) {
         if (name is AstNode) {
-          previous = name.endToken;
+          token = name.endToken;
         } else if (name is _OperatorName) {
-          previous = name.name.endToken;
+          token = name.name.endToken;
         } else {
           throw new UnimplementedError();
         }
       }
-      Token leftParen =
-          new SyntheticBeginToken(TokenType.OPEN_PAREN, previous.end);
+      Token next = token.next;
+      int offset = next.charOffset;
+      BeginToken leftParen =
+          new SyntheticBeginToken(TokenType.OPEN_PAREN, offset);
+      token.setNext(leftParen);
       Token rightParen =
-          new SyntheticToken(TokenType.CLOSE_PAREN, leftParen.offset);
-      rightParen.next = previous.next;
-      leftParen.next = rightParen;
-      previous.next = leftParen;
-      leftParen.previous = previous;
-      rightParen.previous = leftParen;
-      rightParen.next.previous = rightParen;
+          leftParen.setNext(new SyntheticToken(TokenType.CLOSE_PAREN, offset));
+      leftParen.endGroup = rightParen;
+      rightParen.setNext(next);
       parameters = ast.formalParameterList(
           leftParen, <FormalParameter>[], null, null, rightParen);
     }
diff --git a/pkg/analyzer/lib/src/fasta/error_converter.dart b/pkg/analyzer/lib/src/fasta/error_converter.dart
index 5032154..660a6b6 100644
--- a/pkg/analyzer/lib/src/fasta/error_converter.dart
+++ b/pkg/analyzer/lib/src/fasta/error_converter.dart
@@ -64,6 +64,12 @@
         errorReporter?.reportErrorForOffset(
             ParserErrorCode.COLON_IN_PLACE_OF_IN, offset, length);
         return;
+      case "CONCRETE_CLASS_WITH_ABSTRACT_MEMBER":
+        errorReporter?.reportErrorForOffset(
+            StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER,
+            offset,
+            length);
+        return;
       case "CONST_AFTER_FACTORY":
         errorReporter?.reportErrorForOffset(
             ParserErrorCode.CONST_AFTER_FACTORY, offset, length);
diff --git a/pkg/analyzer/lib/src/fasta/token_utils.dart b/pkg/analyzer/lib/src/fasta/token_utils.dart
index 790d04a..52f4388 100644
--- a/pkg/analyzer/lib/src/fasta/token_utils.dart
+++ b/pkg/analyzer/lib/src/fasta/token_utils.dart
@@ -24,19 +24,16 @@
   /// to be an analyzer token stream by removing error tokens and reporting
   /// those errors to the associated error listener.
   Token convertTokens(Token firstToken) {
-    Token previous = new Token.eof(-1);
-    Token token = firstToken;
-    token.previous = previous;
-    previous.next = token;
-    while (!token.isEof) {
-      if (token.type.kind == BAD_INPUT_TOKEN) {
-        translateErrorToken(token, reportError);
-        previous.next = token.next;
-        token.next.previous = previous;
+    Token token = new Token.eof(-1)..setNext(firstToken);
+    Token next = firstToken;
+    while (!next.isEof) {
+      if (next.type.kind == BAD_INPUT_TOKEN) {
+        translateErrorToken(next, reportError);
+        token.setNext(next.next);
       } else {
-        previous = token;
+        token = next;
       }
-      token = token.next;
+      next = token.next;
     }
     return firstToken;
   }
diff --git a/pkg/analyzer/lib/src/file_system/file_system.dart b/pkg/analyzer/lib/src/file_system/file_system.dart
new file mode 100644
index 0000000..8a6ea4b
--- /dev/null
+++ b/pkg/analyzer/lib/src/file_system/file_system.dart
@@ -0,0 +1,44 @@
+// 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:analyzer/src/generated/source.dart';
+import 'package:analyzer/file_system/file_system.dart';
+
+/**
+ * A [UriResolver] for [Resource]s.
+ */
+class ResourceUriResolver extends UriResolver {
+  /**
+   * The name of the `file` scheme.
+   */
+  static final String FILE_SCHEME = "file";
+
+  final ResourceProvider _provider;
+
+  ResourceUriResolver(this._provider);
+
+  ResourceProvider get provider => _provider;
+
+  @override
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
+    if (!isFileUri(uri)) {
+      return null;
+    }
+    String path = _provider.pathContext.fromUri(uri);
+    Resource resource = _provider.getResource(path);
+    if (resource is File) {
+      return resource.createSource(actualUri ?? uri);
+    }
+    return null;
+  }
+
+  @override
+  Uri restoreAbsolute(Source source) =>
+      _provider.pathContext.toUri(source.fullName);
+
+  /**
+   * Return `true` if the given [uri] is a `file` URI.
+   */
+  static bool isFileUri(Uri uri) => uri.scheme == FILE_SCHEME;
+}
diff --git a/pkg/analyzer/lib/src/generated/bazel.dart b/pkg/analyzer/lib/src/generated/bazel.dart
index 89efeef..ae17e37 100644
--- a/pkg/analyzer/lib/src/generated/bazel.dart
+++ b/pkg/analyzer/lib/src/generated/bazel.dart
@@ -2,12 +2,11 @@
 // 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 analyzer.src.generated.bazel;
-
 import 'dart:collection';
 import 'dart:core';
 
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 30d1a57..0e14ee2 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -658,6 +658,21 @@
         DartType staticType = _resolver.strongMode
             ? _getStaticTypeOrFunctionType(target)
             : _getStaticType(target);
+
+        if (_resolver.strongMode &&
+            staticType is FunctionType &&
+            methodName.name == FunctionElement.CALL_METHOD_NAME) {
+          if (target is SimpleIdentifier) {
+            methodName.staticElement = target.staticElement;
+          }
+          methodName.staticType = target.staticType;
+          node.staticType = staticType;
+          node.staticInvokeType = staticType;
+          node.argumentList.correspondingStaticParameters =
+              _computeCorrespondingParameters(node.argumentList, staticType);
+          return null;
+        }
+
         DartType propagatedType = _getPropagatedType(target);
         staticElement = _resolveInvokedElementWithTarget(
             target, staticType, methodName, isConditional);
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 45b1794..56d147d 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -12,7 +12,6 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/source/error_processor.dart';
 import 'package:analyzer/src/cancelable_future.dart';
 import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator;
@@ -24,6 +23,7 @@
 import 'package:analyzer/src/generated/source.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/task/api/dart.dart';
 import 'package:analyzer/src/task/api/model.dart';
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 4382091..281110b 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -7277,19 +7277,10 @@
       return;
     }
 
-    var element = node.type.element;
-    if (element is TypeParameterizedElement &&
-        element.typeParameters.any((p) => p.bound != null)) {
+    final type = node.type;
+    if (type is TypeImpl && type.hasTypeParameterReferenceInBound) {
       _errorReporter.reportErrorForNode(
-          StrongModeCode.NOT_INSTANTIATED_BOUND, node, [node.type]);
-    }
-
-    var enclosingElement = element?.enclosingElement;
-    if (element is GenericFunctionTypeElement &&
-        enclosingElement is GenericTypeAliasElement &&
-        enclosingElement.typeParameters.any((p) => p.bound != null)) {
-      _errorReporter.reportErrorForNode(
-          StrongModeCode.NOT_INSTANTIATED_BOUND, node, [node.type]);
+          StrongModeCode.NOT_INSTANTIATED_BOUND, node, [type]);
     }
   }
 }
diff --git a/pkg/analyzer/lib/src/generated/gn.dart b/pkg/analyzer/lib/src/generated/gn.dart
index 51440cb..ae31823 100644
--- a/pkg/analyzer/lib/src/generated/gn.dart
+++ b/pkg/analyzer/lib/src/generated/gn.dart
@@ -2,17 +2,16 @@
 // 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 analyzer.src.generated.gn;
-
 import 'dart:collection';
 import 'dart:core';
 
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/workspace.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:package_config/packages.dart';
 import 'package:package_config/packages_file.dart';
 import 'package:package_config/src/packages_impl.dart';
diff --git a/pkg/analyzer/lib/src/generated/package.dart b/pkg/analyzer/lib/src/generated/package.dart
index 5983dd3..fba626f 100644
--- a/pkg/analyzer/lib/src/generated/package.dart
+++ b/pkg/analyzer/lib/src/generated/package.dart
@@ -2,18 +2,17 @@
 // 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 analyzer.src.generated.package;
-
 import 'dart:collection';
 
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/builder.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/generated/utilities_general.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:package_config/packages.dart';
 import 'package:yaml/yaml.dart';
 
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 69583e8..5562394 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -8885,7 +8885,7 @@
  * type aliases.
  */
 class TypeParameterBoundsResolver {
-  final TypeProvider typeProvider;
+  final TypeSystem typeSystem;
   final LibraryElement library;
   final Source source;
   final AnalysisErrorListener errorListener;
@@ -8894,7 +8894,7 @@
   TypeNameResolver typeNameResolver = null;
 
   TypeParameterBoundsResolver(
-      this.typeProvider, this.library, this.source, this.errorListener);
+      this.typeSystem, this.library, this.source, this.errorListener);
 
   /**
    * Resolve bounds of type parameters of classes, class and function type
@@ -8964,12 +8964,8 @@
             } else {
               libraryScope ??= new LibraryScope(library);
               typeParametersScope ??= createTypeParametersScope();
-              typeNameResolver ??= new TypeNameResolver(
-                  new TypeSystemImpl(typeProvider),
-                  typeProvider,
-                  library,
-                  source,
-                  errorListener);
+              typeNameResolver ??= new TypeNameResolver(typeSystem,
+                  typeSystem.typeProvider, library, source, errorListener);
               typeNameResolver.nameScope = typeParametersScope;
               _resolveTypeName(bound);
               typeParameterElement.bound = bound.type;
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 16ad79b..7c76550 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -358,10 +358,15 @@
       }
     }
 
-    List<TypeParameterType> getFreeParameters(DartType type) {
+    List<TypeParameterType> getFreeParameters(DartType rootType) {
       List<TypeParameterType> parameters = null;
+      Set<DartType> visitedTypes = new HashSet<DartType>();
 
       void appendParameters(DartType type) {
+        if (visitedTypes.contains(type)) {
+          return;
+        }
+        visitedTypes.add(type);
         if (type is TypeParameterType && all.contains(type)) {
           parameters ??= <TypeParameterType>[];
           parameters.add(type);
@@ -370,7 +375,7 @@
         }
       }
 
-      appendParameters(type);
+      appendParameters(rootType);
       return parameters;
     }
 
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index 5884ac1..006ccb6 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -9,11 +9,11 @@
 import 'package:analyzer/file_system/file_system.dart'
     show File, Folder, ResourceProvider, ResourceUriResolver;
 import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -23,6 +23,7 @@
 import 'package:analyzer/src/lint/project.dart';
 import 'package:analyzer/src/lint/registry.dart';
 import 'package:analyzer/src/services/lint.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer/src/util/sdk.dart';
 import 'package:front_end/src/api_prototype/byte_store.dart';
 import 'package:front_end/src/base/performance_logger.dart';
diff --git a/pkg/analyzer/lib/src/plugin/resolver_provider.dart b/pkg/analyzer/lib/src/plugin/resolver_provider.dart
new file mode 100644
index 0000000..abbb3a8
--- /dev/null
+++ b/pkg/analyzer/lib/src/plugin/resolver_provider.dart
@@ -0,0 +1,13 @@
+// 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/file_system/file_system.dart';
+import 'package:analyzer/src/generated/source.dart';
+
+/**
+ * A function that will return a [UriResolver] that can be used to resolve a
+ * specific kind of URI within the analysis context rooted at the given
+ * [folder].
+ */
+typedef UriResolver ResolverProvider(Folder folder);
diff --git a/pkg/analyzer/lib/src/source/package_map_resolver.dart b/pkg/analyzer/lib/src/source/package_map_resolver.dart
new file mode 100644
index 0000000..b325201
--- /dev/null
+++ b/pkg/analyzer/lib/src/source/package_map_resolver.dart
@@ -0,0 +1,99 @@
+// 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 'dart:core';
+
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/util/asserts.dart' as asserts;
+import 'package:path/path.dart' as pathos;
+
+/**
+ * A [UriResolver] implementation for the `package:` scheme that uses a map of
+ * package names to their directories.
+ */
+class PackageMapUriResolver extends UriResolver {
+  /**
+   * The name of the `package` scheme.
+   */
+  static const String PACKAGE_SCHEME = "package";
+
+  /**
+   * A table mapping package names to the path of the directories containing
+   * the package.
+   */
+  final Map<String, List<Folder>> packageMap;
+
+  /**
+   * The [ResourceProvider] for this resolver.
+   */
+  final ResourceProvider resourceProvider;
+
+  /**
+   * Create a new [PackageMapUriResolver].
+   *
+   * [packageMap] is a table mapping package names to the paths of the
+   * directories containing the package
+   */
+  PackageMapUriResolver(this.resourceProvider, this.packageMap) {
+    asserts.notNull(resourceProvider);
+    asserts.notNull(packageMap);
+    packageMap.forEach((name, folders) {
+      if (folders.length != 1) {
+        throw new ArgumentError(
+            'Exactly one folder must be specified for a package.'
+            'Found $name = $folders');
+      }
+    });
+  }
+
+  @override
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
+    if (!isPackageUri(uri)) {
+      return null;
+    }
+    // Prepare path.
+    String path = uri.path;
+    // Prepare path components.
+    int index = path.indexOf('/');
+    if (index == -1 || index == 0) {
+      return null;
+    }
+    // <pkgName>/<relPath>
+    String pkgName = path.substring(0, index);
+    String relPath = path.substring(index + 1);
+    // If the package is known, return the corresponding file.
+    List<Folder> packageDirs = packageMap[pkgName];
+    if (packageDirs != null) {
+      Folder packageDir = packageDirs.single;
+      File file = packageDir.getChildAssumingFile(relPath);
+      return file.createSource(uri);
+    }
+    return null;
+  }
+
+  @override
+  Uri restoreAbsolute(Source source) {
+    String sourcePath = source.fullName;
+    pathos.Context pathContext = resourceProvider.pathContext;
+    for (String pkgName in packageMap.keys) {
+      Folder pkgFolder = packageMap[pkgName][0];
+      String pkgFolderPath = pkgFolder.path;
+      if (sourcePath.startsWith(pkgFolderPath + pathContext.separator)) {
+        String relPath = sourcePath.substring(pkgFolderPath.length + 1);
+        List<String> relPathComponents = pathContext.split(relPath);
+        String relUriPath = pathos.posix.joinAll(relPathComponents);
+        return Uri.parse('$PACKAGE_SCHEME:$pkgName/$relUriPath');
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Returns `true` if [uri] is a `package` URI.
+   */
+  static bool isPackageUri(Uri uri) {
+    return uri.scheme == PACKAGE_SCHEME;
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index f15fcd2..2271c0c 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -858,6 +858,8 @@
   }
 }
 
+class RecursiveInstantiateToBounds {}
+
 /// Specialization of [ReferenceInfo] for resynthesis from linked summaries.
 class _ReferenceInfo extends ReferenceInfo {
   /**
@@ -983,14 +985,27 @@
       InterfaceTypeImpl type =
           new InterfaceTypeImpl.elementWithNameAndArgs(element, name, () {
         if (typeArguments == null) {
-          if (libraryResynthesizer.summaryResynthesizer.strongMode &&
-              instantiateToBoundsAllowed) {
-            InterfaceType instantiatedToBounds = libraryResynthesizer
-                .summaryResynthesizer.context.typeSystem
-                .instantiateToBounds(element.type) as InterfaceType;
-            return instantiatedToBounds.typeArguments;
+          if (!_isBeingInstantiatedToBounds) {
+            _isBeingInstantiatedToBounds = true;
+            _isRecursiveWhileInstantiateToBounds = false;
+            try {
+              if (libraryResynthesizer.summaryResynthesizer.strongMode) {
+                InterfaceType instantiatedToBounds = libraryResynthesizer
+                    .summaryResynthesizer.context.typeSystem
+                    .instantiateToBounds(element.type) as InterfaceType;
+                if (_isRecursiveWhileInstantiateToBounds) {
+                  throw new RecursiveInstantiateToBounds();
+                }
+                return instantiatedToBounds.typeArguments;
+              } else {
+                return _dynamicTypeArguments;
+              }
+            } finally {
+              _isBeingInstantiatedToBounds = false;
+            }
           } else {
-            return _dynamicTypeArguments;
+            _isRecursiveWhileInstantiateToBounds = true;
+            typeArguments = _dynamicTypeArguments;
           }
         }
         return typeArguments;
@@ -1352,6 +1367,7 @@
       if (declaredType && !referenceInfo.isDeclarableType) {
         return DynamicTypeImpl.instance;
       }
+
       return referenceInfo.buildType(
           instantiateToBoundsAllowed,
           type.typeArguments.length,
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index d117708..fd3b106 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -4927,7 +4927,7 @@
     //
     RecordingErrorListener errorListener = new RecordingErrorListener();
     new TypeParameterBoundsResolver(
-            typeProvider, library, unitElement.source, errorListener)
+            context.typeSystem, library, unitElement.source, errorListener)
         .resolveTypeBounds(unit);
     //
     // Record outputs.
diff --git a/pkg/analyzer/lib/src/util/absolute_path.dart b/pkg/analyzer/lib/src/util/absolute_path.dart
deleted file mode 100644
index 28f5732..0000000
--- a/pkg/analyzer/lib/src/util/absolute_path.dart
+++ /dev/null
@@ -1,170 +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.
-
-library analyzer.src.util.absolute_path;
-
-/// The class for manipulating absolute, normalized paths.
-class AbsolutePathContext {
-  static const int _COLON = 0x3A;
-  static const int _LOWER_A = 0x61;
-  static const int _LOWER_Z = 0x7A;
-  static const int _UPPER_A = 0x41;
-  static const int _UPPER_Z = 0x5A;
-
-  final bool _isWindows;
-  String separator;
-  int _separatorChar;
-  String _singlePeriodComponent;
-  String _doublePeriodComponent;
-  String _singlePeriodEnding;
-  String _doublePeriodEnding;
-
-  AbsolutePathContext(this._isWindows) {
-    separator = _isWindows ? r'\' : '/';
-    _separatorChar = separator.codeUnitAt(0);
-    _singlePeriodComponent = separator + '.' + separator;
-    _doublePeriodComponent = separator + '..' + separator;
-    _singlePeriodEnding = separator + '.';
-    _doublePeriodEnding = separator + '..';
-  }
-
-  /// Append the given relative [suffix] to the given absolute [parent].
-  ///
-  ///     context.append('/path/to', 'foo'); // -> '/path/to/foo'
-  ///
-  /// The given [suffix] cannot be an absolute path or use `..`.
-  String append(String parent, String suffix) {
-    return '$parent$separator$suffix';
-  }
-
-  /// Return the part of the absolute [path] after the last separator on the
-  /// context's platform.
-  ///
-  ///     context.basename('/path/to/foo.dart'); // -> 'foo.dart'
-  ///     context.basename('/path/to');          // -> 'to'
-  ///     context.basename('/path');             // -> 'path'
-  ///     context.basename('/');                 // -> ''
-  String basename(String path) {
-    int index = path.lastIndexOf(separator);
-    return path.substring(index + 1);
-  }
-
-  /// Return the part of the absolute [path] before the last separator.
-  ///
-  ///     context.dirname('/path/to/foo.dart'); // -> '/path/to'
-  ///     context.dirname('/path/to');          // -> '/path'
-  ///     context.dirname(r'/path');            // -> '/'
-  ///     context.dirname(r'/');                // -> '/'
-  ///     context.dirname(r'C:\path');          // -> 'C:\'
-  ///     context.dirname(r'C:\');              // -> 'C:\'
-  String dirname(String path) {
-    int firstIndex = path.indexOf(separator);
-    int lastIndex = path.lastIndexOf(separator);
-    return lastIndex == firstIndex
-        ? path.substring(0, firstIndex + 1)
-        : path.substring(0, lastIndex);
-  }
-
-  /// Return `true` if the given [path] is valid.
-  ///
-  ///     context.isNormalized('/foo/bar');        // -> true
-  ///     context.isNormalized('/foo/bar/../baz'); // -> false
-  bool isValid(String path) {
-    return _isAbsolute(path) && _isNormalized(path);
-  }
-
-  /// Return `true` if [child] is a path beneath [parent], and `false`
-  /// otherwise. Both the [child] and [parent] paths must be absolute paths.
-  ///
-  ///     context.isWithin('/root/path', '/root/path/a'); // -> true
-  ///     context.isWithin('/root/path', '/root/other');  // -> false
-  ///     context.isWithin('/root/path', '/root/path');   // -> false
-  bool isWithin(String parent, String child) {
-    int parentLength = parent.length;
-    int childLength = child.length;
-    if (parentLength >= childLength) {
-      return false;
-    }
-    if (child.codeUnitAt(parentLength) != _separatorChar) {
-      return false;
-    }
-    return _startsWithUnsafe(child, parent);
-  }
-
-  /// Split [path] into its components using [separator].
-  ///
-  ///     context.split('/path/to/foo'); // -> ['', 'path', 'to', 'foo']
-  List<String> split(String path) {
-    return path.split(separator);
-  }
-
-  /// If the given [child] is within the given [parent], then return the
-  /// relative path from [parent] to [child]. Otherwise return `null`. Both
-  /// the [child] and [parent] paths must be absolute paths.
-  ///
-  ///     context.relative('/root/path', '/root/path/a/b.dart'); // -> 'a/b.dart'
-  ///     context.relative('/root/path', '/root/other.dart');    // -> null
-  String suffix(String parent, String child) {
-    String parentPrefix = parent + separator;
-    if (child.startsWith(parentPrefix)) {
-      return child.substring(parentPrefix.length);
-    }
-    return null;
-  }
-
-  /// Return `true` if the given [path] is absolute.
-  ///
-  ///     _isAbsolute('/foo/bar');   // -> true
-  ///     _isAbsolute('/');          // -> true
-  ///     _isAbsolute('foo/bar');    // -> false
-  ///     _isAbsolute('C:\foo\bar'); // -> true
-  ///     _isAbsolute('C:\');        // -> true
-  ///     _isAbsolute('foo\bar');    // -> false
-  bool _isAbsolute(String path) {
-    if (_isWindows) {
-      return path.length >= 3 &&
-          _isAlphabetic(path.codeUnitAt(0)) &&
-          path.codeUnitAt(1) == _COLON &&
-          path.codeUnitAt(2) == _separatorChar;
-    } else {
-      return path.isNotEmpty && path.codeUnitAt(0) == _separatorChar;
-    }
-  }
-
-  /// Return `true` if the given absolute [path] is normalized.
-  ///
-  ///     _isNormalized('/foo/bar');        // -> true
-  ///     _isNormalized('/foo/..bar');      // -> true
-  ///     _isNormalized('/foo/bar..');      // -> true
-  ///     _isNormalized('/');               // -> true
-  ///     _isNormalized('/foo/bar/../baz'); // -> false
-  ///     _isNormalized('/foo/bar/..');     // -> false
-  bool _isNormalized(String path) {
-    return !path.contains(_singlePeriodComponent) &&
-        !path.contains(_doublePeriodComponent) &&
-        !path.endsWith(_singlePeriodEnding) &&
-        !path.endsWith(_doublePeriodEnding);
-  }
-
-  /// Returns whether [char] is the code for an ASCII letter (uppercase or
-  /// lowercase).
-  static bool _isAlphabetic(int char) {
-    return char >= _UPPER_A && char <= _UPPER_Z ||
-        char >= _LOWER_A && char <= _LOWER_Z;
-  }
-
-  /// Return `true` if [str] starts with the given [prefix].
-  ///
-  /// The check is done from the end of [prefix], because absolute paths
-  /// usually have the same prefix, e.g. the user's home directory.
-  static bool _startsWithUnsafe(String str, String prefix) {
-    int len = prefix.length;
-    for (int i = len - 1; i >= 0; i--) {
-      if (str.codeUnitAt(i) != prefix.codeUnitAt(i)) {
-        return false;
-      }
-    }
-    return true;
-  }
-}
diff --git a/pkg/analyzer/lib/task/model.dart b/pkg/analyzer/lib/task/model.dart
new file mode 100644
index 0000000..1b33bf4
--- /dev/null
+++ b/pkg/analyzer/lib/task/model.dart
@@ -0,0 +1,8 @@
+// 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.
+
+@deprecated
+library task.model;
+
+export 'package:analyzer/src/task/api/model.dart';
diff --git a/pkg/analyzer/test/file_system/resource_uri_resolver_test.dart b/pkg/analyzer/test/file_system/resource_uri_resolver_test.dart
index 610048d..c08c9cd 100644
--- a/pkg/analyzer/test/file_system/resource_uri_resolver_test.dart
+++ b/pkg/analyzer/test/file_system/resource_uri_resolver_test.dart
@@ -2,10 +2,8 @@
 // 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 analyzer.test.file_system.resource_uri_resolver_test;
-
-import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index a14fde5..42664e8 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -18,6 +18,7 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart' hide SdkLibrariesReader;
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine_io.dart';
 import 'package:analyzer/src/generated/java_io.dart';
diff --git a/pkg/analyzer/test/generated/analysis_context_factory.dart b/pkg/analyzer/test/generated/analysis_context_factory.dart
index 5f02ed3..73eb7d3 100644
--- a/pkg/analyzer/test/generated/analysis_context_factory.dart
+++ b/pkg/analyzer/test/generated/analysis_context_factory.dart
@@ -15,6 +15,7 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/sdk.dart';
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
index 043f1a3..ed41c50 100644
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ b/pkg/analyzer/test/generated/engine_test.dart
@@ -7,7 +7,6 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
-import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/src/cancelable_future.dart';
 import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator;
 import 'package:analyzer/src/context/cache.dart';
@@ -17,6 +16,7 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:analyzer/src/string_source.dart';
 import 'package:analyzer/src/task/api/model.dart';
 import 'package:html/dom.dart' show Document;
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index c979ff2..94c4d91 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -2176,6 +2176,37 @@
     expect(expression.leftOperand, new isInstanceOf<BinaryExpression>());
   }
 
+  void test_logicalAndExpressionStatement() {
+    // Assert that `<` and `>` are not interpreted as type arguments.
+    ExpressionStatement statement = parseStatement("C<T && T>U;");
+    BinaryExpression expression = statement.expression;
+    expect(expression.leftOperand, new isInstanceOf<BinaryExpression>());
+  }
+
+  void test_methodInvocation1() {
+    // Assert that `<` and `>` are not interpreted as type arguments.
+    ExpressionStatement statement = parseStatement("f(a < b, c > 3);");
+    assertNoErrors();
+    MethodInvocation method = statement.expression;
+    expect(method.argumentList.arguments, hasLength(2));
+  }
+
+  void test_methodInvocation2() {
+    // Assert that `<` and `>` are not interpreted as type arguments.
+    ExpressionStatement statement = parseStatement("f(a < b, c >> 3);");
+    assertNoErrors();
+    MethodInvocation method = statement.expression;
+    expect(method.argumentList.arguments, hasLength(2));
+  }
+
+  void test_methodInvocation3() {
+    // Assert that `<` and `>` are not interpreted as type arguments.
+    ExpressionStatement statement = parseStatement("f(a < b, c < d >> 3);");
+    assertNoErrors();
+    MethodInvocation method = statement.expression;
+    expect(method.argumentList.arguments, hasLength(2));
+  }
+
   void test_logicalAndExpression_precedence_bitwiseOr_left() {
     BinaryExpression expression = parseExpression("x | y < z");
     expect(expression.leftOperand, new isInstanceOf<BinaryExpression>());
@@ -3416,10 +3447,7 @@
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
     listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 3)
-          ]
+        ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1)]
         : [
             expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
             expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)
@@ -3587,7 +3615,12 @@
   void test_functionTypedField_invalidType_class() {
     if (usingFastaParser) {
       parseCompilationUnit("Function(class) x = null;",
-          errors: [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 9, 5)]);
+          errors: usingFastaParser
+              ? [
+                  expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 9, 5),
+                  expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 5)
+                ]
+              : [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 9, 5)]);
     }
   }
 
@@ -3617,7 +3650,6 @@
             ? [
                 expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 1),
                 expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 8),
                 expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 20, 0),
               ]
             : [
@@ -3666,14 +3698,12 @@
 }''');
     CompilationUnit unit = parser.parseCompilationUnit2();
     expectNotNullIfNoErrors(unit);
-    listener.assertErrors([
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.EXPECTED_TOKEN
-              : ParserErrorCode.UNEXPECTED_TOKEN,
-          30,
-          1)
-    ]);
+    listener.assertErrors(usingFastaParser
+        ? [
+            expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 30, 1),
+            expectedError(ParserErrorCode.EXPECTED_TOKEN, 30, 1)
+          ]
+        : [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 30, 1)]);
   }
 
   void test_getterInFunction_block_noReturnType() {
@@ -5608,7 +5638,7 @@
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
     listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.VAR_AND_TYPE, 5, 3)]
+        ? [expectedError(ParserErrorCode.VAR_AND_TYPE, 1, 3)]
         : [expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)]);
   }
 
@@ -9172,15 +9202,14 @@
   }
 
   void test_parseFormalParameterList_prefixedType_partial2() {
-    int errorOffset = usingFastaParser ? 4 : 3;
     FormalParameterList list = parseFormalParameterList('(io.,a)', errors: [
       expectedError(
           usingFastaParser
               ? ParserErrorCode.EXPECTED_TYPE_NAME
               : ParserErrorCode.MISSING_IDENTIFIER,
-          errorOffset,
+          4,
           1),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, errorOffset, 1)
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)
     ]);
     expect(list, isNotNull);
     expect(list.leftParenthesis, isNotNull);
@@ -13146,6 +13175,20 @@
  * More complex tests should be defined in the class [ComplexParserTest].
  */
 abstract class SimpleParserTestMixin implements AbstractParserTestCase {
+  void test_classDeclaration_complexTypeParam() {
+    CompilationUnit unit = parseCompilationUnit('''
+class C<@Foo.bar(const [], const [1], const{"":r""}, 0xFF + 2, .3, 4.5) T> {}
+''');
+    ClassDeclaration clazz = unit.declarations[0];
+    expect(clazz.name.name, 'C');
+    expect(clazz.typeParameters.typeParameters, hasLength(1));
+    TypeParameter typeParameter = clazz.typeParameters.typeParameters[0];
+    expect(typeParameter.name.name, 'T');
+    expect(typeParameter.metadata, hasLength(1));
+    Annotation metadata = typeParameter.metadata[0];
+    expect(metadata.name.name, 'Foo.bar');
+  }
+
   ConstructorName parseConstructorName(String name) {
     createParser('new $name();');
     Statement statement = parser.parseStatement2();
@@ -15044,6 +15087,50 @@
     expect(variableList.type, new isInstanceOf<GenericFunctionType>());
   }
 
+  void test_parseNonLabeledStatement_variableDeclaration_typeParam() {
+    VariableDeclarationStatement statement = parseStatement('C<T> v;');
+    assertNoErrors();
+    VariableDeclarationList variableList = statement.variables;
+    List<VariableDeclaration> variables = variableList.variables;
+    expect(variables, hasLength(1));
+    expect(variables[0].name.name, 'v');
+    TypeName typeName = variableList.type;
+    expect(typeName.name.name, 'C');
+    expect(typeName.typeArguments.arguments, hasLength(1));
+    TypeName typeArgument = typeName.typeArguments.arguments[0];
+    expect(typeArgument.name.name, 'T');
+  }
+
+  void test_parseNonLabeledStatement_variableDeclaration_typeParam2() {
+    VariableDeclarationStatement statement =
+        parseStatement('C<T /* ignored comment */ > v;');
+    assertNoErrors();
+    VariableDeclarationList variableList = statement.variables;
+    List<VariableDeclaration> variables = variableList.variables;
+    expect(variables, hasLength(1));
+    expect(variables[0].name.name, 'v');
+    TypeName typeName = variableList.type;
+    expect(typeName.name.name, 'C');
+    expect(typeName.typeArguments.arguments, hasLength(1));
+    TypeName typeArgument = typeName.typeArguments.arguments[0];
+    expect(typeArgument.name.name, 'T');
+  }
+
+  void test_parseNonLabeledStatement_variableDeclaration_typeParam3() {
+    VariableDeclarationStatement statement =
+        parseStatement('C<T Function(String s)> v;');
+    assertNoErrors();
+    VariableDeclarationList variableList = statement.variables;
+    List<VariableDeclaration> variables = variableList.variables;
+    expect(variables, hasLength(1));
+    expect(variables[0].name.name, 'v');
+    TypeName typeName = variableList.type;
+    expect(typeName.name.name, 'C');
+    expect(typeName.typeArguments.arguments, hasLength(1));
+    expect(typeName.typeArguments.arguments[0],
+        new isInstanceOf<GenericFunctionType>());
+  }
+
   void test_invalid_typeParamAnnotation() {
     parseCompilationUnit('main() { C<@Foo T> v; }',
         errors: usingFastaParser
@@ -15056,6 +15143,36 @@
               ]);
   }
 
+  void test_invalid_typeParamAnnotation2() {
+    parseCompilationUnit('main() { C<@Foo.bar(1) T> v; }',
+        errors: usingFastaParser
+            // TODO(danrubel): Improve this error to indicate that annotations
+            // are not valid in this context.
+            ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 11, 1)]
+            : [
+                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 11, 1),
+                expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 1)
+              ]);
+  }
+
+  void test_invalid_typeParamAnnotation3() {
+    if (usingFastaParser) {
+      parseCompilationUnit('''
+main() {
+  C<@Foo.bar(const [], const [1], const{"":r""}, 0xFF + 2, .3, 4.5) T,
+    F Function<G>(int, String, {Bar b}),
+    void Function<H>(int i, [String j, K]),
+    A<B<C>>,
+    W<X<Y<Z>>>
+  > v;
+}''', errors: [
+        // TODO(danrubel): Improve this error to indicate that annotations
+        // are not valid in this context.
+        expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 13, 1)
+      ]);
+    }
+  }
+
   void test_parseStatement_emptyTypeArgumentList() {
     var declaration = parseStatement('C<> c;') as VariableDeclarationStatement;
     assertErrorsWithCodes([ParserErrorCode.EXPECTED_TYPE_NAME]);
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart
index 4f9f022..96b1156 100644
--- a/pkg/analyzer/test/generated/resolver_test_case.dart
+++ b/pkg/analyzer/test/generated/resolver_test_case.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.
 
-library analyzer.test.generated.resolver_test_case;
-
 import 'dart:async';
 
 import 'package:analyzer/dart/ast/ast.dart';
@@ -14,12 +12,12 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -27,6 +25,7 @@
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
 import 'package:analyzer/src/generated/testing/element_factory.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:front_end/src/api_prototype/byte_store.dart';
 import 'package:front_end/src/base/performance_logger.dart';
 import 'package:test/test.dart';
diff --git a/pkg/analyzer/test/generated/source_factory_test.dart b/pkg/analyzer/test/generated/source_factory_test.dart
index eda1c21..d5dbae9 100644
--- a/pkg/analyzer/test/generated/source_factory_test.dart
+++ b/pkg/analyzer/test/generated/source_factory_test.dart
@@ -2,17 +2,16 @@
 // 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 analyzer.test.generated.test.generated.source_factory;
-
 import 'dart:convert';
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine, Logger;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart' as utils;
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer/src/source/source_resource.dart';
 import 'package:package_config/packages.dart';
 import 'package:package_config/packages_file.dart' as pkgfile show parse;
diff --git a/pkg/analyzer/test/generated/static_warning_code_test.dart b/pkg/analyzer/test/generated/static_warning_code_test.dart
index ea87317..f908337 100644
--- a/pkg/analyzer/test/generated/static_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_warning_code_test.dart
@@ -368,6 +368,20 @@
     verify([source]);
   }
 
+  test_argumentTypeNotAssignable_call() async {
+    resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+    Source source = addSource(r'''
+typedef bool Predicate<T>(T object);
+
+Predicate<String> f() => null;
+
+void main() {
+  f().call(3);
+}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+
   test_argumentTypeNotAssignable_cascadeSecond() async {
     Source source = addSource(r'''
 // filler filler filler filler filler filler filler filler filler filler
diff --git a/pkg/analyzer/test/generated/strong_mode_driver_test.dart b/pkg/analyzer/test/generated/strong_mode_driver_test.dart
index 28609bb..4e83452 100644
--- a/pkg/analyzer/test/generated/strong_mode_driver_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_driver_test.dart
@@ -65,6 +65,18 @@
   test_genericMethod_functionTypedParameter_tearoff() {
     return super.test_genericMethod_functionTypedParameter_tearoff();
   }
+
+  @override
+  test_notInstantiatedBound_class_error_recursion() {
+    // overridden because not failing
+    return super.test_notInstantiatedBound_class_error_recursion();
+  }
+
+  @override
+  test_notInstantiatedBound_class_error_recursion_less_direct() {
+    // overridden because not failing
+    return super.test_notInstantiatedBound_class_error_recursion_less_direct();
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/generated/strong_mode_kernel_test.dart b/pkg/analyzer/test/generated/strong_mode_kernel_test.dart
index 433d68c..fdd3388 100644
--- a/pkg/analyzer/test/generated/strong_mode_kernel_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_kernel_test.dart
@@ -392,48 +392,6 @@
 
   @override
   @failingTest
-  test_notInstantiatedBound_direct_class_class() async {
-    // Expected 1 errors of type StrongModeCode.STRONG_MODE_NOT_INSTANTIATED_BOUND, found 0
-    await super.test_notInstantiatedBound_direct_class_class();
-  }
-
-  @override
-  @failingTest
-  test_notInstantiatedBound_direct_class_typedef() async {
-    // Expected 1 errors of type StrongModeCode.STRONG_MODE_NOT_INSTANTIATED_BOUND, found 0
-    await super.test_notInstantiatedBound_direct_class_typedef();
-  }
-
-  @override
-  @failingTest
-  test_notInstantiatedBound_direct_typedef_class() async {
-    // Expected 1 errors of type StrongModeCode.STRONG_MODE_NOT_INSTANTIATED_BOUND, found 0
-    await super.test_notInstantiatedBound_direct_typedef_class();
-  }
-
-  @override
-  @failingTest
-  test_notInstantiatedBound_functionType() async {
-    // Expected 2 errors of type StrongModeCode.STRONG_MODE_NOT_INSTANTIATED_BOUND, found 0
-    await super.test_notInstantiatedBound_functionType();
-  }
-
-  @override
-  @failingTest
-  test_notInstantiatedBound_indirect_class_class() async {
-    // Expected 1 errors of type StrongModeCode.STRONG_MODE_NOT_INSTANTIATED_BOUND, found 0
-    await super.test_notInstantiatedBound_indirect_class_class();
-  }
-
-  @override
-  @failingTest
-  test_notInstantiatedBound_indirect_class_class2() async {
-    // Expected 2 errors of type StrongModeCode.STRONG_MODE_NOT_INSTANTIATED_BOUND, found 0
-    await super.test_notInstantiatedBound_indirect_class_class2();
-  }
-
-  @override
-  @failingTest
   test_setterWithDynamicTypeIsError() async {
     // Expected 2 errors of type StaticWarningCode.NON_VOID_RETURN_FOR_SETTER, found 0
     await super.test_setterWithDynamicTypeIsError();
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index b7ead13..6a0a0b3 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -3910,42 +3910,48 @@
 ''');
   }
 
-  test_notInstantiatedBound_direct_class_class() async {
+  test_notInstantiatedBound_error_class_argument() async {
     String code = r'''
-class A<T extends int> {}
+class A<K, V extends List<K>> {}
 class C<T extends A> {}
 ''';
     await resolveTestUnit(code, noErrors: false);
     assertErrors(testSource, [StrongModeCode.NOT_INSTANTIATED_BOUND]);
   }
 
-  test_notInstantiatedBound_direct_class_typedef() async {
-    // Check that if the bound of a class is an uninstantiated typedef
-    // we emit an error
+  test_notInstantiatedBound_error_class_argument2() async {
     String code = r'''
-typedef void F<T extends int>();
-class C<T extends F> {}
+class A<K, V extends List<List<K>>> {}
+class C<T extends A> {}
 ''';
     await resolveTestUnit(code, noErrors: false);
     assertErrors(testSource, [StrongModeCode.NOT_INSTANTIATED_BOUND]);
   }
 
-  test_notInstantiatedBound_direct_typedef_class() async {
-    // Check that if the bound of a typeded is an uninstantiated class
-    // we emit an error
+  test_notInstantiatedBound_error_class_direct() async {
     String code = r'''
-class C<T extends int> {}
-typedef void F<T extends C>();
+class A<K, V extends K> {}
+class C<T extends A> {}
 ''';
     await resolveTestUnit(code, noErrors: false);
     assertErrors(testSource, [StrongModeCode.NOT_INSTANTIATED_BOUND]);
   }
 
-  test_notInstantiatedBound_functionType() async {
+  test_notInstantiatedBound_error_class_indirect() async {
+    String code = r'''
+class A<K, V extends K> {}
+class C<T extends List<A>> {}
+''';
+    await resolveTestUnit(code, noErrors: false);
+    assertErrors(testSource, [StrongModeCode.NOT_INSTANTIATED_BOUND]);
+  }
+
+  test_notInstantiatedBound_error_functionType() async {
     await resolveTestUnit(r'''
-class A<T extends int> {}
-class C<T extends Function(A)> {}
-class D<T extends A Function()> {}
+class A<T extends Function(T)> {}
+class B<T extends T Function()> {}
+class C<T extends A> {}
+class D<T extends B> {}
 ''', noErrors: false);
     assertErrors(testSource, [
       StrongModeCode.NOT_INSTANTIATED_BOUND,
@@ -3953,27 +3959,140 @@
     ]);
   }
 
-  test_notInstantiatedBound_indirect_class_class() async {
+  @failingTest
+  test_notInstantiatedBound_class_error_recursion() async {
     String code = r'''
-class A<T> {}
-class B<T extends int> {}
-class C<T extends A<B>> {}
+class A<T extends B> {} // points to a
+class B<T extends A> {} // points to b
+class C<T extends A> {} // points to a cyclical type
+''';
+    await resolveTestUnit(code, noErrors: false);
+    assertErrors(testSource, [
+      StrongModeCode.NOT_INSTANTIATED_BOUND,
+      StrongModeCode.NOT_INSTANTIATED_BOUND,
+      StrongModeCode.NOT_INSTANTIATED_BOUND,
+    ]);
+  }
+
+  @failingTest
+  test_notInstantiatedBound_class_error_recursion_less_direct() async {
+    String code = r'''
+class A<T extends B<A>> {}
+class B<T extends A<B>> {}
+''';
+    await resolveTestUnit(code, noErrors: false);
+    assertErrors(testSource, [
+      StrongModeCode.NOT_INSTANTIATED_BOUND,
+      StrongModeCode.NOT_INSTANTIATED_BOUND,
+    ]);
+  }
+
+  test_notInstantiatedBound_error_typedef_argument() async {
+    String code = r'''
+class A<K, V extends List<K>> {}
+typedef void F<T extends A>();
 ''';
     await resolveTestUnit(code, noErrors: false);
     assertErrors(testSource, [StrongModeCode.NOT_INSTANTIATED_BOUND]);
   }
 
-  test_notInstantiatedBound_indirect_class_class2() async {
+  test_notInstantiatedBound_error_typedef_argument2() async {
+    String code = r'''
+class A<K, V extends List<List<K>>> {}
+typedef void F<T extends A>();
+''';
+    await resolveTestUnit(code, noErrors: false);
+    assertErrors(testSource, [StrongModeCode.NOT_INSTANTIATED_BOUND]);
+  }
+
+  test_notInstantiatedBound_error_typedef_direct() async {
+    String code = r'''
+class A<K, V extends K> {}
+typedef void F<T extends A>();
+''';
+    await resolveTestUnit(code, noErrors: false);
+    assertErrors(testSource, [StrongModeCode.NOT_INSTANTIATED_BOUND]);
+  }
+
+  test_notInstantiatedBound_class_error_recursion_typedef() async {
+    String code = r'''
+typedef F(C value);
+class C<T extends F> {}
+class D<T extends C> {}
+''';
+    await resolveTestUnit(code, noErrors: false);
+    assertErrors(testSource, [
+      StrongModeCode.NOT_INSTANTIATED_BOUND,
+      StrongModeCode.NOT_INSTANTIATED_BOUND,
+      CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
+    ]);
+  }
+
+  test_notInstantiatedBound_ok_class() async {
+    String code = r'''
+class A<T extends int> {}
+class C1<T extends A> {}
+class C2<T extends List<A>> {}
+''';
+    await resolveTestUnit(code);
+    assertNoErrors(testSource);
+  }
+
+  test_notInstantiatedBound_ok_class_class2() async {
+    String code = r'''
+class A<T> {}
+class C<T extends A<int>> {}
+class D<T extends C> {}
+''';
+    await resolveTestUnit(code);
+    assertNoErrors(testSource);
+  }
+
+  test_notInstantiatedBound_ok_class_class3() async {
+    String code = r'''
+class A<T> {}
+class B<T extends int> {}
+class C<T extends A<B>> {}
+''';
+    await resolveTestUnit(code);
+    assertNoErrors(testSource);
+  }
+
+  test_notInstantiatedBound_ok_class_class4() async {
     String code = r'''
 class A<K, V> {}
 class B<T extends int> {}
 class C<T extends A<B, B>> {}
 ''';
-    await resolveTestUnit(code, noErrors: false);
-    assertErrors(testSource, [
-      StrongModeCode.NOT_INSTANTIATED_BOUND,
-      StrongModeCode.NOT_INSTANTIATED_BOUND
-    ]);
+    await resolveTestUnit(code);
+    assertNoErrors(testSource);
+  }
+
+  test_notInstantiatedBound_ok_class_typedef() async {
+    String code = r'''
+typedef void F<T extends int>();
+class C<T extends F> {}
+''';
+    await resolveTestUnit(code);
+    assertNoErrors(testSource);
+  }
+
+  test_notInstantiatedBound_ok_typedef_class() async {
+    String code = r'''
+class C<T extends int> {}
+typedef void F<T extends C>();
+''';
+    await resolveTestUnit(code);
+    assertNoErrors(testSource);
+  }
+
+  test_notInstantiatedBound_ok_class_function() async {
+    String code = r'''
+class A<T extends void Function<Z>()> {}
+class B<T extends A> {}
+''';
+    await resolveTestUnit(code);
+    assertNoErrors(testSource);
   }
 
   test_objectMethodOnFunctions_Anonymous() async {
diff --git a/pkg/analyzer/test/resource_utils.dart b/pkg/analyzer/test/resource_utils.dart
index c03eb1d..10aed70 100644
--- a/pkg/analyzer/test/resource_utils.dart
+++ b/pkg/analyzer/test/resource_utils.dart
@@ -10,7 +10,6 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/util/absolute_path.dart';
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 
@@ -92,12 +91,7 @@
 class TestResourceProvider implements ResourceProvider {
   final ResourceProvider _provider;
 
-  TestResourceProvider(this._provider) {
-    expect(_provider.absolutePathContext.separator, isWindows ? '\\' : '/');
-  }
-
-  @override
-  AbsolutePathContext get absolutePathContext => _provider.absolutePathContext;
+  TestResourceProvider(this._provider);
 
   @override
   path.Context get pathContext => _provider.pathContext;
diff --git a/pkg/analyzer/test/source/analysis_options_provider_test.dart b/pkg/analyzer/test/source/analysis_options_provider_test.dart
index 00e24ad..4d376e4 100644
--- a/pkg/analyzer/test/source/analysis_options_provider_test.dart
+++ b/pkg/analyzer/test/source/analysis_options_provider_test.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/util/yaml.dart';
diff --git a/pkg/analyzer/test/source/package_map_resolver_test.dart b/pkg/analyzer/test/source/package_map_resolver_test.dart
index 924704d..6072255 100644
--- a/pkg/analyzer/test/source/package_map_resolver_test.dart
+++ b/pkg/analyzer/test/source/package_map_resolver_test.dart
@@ -2,12 +2,10 @@
 // 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 analyzer.test.source.package_map_resolver_test;
-
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:path/path.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
diff --git a/pkg/analyzer/test/src/context/abstract_context.dart b/pkg/analyzer/test/src/context/abstract_context.dart
index 103433e..6c184b3 100644
--- a/pkg/analyzer/test/src/context/abstract_context.dart
+++ b/pkg/analyzer/test/src/context/abstract_context.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/file_system/memory_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';
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index 01fbb86..2601fcd 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -4,11 +4,11 @@
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/command_line/arguments.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/context/context_root.dart';
 import 'package:analyzer/src/context/source.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/bazel.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
@@ -16,6 +16,7 @@
 import 'package:analyzer/src/lint/linter.dart';
 import 'package:analyzer/src/lint/registry.dart';
 import 'package:analyzer/src/services/lint.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:args/args.dart';
 import 'package:package_config/packages.dart';
 import 'package:package_config/src/packages_impl.dart';
diff --git a/pkg/analyzer/test/src/context/cache_test.dart b/pkg/analyzer/test/src/context/cache_test.dart
index 32b2cbd..279aef0 100644
--- a/pkg/analyzer/test/src/context/cache_test.dart
+++ b/pkg/analyzer/test/src/context/cache_test.dart
@@ -6,12 +6,12 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_collection.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer/src/task/api/model.dart';
 import 'package:analyzer/src/task/model.dart';
 import 'package:test/test.dart';
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index 14565dc..a4e112b 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -14,7 +14,6 @@
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/cancelable_future.dart';
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/context/context.dart';
@@ -23,6 +22,7 @@
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_collection.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer/src/task/api/dart.dart';
 import 'package:analyzer/src/task/api/model.dart';
 import 'package:analyzer/src/task/dart.dart';
diff --git a/pkg/analyzer/test/src/context/source_test.dart b/pkg/analyzer/test/src/context/source_test.dart
index 5347f29..21c47ad 100644
--- a/pkg/analyzer/test/src/context/source_test.dart
+++ b/pkg/analyzer/test/src/context/source_test.dart
@@ -2,8 +2,8 @@
 // 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/file_system/file_system.dart';
 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:package_config/packages.dart';
 import 'package:test/test.dart';
diff --git a/pkg/analyzer/test/src/dart/analysis/base.dart b/pkg/analyzer/test/src/dart/analysis/base.dart
index fff1a3c..dacd732 100644
--- a/pkg/analyzer/test/src/dart/analysis/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/base.dart
@@ -6,13 +6,14 @@
 import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/status.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:front_end/src/api_prototype/byte_store.dart';
 import 'package:front_end/src/base/performance_logger.dart';
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 907139e..ab5f6b6 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -9,7 +9,6 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/error.dart';
-import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
@@ -18,6 +17,7 @@
 import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/resolver.dart' show ResolverErrorCode;
 import 'package:analyzer/src/generated/sdk.dart';
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index 7dc865f..3a84319 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -7,12 +7,13 @@
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisOptions, AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:convert/convert.dart';
 import 'package:crypto/crypto.dart';
 import 'package:front_end/src/api_prototype/byte_store.dart';
diff --git a/pkg/analyzer/test/src/fasta/recovery/extra_code_test.dart b/pkg/analyzer/test/src/fasta/recovery/extra_code_test.dart
index 3cbbd73..1d2917a 100644
--- a/pkg/analyzer/test/src/fasta/recovery/extra_code_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/extra_code_test.dart
@@ -23,19 +23,14 @@
  */
 @reflectiveTest
 class AnnotationTest extends AbstractRecoveryTest {
-  @failingTest
   void test_typeArgument() {
-    // https://github.com/dart-lang/sdk/issues/22314
-    // Parser crashes
-    // 'package:analyzer/src/fasta/ast_builder.dart': Failed assertion:
-    //     line 256 pos 12: 'token.isKeywordOrIdentifier': is not true.
     testRecovery('''
 const annotation = null;
 class A<E> {}
 class C {
   m() => new A<@annotation C>();
 }
-''', [ParserErrorCode.UNEXPECTED_TOKEN, ParserErrorCode.UNEXPECTED_TOKEN], '''
+''', [ParserErrorCode.UNEXPECTED_TOKEN], '''
 const annotation = null;
 class A<E> {}
 class C {
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 1531a12..9d6e061 100644
--- a/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
@@ -294,6 +294,19 @@
   }
 
   @failingTest
+  void test_missingGet() {
+    testRecovery('''
+class Bar {
+  int foo => 0;
+}
+''', [ParserErrorCode.MISSING_GET], '''
+class Bar {
+  int get foo => 0;
+}
+''');
+  }
+
+  @failingTest
   void test_parameterList_leftParen() {
     // https://github.com/dart-lang/sdk/issues/22938
     testRecovery('''
@@ -425,7 +438,6 @@
 ''');
   }
 
-  @failingTest
   void test_extraComma_named_noLast() {
     testRecovery('''
 f({a, , b}) {}
@@ -443,7 +455,6 @@
 ''');
   }
 
-  @failingTest
   void test_extraComma_positional_noLast() {
     testRecovery('''
 f([a, , b]) {}
@@ -461,7 +472,6 @@
 ''');
   }
 
-  @failingTest
   void test_extraComma_required_noLast() {
     testRecovery('''
 f(a, , b) {}
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/do_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/do_statement_test.dart
index b8eb3ff..56fb98f 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/do_statement_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/do_statement_test.dart
@@ -35,7 +35,7 @@
               'leftBrace',
               'do {',
               [
-                ParserErrorCode.EXPECTED_TOKEN,
+                ScannerErrorCode.EXPECTED_TOKEN,
                 ParserErrorCode.EXPECTED_TOKEN,
                 ParserErrorCode.EXPECTED_TOKEN,
                 ParserErrorCode.MISSING_IDENTIFIER,
@@ -43,7 +43,7 @@
                 ParserErrorCode.EXPECTED_TOKEN
               ],
               "do {} while (_s_);",
-              allFailing: true),
+              failing: allExceptEof),
           new TestDescriptor(
               'rightBrace',
               'do {}',
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/export_directive_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/export_directive_test.dart
index 9cd9192..7c73192 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/export_directive_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/export_directive_test.dart
@@ -32,9 +32,13 @@
           new TestDescriptor(
               'keyword',
               'export',
-              [/*ParserErrorCode.MISSING_URI,*/ ParserErrorCode.EXPECTED_TOKEN],
-              "export '';",
-              allFailing: true),
+              [
+                // TODO(danrubel): Consider an improved error message
+                // ParserErrorCode.MISSING_URI,
+                ParserErrorCode.EXPECTED_STRING_LITERAL,
+                ParserErrorCode.EXPECTED_TOKEN
+              ],
+              "export '';"),
           new TestDescriptor('emptyUri', "export ''",
               [ParserErrorCode.EXPECTED_TOKEN], "export '';"),
           new TestDescriptor('uri', "export 'a.dart'",
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/import_directive_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/import_directive_test.dart
index eb6dfc6..52cf298 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/import_directive_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/import_directive_test.dart
@@ -12,17 +12,19 @@
 
 class ImportDirectivesTest extends PartialCodeTest {
   buildAll() {
-    List<String> allExceptEof =
-        PartialCodeTest.prePartSuffixes.map((t) => t.name).toList();
     buildTests(
         'import_directive',
         [
           new TestDescriptor(
               'keyword',
               'import',
-              [/*ParserErrorCode.MISSING_URI,*/ ParserErrorCode.EXPECTED_TOKEN],
-              "import '';",
-              allFailing: true),
+              [
+                // TODO(danrubel): Consider an improved error message
+                // ParserErrorCode.MISSING_URI,
+                ParserErrorCode.EXPECTED_STRING_LITERAL,
+                ParserErrorCode.EXPECTED_TOKEN
+              ],
+              "import '';"),
           new TestDescriptor('emptyUri', "import ''",
               [ParserErrorCode.EXPECTED_TOKEN], "import '';"),
           new TestDescriptor('fullUri', "import 'a.dart'",
@@ -46,7 +48,7 @@
                 ParserErrorCode.EXPECTED_TOKEN
               ],
               "import 'a.dart' if (_s_) '';",
-              failing: allExceptEof),
+              failing: ['functionNonVoid', 'getter', 'setter']),
           new TestDescriptor(
               'ifId',
               "import 'a.dart' if (b",
@@ -55,8 +57,7 @@
                 ParserErrorCode.EXPECTED_TOKEN,
                 ParserErrorCode.EXPECTED_STRING_LITERAL
               ],
-              "import 'a.dart' if (b) '';",
-              failing: allExceptEof),
+              "import 'a.dart' if (b) '';"),
           new TestDescriptor(
               'ifEquals',
               "import 'a.dart' if (b ==",
@@ -66,8 +67,7 @@
                 ScannerErrorCode.EXPECTED_TOKEN,
                 ParserErrorCode.EXPECTED_STRING_LITERAL
               ],
-              "import 'a.dart' if (b == '') '';",
-              failing: allExceptEof),
+              "import 'a.dart' if (b == '') '';"),
           new TestDescriptor(
               'ifCondition',
               "import 'a.dart' if (b)",
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/local_variable_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/local_variable_test.dart
index 23eac88..388eec1 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/local_variable_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/local_variable_test.dart
@@ -59,14 +59,8 @@
               ],
               "const a, _s_;",
               failing: <String>[
-                'assert',
-                'block',
-                'break',
-                'continue',
-                'for',
                 'labeled',
                 'localFunctionNonVoid',
-                'return',
               ]),
           new TestDescriptor(
               'constTypeNameComma',
@@ -77,14 +71,8 @@
               ],
               "const int a, _s_;",
               failing: [
-                'assert',
-                'block',
-                'break',
-                'continue',
-                'for',
                 'labeled',
                 'localFunctionNonVoid',
-                'return',
               ]),
           new TestDescriptor('constNameCommaName', 'const a, b',
               [ParserErrorCode.EXPECTED_TOKEN], "const a, b;"),
@@ -99,16 +87,10 @@
               ],
               "final _s_;",
               failing: [
-                'assert',
-                'block',
-                'break',
-                'continue',
-                'for',
                 'labeled',
                 'localFunctionNonVoid',
                 'localFunctionVoid',
                 'localVariable',
-                'return',
               ]),
           new TestDescriptor('finalName', 'final a',
               [ParserErrorCode.EXPECTED_TOKEN], "final a;",
@@ -138,16 +120,10 @@
               ],
               "var _s_;",
               failing: [
-                'assert',
-                'block',
-                'break',
-                'continue',
-                'for',
                 'labeled',
                 'localFunctionNonVoid',
                 'localFunctionVoid',
                 'localVariable',
-                'return',
               ]),
           new TestDescriptor(
               'varName', 'var a', [ParserErrorCode.EXPECTED_TOKEN], "var a;",
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/part_directive_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/part_directive_test.dart
index bed24e2..814cf9b 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/part_directive_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/part_directive_test.dart
@@ -18,9 +18,13 @@
           new TestDescriptor(
               'keyword',
               'part',
-              [/*ParserErrorCode.MISSING_URI,*/ ParserErrorCode.EXPECTED_TOKEN],
-              "part '';",
-              allFailing: true),
+              [
+                // TODO(danrubel): Consider an improved error message
+                // ParserErrorCode.MISSING_URI,
+                ParserErrorCode.EXPECTED_STRING_LITERAL,
+                ParserErrorCode.EXPECTED_TOKEN
+              ],
+              "part '';"),
           new TestDescriptor('emptyUri', "part ''",
               [ParserErrorCode.EXPECTED_TOKEN], "part '';"),
           new TestDescriptor('uri', "part 'a.dart'",
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 c555393..60b559c 100644
--- a/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
@@ -26,6 +26,7 @@
     try {
       validUnit =
           parseCompilationUnit(validCode, codes: expectedErrorsInValidCode);
+      validateTokenStream(validUnit.beginToken);
     } catch (e) {
 //      print('');
 //      print('  Errors in valid code.');
@@ -55,8 +56,14 @@
 
   void validateTokenStream(Token token) {
     while (!token.isEof) {
-      expect(token.end, lessThanOrEqualTo(token.next.offset));
-      token = token.next;
+      Token next = token.next;
+      expect(token.end, lessThanOrEqualTo(next.offset));
+      if (next.isSynthetic) {
+        if (const [')', ']', '}'].contains(next.lexeme)) {
+          expect(next.beforeSynthetic, token);
+        }
+      }
+      token = next;
     }
   }
 }
diff --git a/pkg/analyzer/test/src/source/source_resource_test.dart b/pkg/analyzer/test/src/source/source_resource_test.dart
index 29474a0..cde9868 100644
--- a/pkg/analyzer/test/src/source/source_resource_test.dart
+++ b/pkg/analyzer/test/src/source/source_resource_test.dart
@@ -2,11 +2,10 @@
 // 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 analyzer.test.src.source.source_resource_test;
-
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/java_engine_io.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index 0b6ec9f..186ab04 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/source/error_processor.dart';
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/lint/linter.dart';
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 cb9db3a..44e1444 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -11,6 +11,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../../../utils.dart';
+import '../../summary/element_text.dart';
 import 'strong_test_helper.dart';
 
 void main() {
@@ -3527,58 +3528,12 @@
     expect(x.type.toString(), 'void');
   }
 
-  test_instantiateToBounds_generic2_hasBound_definedAfter() async {
-    var unit = await checkFileElement(r'''
-class B<T extends /*error:NOT_INSTANTIATED_BOUND*/A> {}
-class A<T extends int> {}
-B v = null;
-''');
-    expect(unit.topLevelVariables[0].type.toString(), 'B<A<dynamic>>');
-  }
-
-  test_instantiateToBounds_generic2_hasBound_definedBefore() async {
-    var unit = await checkFileElement(r'''
-class A<T extends int> {}
-class B<T extends /*error:NOT_INSTANTIATED_BOUND*/A> {}
-B v = null;
-''');
-    expect(unit.topLevelVariables[0].type.toString(), 'B<A<dynamic>>');
-  }
-
-  test_instantiateToBounds_generic2_noBound() async {
-    var unit = await checkFileElement(r'''
-class A<T> {}
-class B<T extends A> {}
-B v = null;
-''');
-    expect(unit.topLevelVariables[0].type.toString(), 'B<A<dynamic>>');
-  }
-
-  test_instantiateToBounds_generic_hasBound_definedAfter() async {
-    var unit = await checkFileElement(r'''
-A v = null;
-class A<T extends int> {}
-''');
-    expect(unit.topLevelVariables[0].type.toString(), 'A<int>');
-  }
-
-  test_instantiateToBounds_generic_hasBound_definedBefore() async {
-    var unit = await checkFileElement(r'''
-class A<T extends int> {}
-A v = null;
-''');
-    expect(unit.topLevelVariables[0].type.toString(), 'A<int>');
-  }
-
   test_instantiateToBounds_invokeConstructor_noBound() async {
-    var unit = await checkFile('''
+    var unit = await checkFileElement('''
 class C<T> {}
-main() {
-  var v = new C();
-}
+var x = /*info:INFERRED_TYPE_ALLOCATION*/new C();
 ''');
-    var v = findLocalVariable(unit, 'v');
-    expect(v.type.toString(), 'C<dynamic>');
+    expect(unit.topLevelVariables[0].type.toString(), 'C<dynamic>');
   }
 
   test_instantiateToBounds_invokeConstructor_typeArgsExact() async {
@@ -3595,7 +3550,128 @@
 class B<T extends A> {}
 B v = null;
 ''');
-    expect(unit.topLevelVariables[0].type.toString(), 'B<A>');
+    checkElementText(unit.library, r'''
+class A {
+}
+class B<T extends A> {
+}
+B<A> v;
+''');
+  }
+
+  test_instantiateToBounds_typeName_error1() async {
+    var unit = await checkFileElement(r'''
+class A<T1 extends int, T2 extends T1> {}
+class B<T extends /*error:NOT_INSTANTIATED_BOUND*/A> {}
+B v = null;
+''');
+    checkElementText(unit.library, r'''
+class A<T1 extends int, T2 extends T1> {
+}
+class B<T extends A<int, int>> {
+}
+B<A<int, int>> v;
+''');
+  }
+
+  test_instantiateToBounds_typeName_error2() async {
+    var unit = await checkFileElement(r'''
+class A<T1 extends T2, T2 extends int> {}
+class B<T extends /*error:NOT_INSTANTIATED_BOUND*/A> {}
+B v = null;
+''');
+    checkElementText(unit.library, r'''
+class A<T1 extends T2, T2 extends int> {
+}
+class B<T extends A<int, int>> {
+}
+B<A<int, int>> v;
+''');
+  }
+
+  test_instantiateToBounds_typeName_error3() async {
+    var unit = await checkFileElement(r'''
+class A<T1 extends int, T2 extends List<T1>> {}
+class B<T extends /*error:NOT_INSTANTIATED_BOUND*/A> {}
+B v = null;
+''');
+    checkElementText(unit.library, r'''
+class A<T1 extends int, T2 extends List<T1>> {
+}
+class B<T extends A<int, List<int>>> {
+}
+B<A<int, List<int>>> v;
+''');
+  }
+
+  @failingTest
+  test_instantiateToBounds_typeName_OK_hasBound_definedAfter() async {
+    var unit = await checkFileElement(r'''
+class B<T extends A> {}
+class A<T extends int> {}
+B v = null;
+''');
+    checkElementText(unit.library, r'''
+class B<T extends A<int>> {
+}
+class A<T extends int> {
+}
+B<A<int>> v;
+''');
+  }
+
+  test_instantiateToBounds_typeName_OK_hasBound_definedBefore() async {
+    var unit = await checkFileElement(r'''
+class A<T extends int> {}
+class B<T extends A> {}
+B v = null;
+''');
+    checkElementText(unit.library, r'''
+class A<T extends int> {
+}
+class B<T extends A<int>> {
+}
+B<A<int>> v;
+''');
+  }
+
+  test_instantiateToBounds_typeName_OK_inBound_hasBound_definedAfter() async {
+    var unit = await checkFileElement(r'''
+A v = null;
+class A<T extends int> {}
+''');
+    checkElementText(unit.library, r'''
+class A<T extends int> {
+}
+A<int> v;
+''');
+  }
+
+  test_instantiateToBounds_typeName_OK_inBound_hasBound_definedBefore() async {
+    var unit = await checkFileElement(r'''
+class A<T extends int> {}
+A v = null;
+''');
+    checkElementText(unit.library, r'''
+class A<T extends int> {
+}
+A<int> v;
+''');
+  }
+
+  test_instantiateToBounds_typeName_OK_noBound() async {
+    var unit = await checkFileElement(r'''
+class A<T> {}
+class B<T extends A> {}
+B v = null;
+''');
+    checkElementText(unit.library, r'''
+class A<T> {
+}
+class B<T extends A<dynamic>> {
+}
+B<A<dynamic>> v;
+''');
   }
 
   test_lambdaDoesNotHavePropagatedTypeHint() async {
@@ -4354,11 +4430,34 @@
   bool get hasExtraTaskModelPass => false;
 
   @override
+  test_instantiateToBounds_typeName_OK_hasBound_definedAfter() async {
+    await super.test_instantiateToBounds_typeName_OK_hasBound_definedAfter();
+  }
+
+  @override
+  test_listLiteralsCanInferNull_topLevel() =>
+      super.test_listLiteralsCanInferNull_topLevel();
+
+  @override
+  test_mapLiteralsCanInferNull_topLevel() =>
+      super.test_mapLiteralsCanInferNull_topLevel();
+
+  @override
+  test_nullCoalescingOperator() async {
+    await super.test_nullCoalescingOperator();
+  }
+
+  @override
   test_circularReference_viaClosures() async {
     await super.test_circularReference_viaClosures();
   }
 
   @override
+  test_unsafeBlockClosureInference_closureCall() async {
+    await super.test_unsafeBlockClosureInference_closureCall();
+  }
+
+  @override
   test_circularReference_viaClosures_initializerTypes() async {
     await super.test_circularReference_viaClosures_initializerTypes();
   }
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 f1c59c2..bd0f90a 100644
--- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
+++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -26,6 +26,7 @@
 import 'package:front_end/src/base/performance_logger.dart';
 import 'package:source_span/source_span.dart';
 import 'package:test/test.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 
 import '../../context/mock_sdk.dart';
 
diff --git a/pkg/analyzer/test/src/util/absolute_path_test.dart b/pkg/analyzer/test/src/util/absolute_path_test.dart
deleted file mode 100644
index 42c8449..0000000
--- a/pkg/analyzer/test/src/util/absolute_path_test.dart
+++ /dev/null
@@ -1,141 +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.
-
-library analyzer.test.src.util.absolute_path_test;
-
-import 'package:analyzer/src/util/absolute_path.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(AbsolutePathContextPosixTest);
-    defineReflectiveTests(AbsolutePathContextWindowsTest);
-  });
-}
-
-@reflectiveTest
-class AbsolutePathContextPosixTest {
-  AbsolutePathContext context = new AbsolutePathContext(false);
-
-  void test_append() {
-    expect(context.append(r'/path/to', r'foo.dart'), r'/path/to/foo.dart');
-  }
-
-  void test_basename() {
-    expect(context.basename(r'/path/to/foo.dart'), r'foo.dart');
-    expect(context.basename(r'/path/to'), r'to');
-    expect(context.basename(r'/path'), r'path');
-    expect(context.basename(r'/'), r'');
-  }
-
-  void test_dirname() {
-    expect(context.dirname(r'/path/to/foo.dart'), r'/path/to');
-    expect(context.dirname(r'/path/to'), r'/path');
-    expect(context.dirname(r'/path'), r'/');
-    expect(context.dirname(r'/'), r'/');
-  }
-
-  void test_isValid_absolute() {
-    expect(context.isValid(r'/foo/bar'), isTrue);
-    expect(context.isValid(r'/foo'), isTrue);
-    expect(context.isValid(r'/'), isTrue);
-    expect(context.isValid(r''), isFalse);
-    expect(context.isValid(r'foo/bar'), isFalse);
-  }
-
-  void test_isValid_normalized() {
-    expect(context.isValid(r'/foo/bar'), isTrue);
-    expect(context.isValid(r'/foo/..bar'), isTrue);
-    expect(context.isValid(r'/foo/.bar/baz'), isTrue);
-    expect(context.isValid(r'/foo/...'), isTrue);
-    expect(context.isValid(r'/foo/bar..'), isTrue);
-    expect(context.isValid(r'/foo/.../bar'), isTrue);
-    expect(context.isValid(r'/foo/.bar/.'), isFalse);
-    expect(context.isValid(r'/foo/bar/../baz'), isFalse);
-    expect(context.isValid(r'/foo/bar/..'), isFalse);
-    expect(context.isValid(r'/foo/./bar'), isFalse);
-    expect(context.isValid(r'/.'), isFalse);
-  }
-
-  void test_isWithin() {
-    expect(context.isWithin(r'/root/path', r'/root/path/a'), isTrue);
-    expect(context.isWithin(r'/root/path', r'/root/other'), isFalse);
-    expect(context.isWithin(r'/root/path', r'/root/path'), isFalse);
-  }
-
-  void test_split() {
-    expect(context.split(r'/path/to/foo'), [r'', r'path', r'to', r'foo']);
-    expect(context.split(r'/path'), [r'', r'path']);
-  }
-
-  void test_suffix() {
-    expect(context.suffix(r'/root/path', r'/root/path/a/b.dart'), r'a/b.dart');
-    expect(context.suffix(r'/root/path', r'/root/other.dart'), isNull);
-  }
-}
-
-@reflectiveTest
-class AbsolutePathContextWindowsTest {
-  AbsolutePathContext context = new AbsolutePathContext(true);
-
-  void test_append() {
-    expect(context.append(r'C:\path\to', r'foo.dart'), r'C:\path\to\foo.dart');
-  }
-
-  void test_basename() {
-    expect(context.basename(r'C:\path\to\foo.dart'), r'foo.dart');
-    expect(context.basename(r'C:\path\to'), r'to');
-    expect(context.basename(r'C:\path'), r'path');
-    expect(context.basename(r'C:\'), r'');
-  }
-
-  void test_dirname() {
-    expect(context.dirname(r'C:\path\to\foo.dart'), r'C:\path\to');
-    expect(context.dirname(r'C:\path\to'), r'C:\path');
-    expect(context.dirname(r'C:\path'), r'C:\');
-    expect(context.dirname(r'C:\'), r'C:\');
-  }
-
-  void test_isValid_absolute() {
-    expect(context.isValid(r'C:\foo\bar'), isTrue);
-    expect(context.isValid(r'c:\foo\bar'), isTrue);
-    expect(context.isValid(r'D:\foo\bar'), isTrue);
-    expect(context.isValid(r'C:\foo'), isTrue);
-    expect(context.isValid(r'C:\'), isTrue);
-    expect(context.isValid(r''), isFalse);
-    expect(context.isValid(r'foo\bar'), isFalse);
-  }
-
-  void test_isValid_normalized() {
-    expect(context.isValid(r'C:\foo\bar'), isTrue);
-    expect(context.isValid(r'C:\foo\..bar'), isTrue);
-    expect(context.isValid(r'C:\foo\.bar\baz'), isTrue);
-    expect(context.isValid(r'C:\foo\...'), isTrue);
-    expect(context.isValid(r'C:\foo\bar..'), isTrue);
-    expect(context.isValid(r'C:\foo\...\bar'), isTrue);
-    expect(context.isValid(r'C:\foo\.bar\.'), isFalse);
-    expect(context.isValid(r'C:\foo\bar\..\baz'), isFalse);
-    expect(context.isValid(r'C:\foo\bar\..'), isFalse);
-    expect(context.isValid(r'C:\foo\.\bar'), isFalse);
-    expect(context.isValid(r'C:\.'), isFalse);
-  }
-
-  void test_isWithin() {
-    expect(context.isWithin(r'C:\root\path', r'C:\root\path\a'), isTrue);
-    expect(context.isWithin(r'C:\root\path', r'C:\root\other'), isFalse);
-    expect(context.isWithin(r'C:\root\path', r'C:\root\path'), isFalse);
-  }
-
-  void test_split() {
-    expect(context.split(r'C:\path\to\foo'), [r'C:', r'path', r'to', r'foo']);
-    expect(context.split(r'C:\path'), [r'C:', r'path']);
-  }
-
-  void test_suffix() {
-    expect(
-        context.suffix(r'C:\root\path', r'C:\root\path\a\b.dart'), r'a\b.dart');
-    expect(context.suffix(r'C:\root\path', r'C:\root\other.dart'), isNull);
-  }
-}
diff --git a/pkg/analyzer/test/src/util/test_all.dart b/pkg/analyzer/test/src/util/test_all.dart
index de12251..d9cd7bd 100644
--- a/pkg/analyzer/test/src/util/test_all.dart
+++ b/pkg/analyzer/test/src/util/test_all.dart
@@ -6,7 +6,6 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'absolute_path_test.dart' as absolute_path_test;
 import 'asserts_test.dart' as asserts_test;
 import 'glob_test.dart' as glob_test;
 import 'lru_map_test.dart' as lru_map_test;
@@ -15,7 +14,6 @@
 /// Utility for manually running all tests.
 main() {
   defineReflectiveSuite(() {
-    absolute_path_test.main();
     asserts_test.main();
     glob_test.main();
     lru_map_test.main();
diff --git a/pkg/analyzer/tool/task_dependency_graph/generate.dart b/pkg/analyzer/tool/task_dependency_graph/generate.dart
index e3ddb67..53477e1 100644
--- a/pkg/analyzer/tool/task_dependency_graph/generate.dart
+++ b/pkg/analyzer/tool/task_dependency_graph/generate.dart
@@ -15,8 +15,6 @@
  *   of exactly one task.
  * - Convert this tool to use package_config to find the package map.
  */
-library analyzer.tool.task_dependency_graph.generate;
-
 import 'dart:async';
 import 'dart:io' hide File;
 import 'dart:io' as io;
@@ -24,19 +22,19 @@
 import 'package:analyzer/analyzer.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
+import 'package:analyzer/src/file_system/file_system.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';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:front_end/src/api_prototype/byte_store.dart';
 import 'package:front_end/src/base/performance_logger.dart';
 import 'package:front_end/src/codegen/tools.dart';
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index ca20983..492de93 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -9,13 +9,12 @@
 import 'package:analyzer/file_system/file_system.dart' as file_system;
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/plugin/resolver_provider.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/interner.dart';
@@ -25,8 +24,10 @@
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/utilities_general.dart'
     show PerformanceTag;
+import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:analyzer/src/pubspec/pubspec_validator.dart';
 import 'package:analyzer/src/source/package_map_provider.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer/src/source/path_filter.dart';
 import 'package:analyzer/src/source/pub_package_map_provider.dart';
 import 'package:analyzer/src/source/sdk_ext.dart';
@@ -509,7 +510,7 @@
         resolvers
             .add(new InSummaryUriResolver(resourceProvider, summaryDataStore));
         resolvers.add(resolver);
-        resolvers.add(new file_system.ResourceUriResolver(resourceProvider));
+        resolvers.add(new ResourceUriResolver(resourceProvider));
         return new SourceFactory(resolvers);
       }
     }
@@ -579,7 +580,7 @@
     }
 
     // Finally files.
-    resolvers.add(new file_system.ResourceUriResolver(resourceProvider));
+    resolvers.add(new ResourceUriResolver(resourceProvider));
 
     return new SourceFactory(resolvers, packageInfo.packages);
   }
diff --git a/pkg/analyzer_cli/lib/starter.dart b/pkg/analyzer_cli/lib/starter.dart
index 206fff6..40d480c 100644
--- a/pkg/analyzer_cli/lib/starter.dart
+++ b/pkg/analyzer_cli/lib/starter.dart
@@ -2,11 +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.
 
-library analyzer_cli.starter;
-
 import 'dart:async';
 
-import 'package:analyzer/plugin/resolver_provider.dart';
+import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:analyzer_cli/src/driver.dart';
 import 'package:plugin/plugin.dart';
 
diff --git a/pkg/analyzer_cli/tool/perf.dart b/pkg/analyzer_cli/tool/perf.dart
index 4aa3aa6..3e622c8 100644
--- a/pkg/analyzer_cli/tool/perf.dart
+++ b/pkg/analyzer_cli/tool/perf.dart
@@ -3,25 +3,23 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// An entrypoint used to run portions of analyzer and measure its performance.
-library analyzer_cli.tool.perf;
-
 import 'dart:async';
 import 'dart:io' show exit;
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/file_system/file_system.dart' show ResourceUriResolver;
 import 'package:analyzer/file_system/physical_file_system.dart'
     show PhysicalResourceProvider;
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk;
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:package_config/discovery.dart';
 
 main(List<String> args) async {
diff --git a/pkg/analyzer_plugin/test/support/abstract_context.dart b/pkg/analyzer_plugin/test/support/abstract_context.dart
index e5b4622..844b487 100644
--- a/pkg/analyzer_plugin/test/support/abstract_context.dart
+++ b/pkg/analyzer_plugin/test/support/abstract_context.dart
@@ -11,16 +11,17 @@
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.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';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/engine.dart' as engine;
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/testing/element_search.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 
 import 'mock_sdk.dart';
 
diff --git a/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart b/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart
index 6bb494c..9211a5e 100644
--- a/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart
+++ b/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart
@@ -6,8 +6,8 @@
 
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/src/utilities/completion/completion_core.dart';
 import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 140d9e8..04c300e 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -18,6 +18,8 @@
 import 'universe/call_structure.dart' show CallStructure;
 import 'universe/selector.dart' show Selector;
 import 'universe/call_structure.dart';
+import 'universe/world_builder.dart';
+import 'world.dart';
 
 /// The common elements and types in Dart.
 class CommonElements {
@@ -160,11 +162,39 @@
         _findConstructor(symbolImplementationClass, '');
   }
 
+  bool _computedSymbolConstructorDependencies = false;
+  ConstructorEntity _symbolConstructorImplementationTarget;
+
+  void _ensureSymbolConstructorDependencies() {
+    if (_computedSymbolConstructorDependencies) return;
+    _computedSymbolConstructorDependencies = true;
+    if (_symbolConstructorTarget == null) {
+      if (_symbolImplementationClass == null) {
+        _symbolImplementationClass =
+            _findClass(internalLibrary, 'Symbol', required: false);
+      }
+      if (_symbolImplementationClass != null) {
+        _symbolConstructorTarget =
+            _findConstructor(_symbolImplementationClass, '', required: false);
+      }
+    }
+    if (_symbolClass == null) {
+      _symbolClass = _findClass(coreLibrary, 'Symbol', required: false);
+    }
+    if (_symbolClass == null) {
+      return;
+    }
+    _symbolConstructorImplementationTarget =
+        _findConstructor(symbolClass, '', required: false);
+  }
+
   /// Whether [element] is the same as [symbolConstructor]. Used to check
   /// for the constructor without computing it until it is likely to be seen.
   bool isSymbolConstructor(ConstructorEntity element) {
-    return element == symbolConstructorTarget ||
-        element == _findConstructor(symbolClass, '', required: false);
+    assert(element != null);
+    _ensureSymbolConstructorDependencies();
+    return element == _symbolConstructorImplementationTarget ||
+        element == _symbolConstructorTarget;
   }
 
   /// The `MirrorSystem` class in dart:mirrors.
@@ -698,10 +728,13 @@
   ClassEntity get jsUInt31Class =>
       _jsUInt31Class ??= _findInterceptorsClass('JSUInt31');
 
-  FunctionEntity _findIndexForNativeSubclassType;
-  FunctionEntity get findIndexForNativeSubclassType =>
-      _findIndexForNativeSubclassType ??= _findLibraryMember(
-          interceptorsLibrary, 'findIndexForNativeSubclassType');
+  /// Returns `true` member is the 'findIndexForNativeSubclassType' method
+  /// declared in `dart:_interceptors`.
+  bool isFindIndexForNativeSubclassType(MemberEntity member) {
+    return member.name == 'findIndexForNativeSubclassType' &&
+        member.isTopLevel &&
+        member.library == interceptorsLibrary;
+  }
 
   FunctionEntity _getInterceptorMethod;
   FunctionEntity get getInterceptorMethod =>
@@ -712,9 +745,10 @@
       _getNativeInterceptorMethod ??=
           _findInterceptorsFunction('getNativeInterceptor');
 
-  MemberEntity _jsIndexableLength;
-  MemberEntity get jsIndexableLength =>
-      _jsIndexableLength ??= _findClassMember(jsIndexableClass, 'length');
+  /// Returns `true` if [selector] applies to `JSIndexable.length`.
+  bool appliesToJsIndexableLength(Selector selector) {
+    return selector.name == 'length' && (selector.isGetter || selector.isCall);
+  }
 
   ConstructorEntity _jsArrayTypedConstructor;
   ConstructorEntity get jsArrayTypedConstructor =>
@@ -728,6 +762,33 @@
   FunctionEntity get jsArrayAdd =>
       _jsArrayAdd ??= _findClassMember(jsArrayClass, 'add');
 
+  bool isJsStringClass(ClassEntity cls) {
+    return cls.name == 'JSString' && cls.library == interceptorsLibrary;
+  }
+
+  bool isJsStringSplit(MemberEntity member) {
+    return member.name == 'split' &&
+        member.isInstanceMember &&
+        isJsStringClass(member.enclosingClass);
+  }
+
+  /// Returns `true` if [selector] applies to `JSString.split` on [receiver]
+  /// in the given [world].
+  ///
+  /// Returns `false` if `JSString.split` is not available.
+  bool appliesToJsStringSplit(
+      Selector selector, ReceiverConstraint receiver, World world) {
+    if (_jsStringSplit == null) {
+      ClassEntity cls =
+          _findClass(interceptorsLibrary, 'JSString', required: false);
+      if (cls == null) return false;
+      _jsStringSplit = _findClassMember(cls, 'split', required: false);
+      if (_jsStringSplit == null) return false;
+    }
+    return selector.applies(_jsStringSplit) &&
+        (receiver == null || receiver.canHit(jsStringSplit, selector, world));
+  }
+
   FunctionEntity _jsStringSplit;
   FunctionEntity get jsStringSplit =>
       _jsStringSplit ??= _findClassMember(jsStringClass, 'split');
@@ -1122,6 +1183,12 @@
       _env.lookupLibrary(Uris.dart__native_typed_data, required: true),
       'NativeTypedArrayOfInt');
 
+  ClassEntity _typedArrayOfDoubleClass;
+  ClassEntity get typedArrayOfDoubleClass =>
+      _typedArrayOfDoubleClass ??= _findClass(
+          _env.lookupLibrary(Uris.dart__native_typed_data, required: true),
+          'NativeTypedArrayOfDouble');
+
   // From dart:_js_embedded_names
 
   /// Holds the class for the [JsGetName] enum.
@@ -1420,6 +1487,11 @@
   /// Returns the function type variables defined on [function].
   List<TypeVariableType> getFunctionTypeVariables(FunctionEntity function);
 
+  /// Returns the 'element' type of a function with an async, async* ot sync*
+  /// marker. The return type of the method is inspected to determine the type
+  /// parameter of the Future, Stream or Iterable.
+  DartType getFunctionAsyncOrSyncStarElementType(FunctionEntity function);
+
   /// Returns the type of [field].
   DartType getFieldType(FieldEntity field);
 
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index e63edc3..7bc310e 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -170,6 +170,12 @@
 
   bool compilationFailed = false;
 
+  // Callback function used for testing resolution enqueuing.
+  void Function() onResolutionQueueEmptyForTesting;
+
+  // Callback function used for testing codegen enqueuing.
+  void Function() onCodegenQueueEmptyForTesting;
+
   Compiler(
       {CompilerOptions options,
       api.CompilerOutput outputProvider,
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index ad5e6f2..e97726c 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -128,7 +128,9 @@
       compiler.globalInference.results.resultOfParameter(e);
 
   FieldInfo visitField(FieldEntity field) {
-    if (!_hasBeenResolved(field)) return null;
+    if (!_hasBeenResolved(field)) {
+      return null;
+    }
     TypeMask inferredType = _resultOfMember(field).type;
     // If a field has an empty inferred type it is never used.
     if (inferredType == null || inferredType.isEmpty) return null;
@@ -163,6 +165,12 @@
     return info;
   }
 
+  bool _hasBeenResolved(MemberEntity entity) {
+    return compiler.globalInference.typesInferrerInternal.inferrer.types
+        .memberTypeInformations
+        .containsKey(entity);
+  }
+
   ClassInfo visitClass(ClassEntity clazz) {
     // Omit class if it is not needed.
     if (!_hasClassBeenResolved(clazz)) return null;
@@ -372,11 +380,6 @@
     return _infoFromOutputUnit(outputUnit);
   }
 
-  bool _hasBeenResolved(Entity entity) {
-    return compiler.enqueuer.codegenEnqueuerForTesting.processedEntities
-        .contains(entity);
-  }
-
   bool _hasClassBeenResolved(ClassEntity cls) {
     return compiler.backend.mirrorsData.isClassResolved(cls);
   }
diff --git a/pkg/compiler/lib/src/elements/resolution_types.dart b/pkg/compiler/lib/src/elements/resolution_types.dart
index 2ae43fa..4b80a11 100644
--- a/pkg/compiler/lib/src/elements/resolution_types.dart
+++ b/pkg/compiler/lib/src/elements/resolution_types.dart
@@ -162,6 +162,12 @@
   /// Is [: true :] if this type contains any type variables.
   bool get containsTypeVariables => typeVariableOccurrence != null;
 
+  bool get containsFreeTypeVariables {
+    assert(!containsMethodTypeVariableType,
+        'Used only after removing method type variables');
+    return containsTypeVariables;
+  }
+
   /// Returns a textual representation of this type as if it was the type
   /// of a member named [name].
   String getStringAsDeclared(String name) {
@@ -1233,10 +1239,12 @@
   }
 
   bool isPotentialSubtype(
-      covariant ResolutionDartType t, covariant ResolutionDartType s) {
+      covariant ResolutionDartType t, covariant ResolutionDartType s,
+      {bool assumeInstantiations: true}) {
     // TODO(johnniwinther): Return a set of variable points in the positive
     // cases.
-    return potentialSubtypeVisitor.isSubtype(t, s);
+    return potentialSubtypeVisitor.isPotentialSubtype(t, s,
+        assumeInstantiations: assumeInstantiations);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index c2110c7..b60700f 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -74,6 +74,12 @@
   /// Whether this type contains a type variable.
   bool get containsTypeVariables => false;
 
+  /// Whether this type contains a free class type variable or function type
+  /// variable.
+  // TODO(sra): Review uses of [containsTypeVariables] for update with
+  // [containsFreeTypeVariables].
+  bool get containsFreeTypeVariables => _containsFreeTypeVariables(null);
+
   /// Is `true` if this type is the 'Object' type defined in 'dart:core'.
   bool get isObject => false;
 
@@ -96,6 +102,8 @@
   R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument);
 
   bool _equals(DartType other, _Assumptions assumptions);
+
+  bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) => false;
 }
 
 /// Pairs of [FunctionTypeVariable]s that are currently assumed to be equivalent.
@@ -173,6 +181,11 @@
     typeArguments.forEach((type) => type.forEachTypeVariable(f));
   }
 
+  bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) {
+    return typeArguments
+        .any((type) => type._containsFreeTypeVariables(bindings));
+  }
+
   InterfaceType subst(List<DartType> arguments, List<DartType> parameters) {
     if (typeArguments.isEmpty) {
       // Return fast on non-generic types.
@@ -263,6 +276,9 @@
     typeArguments.forEach((type) => type.forEachTypeVariable(f));
   }
 
+  bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) =>
+      typeArguments.any((type) => type._containsFreeTypeVariables(bindings));
+
   TypedefType subst(List<DartType> arguments, List<DartType> parameters) {
     if (typeArguments.isEmpty) {
       // Return fast on non-generic types.
@@ -350,6 +366,8 @@
 
   @override
   bool get isMalformed => true;
+
+  bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) => false;
 }
 
 class TypeVariableType extends DartType {
@@ -365,6 +383,8 @@
     f(this);
   }
 
+  bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) => true;
+
   DartType subst(List<DartType> arguments, List<DartType> parameters) {
     assert(arguments.length == parameters.length);
     if (parameters.isEmpty) {
@@ -433,6 +453,12 @@
   @override
   bool get isFunctionTypeVariable => true;
 
+  bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) {
+    if (bindings == null) return true;
+    if (bindings.indexOf(this) >= 0) return false;
+    return true;
+  }
+
   DartType subst(List<DartType> arguments, List<DartType> parameters) {
     assert(arguments.length == parameters.length);
     if (parameters.isEmpty) {
@@ -564,6 +590,29 @@
     namedParameterTypes.forEach((type) => type.forEachTypeVariable(f));
   }
 
+  bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) {
+    int restore;
+    if (typeVariables.isNotEmpty) {
+      if (bindings == null) {
+        bindings = <FunctionTypeVariable>[];
+      } else {
+        restore = bindings.length;
+      }
+      bindings.addAll(typeVariables);
+    }
+
+    bool hasFree(DartType type) => type._containsFreeTypeVariables(bindings);
+
+    bool result = hasFree(returnType) ||
+        typeVariables.any((type) => hasFree(type.bound)) ||
+        parameterTypes.any(hasFree) ||
+        optionalParameterTypes.any(hasFree) ||
+        namedParameterTypes.any(hasFree);
+
+    if (restore != null) bindings.length = restore;
+    return result;
+  }
+
   bool get isFunctionType => true;
 
   DartType subst(List<DartType> arguments, List<DartType> parameters) {
@@ -674,7 +723,7 @@
         }
       }
     }
-    bool result = returnType == other.returnType &&
+    bool result = returnType._equals(other.returnType, assumptions) &&
         _equalTypes(parameterTypes, other.parameterTypes, assumptions) &&
         _equalTypes(optionalParameterTypes, other.optionalParameterTypes,
             assumptions) &&
@@ -778,6 +827,9 @@
     typeArgument.forEachTypeVariable(f);
   }
 
+  bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) =>
+      typeArgument._containsFreeTypeVariables(bindings);
+
   R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
       visitor.visitFutureOrType(this, argument);
 
@@ -981,29 +1033,37 @@
     if (s is! FunctionType) return false;
     FunctionType tf = t;
     FunctionType sf = s;
-    if (invalidFunctionReturnTypes(tf.returnType, sf.returnType)) {
+    int typeVariablesCount = getCommonTypeVariablesCount(tf, sf);
+    if (typeVariablesCount == null) {
       return false;
     }
-
-    if (tf.typeVariables.length != sf.typeVariables.length) {
-      return false;
-    }
-    for (int i = 0; i < tf.typeVariables.length; i++) {
+    for (int i = 0; i < typeVariablesCount; i++) {
       assumptions.assume(tf.typeVariables[i], sf.typeVariables[i]);
     }
-    for (int i = 0; i < tf.typeVariables.length; i++) {
+    for (int i = 0; i < typeVariablesCount; i++) {
       if (!tf.typeVariables[i].bound
           ._equals(sf.typeVariables[i].bound, assumptions)) {
         return false;
       }
     }
+    if (invalidFunctionReturnTypes(tf.returnType, sf.returnType)) {
+      return false;
+    }
+
     bool result = visitFunctionTypeInternal(tf, sf);
-    for (int i = 0; i < tf.typeVariables.length; i++) {
+    for (int i = 0; i < typeVariablesCount; i++) {
       assumptions.forget(tf.typeVariables[i], sf.typeVariables[i]);
     }
     return result;
   }
 
+  int getCommonTypeVariablesCount(FunctionType t, FunctionType s) {
+    if (t.typeVariables.length == s.typeVariables.length) {
+      return t.typeVariables.length;
+    }
+    return null;
+  }
+
   bool visitFunctionTypeInternal(FunctionType tf, FunctionType sf) {
     // TODO(johnniwinther): Rewrite the function subtyping to be more readable
     // but still as efficient.
@@ -1249,12 +1309,34 @@
 /// `false` only if we are sure no such substitution exists.
 abstract class PotentialSubtypeVisitor<T extends DartType>
     extends SubtypeVisitor<T> {
+  bool _assumeInstantiations = true;
+
   bool isSubtype(DartType t, DartType s) {
     if (t is TypeVariableType || s is TypeVariableType) {
       return true;
     }
+    if ((t is FunctionTypeVariable || s is FunctionTypeVariable) &&
+        _assumeInstantiations) {
+      return true;
+    }
     return super.isSubtype(t, s);
   }
+
+  int getCommonTypeVariablesCount(FunctionType t, FunctionType s) {
+    if (t.typeVariables.length == s.typeVariables.length) {
+      return t.typeVariables.length;
+    }
+    if (_assumeInstantiations && s.typeVariables.length == 0) {
+      return 0;
+    }
+    return null;
+  }
+
+  bool isPotentialSubtype(DartType t, DartType s,
+      {bool assumeInstantiations: true}) {
+    _assumeInstantiations = assumeInstantiations;
+    return isSubtype(t, s);
+  }
 }
 
 /// Basic interface for the Dart type system.
@@ -1270,7 +1352,11 @@
 
   /// Returns `true` if [t] might be a subtype of [s] for some values of
   /// type variables in [s] and [t].
-  bool isPotentialSubtype(DartType t, DartType s);
+  ///
+  /// If [assumeInstantiations], generic function types are assumed to be
+  /// potentially instantiated.
+  bool isPotentialSubtype(DartType t, DartType s,
+      {bool assumeInstantiations: true});
 
   static const int IS_SUBTYPE = 1;
   static const int MAYBE_SUBTYPE = 0;
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 6fa0f01..0abf135 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -55,13 +55,15 @@
   }
 
   ResolutionEnqueuer createResolutionEnqueuer() {
-    return _resolution ??=
-        compiler.backend.createResolutionEnqueuer(this, compiler);
+    return _resolution ??= compiler.backend
+        .createResolutionEnqueuer(this, compiler)
+          ..onEmptyForTesting = compiler.onResolutionQueueEmptyForTesting;
   }
 
   Enqueuer createCodegenEnqueuer(ClosedWorld closedWorld) {
-    return codegenEnqueuerForTesting =
-        compiler.backend.createCodegenEnqueuer(this, compiler, closedWorld);
+    return codegenEnqueuerForTesting = compiler.backend
+        .createCodegenEnqueuer(this, compiler, closedWorld)
+          ..onEmptyForTesting = compiler.onCodegenQueueEmptyForTesting;
   }
 }
 
@@ -213,6 +215,10 @@
   /// has been emptied.
   final Queue<DeferredAction> _deferredQueue = new Queue<DeferredAction>();
 
+  // If not `null` this is called when the queue has been emptied. It allows for
+  // applying additional impacts before re-emptying the queue.
+  void Function() onEmptyForTesting;
+
   ResolutionEnqueuer(this.task, this._options, this._reporter, this.strategy,
       this.listener, this._worldBuilder, this._workItemBuilder,
       [this.name = 'resolution enqueuer']) {
@@ -396,7 +402,7 @@
     _worldBuilder.registerClosurizedMember(element);
   }
 
-  void forEach(void f(WorkItem work)) {
+  void _forEach(void f(WorkItem work)) {
     do {
       while (_queue.isNotEmpty) {
         // TODO(johnniwinther): Find an optimal process order.
@@ -418,6 +424,14 @@
         _recentConstants);
   }
 
+  void forEach(void f(WorkItem work)) {
+    _forEach(f);
+    if (onEmptyForTesting != null) {
+      onEmptyForTesting();
+      _forEach(f);
+    }
+  }
+
   void logSummary(void log(String message)) {
     log('Resolved ${processedEntities.length} elements.');
     listener.logSummary(log);
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index 100fbdb..6d6b2f5 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -1634,7 +1634,8 @@
 
     TypeInformation rhsType = visit(node.value);
     MemberEntity member = _elementMap.getSuperMember(
-        _analyzedMember, node.name, node.interfaceTarget);
+        _analyzedMember, node.name, node.interfaceTarget,
+        setter: true);
     TypeMask mask = _memberData.typeOfSend(node);
     Selector selector = new Selector.setter(_elementMap.getName(node.name));
     ArgumentsTypes arguments = new ArgumentsTypes([rhsType], null);
diff --git a/pkg/compiler/lib/src/js/js_debug.dart b/pkg/compiler/lib/src/js/js_debug.dart
index 8851aa6..f58853e 100644
--- a/pkg/compiler/lib/src/js/js_debug.dart
+++ b/pkg/compiler/lib/src/js/js_debug.dart
@@ -12,10 +12,10 @@
 import '../util/util.dart' show Indentation, Tagging;
 
 /// Unparse the JavaScript [node].
-String nodeToString(Node node) {
+String nodeToString(Node node, {bool pretty: false}) {
   JavaScriptPrintingOptions options = new JavaScriptPrintingOptions(
-      shouldCompressOutput: true,
-      preferSemicolonToNewlineInMinifiedOutput: true);
+      shouldCompressOutput: !pretty,
+      preferSemicolonToNewlineInMinifiedOutput: !pretty);
   LenientPrintingContext printingContext = new LenientPrintingContext();
   new Printer(options, printingContext).visit(node);
   return printingContext.getText();
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index b69771e..c26521e 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -1739,6 +1739,7 @@
   ///
   /// Specific to async methods.
   final js.Expression completerFactory;
+  final js.Expression completerFactoryTypeArgument;
 
   final js.Expression wrapBody;
 
@@ -1748,6 +1749,7 @@
       this.asyncReturn,
       this.asyncRethrow,
       this.completerFactory,
+      this.completerFactoryTypeArgument,
       this.wrapBody,
       String safeVariableName(String proposedName),
       js.Name bodyName})
@@ -1799,8 +1801,10 @@
     List<js.VariableInitialization> variables = <js.VariableInitialization>[];
     variables.add(_makeVariableInitializer(
         completer,
-        new js.Call(completerFactory, [])
-            .withSourceInformation(sourceInformation),
+        js.js('#(#)', [
+          completerFactory,
+          completerFactoryTypeArgument
+        ]).withSourceInformation(sourceInformation),
         sourceInformation));
     if (analysis.hasExplicitReturns) {
       variables
@@ -1900,6 +1904,7 @@
   /// Constructor creating the Iterable for a sync* method. Called with
   /// [bodyName].
   final js.Expression iterableFactory;
+  final js.Expression iterableFactoryTypeArgument;
 
   /// A JS Expression that creates a marker showing that iteration is over.
   ///
@@ -1917,6 +1922,7 @@
   SyncStarRewriter(DiagnosticReporter diagnosticListener, spannable,
       {this.endOfIteration,
       this.iterableFactory,
+      this.iterableFactoryTypeArgument,
       this.yieldStarExpression,
       this.uncaughtErrorExpression,
       String safeVariableName(String proposedName),
@@ -2009,8 +2015,9 @@
       "returnInnerInnerFunction": returnInnerInnerFunction,
     }).withSourceInformation(functionSourceInformation);
     js.Expression callIterableFactory =
-        js.js("#iterableFactory(#innerFunction)", {
+        js.js("#iterableFactory(#innerFunction, #type)", {
       "iterableFactory": iterableFactory,
+      "type": iterableFactoryTypeArgument,
       "innerFunction": innerFunction,
     }).withSourceInformation(bodySourceInformation);
     js.Statement returnCallIterableFactory = new js.Return(callIterableFactory)
@@ -2108,6 +2115,7 @@
   ///
   /// Specific to async* methods.
   final js.Expression newController;
+  final js.Expression newControllerTypeArgument;
 
   /// Used to get the `Stream` out of the [controllerName] variable.
   final js.Expression streamOfController;
@@ -2128,6 +2136,7 @@
       {this.asyncStarHelper,
       this.streamOfController,
       this.newController,
+      this.newControllerTypeArgument,
       this.yieldExpression,
       this.yieldStarExpression,
       this.wrapBody,
@@ -2317,8 +2326,11 @@
     List<js.VariableInitialization> variables = <js.VariableInitialization>[];
     variables.add(_makeVariableInitializer(
         controller,
-        js.js('#(#)', [newController, bodyName]).withSourceInformation(
-            sourceInformation),
+        js.js('#(#, #)', [
+          newController,
+          bodyName,
+          newControllerTypeArgument
+        ]).withSourceInformation(sourceInformation),
         sourceInformation));
     if (analysis.hasYield) {
       variables.add(
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 4043360..dd73a35 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -764,7 +764,9 @@
             rtiNeedBuilder,
             _nativeResolutionEnqueuer,
             noSuchMethodRegistry,
-            const OpenWorldStrategy(),
+            compiler.options.strongMode && useStrongModeWorldStrategy
+                ? const StrongModeWorldStrategy()
+                : const OpenWorldStrategy(),
             classHierarchyBuilder,
             classQueries),
         compiler.frontendStrategy.createResolutionWorkItemBuilder(
@@ -1154,35 +1156,20 @@
 
   jsAst.Expression rewriteAsync(
       CommonElements commonElements,
+      ElementEnvironment elementEnvironment,
       FunctionEntity element,
       jsAst.Expression code,
       SourceInformation bodySourceInformation,
       SourceInformation exitSourceInformation) {
-    bool startAsyncSynchronously = compiler.options.startAsyncSynchronously;
+    if (element.asyncMarker == AsyncMarker.SYNC) return code;
 
     AsyncRewriterBase rewriter = null;
     jsAst.Name name = namer.methodPropertyName(element);
+
     switch (element.asyncMarker) {
       case AsyncMarker.ASYNC:
-        var startFunction = startAsyncSynchronously
-            ? commonElements.asyncHelperStartSync
-            : commonElements.asyncHelperStart;
-        var completerConstructor = startAsyncSynchronously
-            ? commonElements.asyncAwaitCompleterConstructor
-            : commonElements.syncCompleterConstructor;
-        rewriter = new AsyncRewriter(reporter, element,
-            asyncStart: emitter.staticFunctionAccess(startFunction),
-            asyncAwait:
-                emitter.staticFunctionAccess(commonElements.asyncHelperAwait),
-            asyncReturn:
-                emitter.staticFunctionAccess(commonElements.asyncHelperReturn),
-            asyncRethrow:
-                emitter.staticFunctionAccess(commonElements.asyncHelperRethrow),
-            wrapBody: emitter.staticFunctionAccess(commonElements.wrapBody),
-            completerFactory:
-                emitter.staticFunctionAccess(completerConstructor),
-            safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
-            bodyName: namer.deriveAsyncBodyName(name));
+        rewriter = _makeAsyncRewriter(
+            commonElements, elementEnvironment, element, code, name);
         break;
       case AsyncMarker.SYNC_STAR:
         rewriter = new SyncStarRewriter(reporter, element,
@@ -1190,6 +1177,8 @@
                 emitter.staticFunctionAccess(commonElements.endOfIteration),
             iterableFactory: emitter.staticFunctionAccess(
                 commonElements.syncStarIterableConstructor),
+            iterableFactoryTypeArgument:
+                _fetchItemType(element, elementEnvironment),
             yieldStarExpression:
                 emitter.staticFunctionAccess(commonElements.yieldStar),
             uncaughtErrorExpression: emitter
@@ -1206,6 +1195,8 @@
             wrapBody: emitter.staticFunctionAccess(commonElements.wrapBody),
             newController: emitter.staticFunctionAccess(
                 commonElements.asyncStarControllerConstructor),
+            newControllerTypeArgument:
+                _fetchItemType(element, elementEnvironment),
             safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
             yieldExpression:
                 emitter.staticFunctionAccess(commonElements.yieldSingle),
@@ -1213,13 +1204,60 @@
                 emitter.staticFunctionAccess(commonElements.yieldStar),
             bodyName: namer.deriveAsyncBodyName(name));
         break;
-      default:
-        assert(element.asyncMarker == AsyncMarker.SYNC);
-        return code;
     }
     return rewriter.rewrite(code, bodySourceInformation, exitSourceInformation);
   }
 
+  /// Returns an expression that evaluates the type argument to the
+  /// Future/Stream/Iterable.
+  jsAst.Expression _fetchItemType(
+      FunctionEntity element, ElementEnvironment elementEnvironment) {
+    DartType type =
+        elementEnvironment.getFunctionAsyncOrSyncStarElementType(element);
+
+    if (!type.containsFreeTypeVariables) {
+      return rtiEncoder.getTypeRepresentation(emitter.emitter, type, null);
+    }
+
+    // TODO(sra): Handle types that have type variables.
+    return js('null');
+  }
+
+  AsyncRewriter _makeAsyncRewriter(
+      CommonElements commonElements,
+      ElementEnvironment elementEnvironment,
+      FunctionEntity element,
+      jsAst.Expression code,
+      jsAst.Name name) {
+    bool startAsyncSynchronously = compiler.options.startAsyncSynchronously;
+
+    var startFunction = startAsyncSynchronously
+        ? commonElements.asyncHelperStartSync
+        : commonElements.asyncHelperStart;
+    var completerConstructor = startAsyncSynchronously
+        ? commonElements.asyncAwaitCompleterConstructor
+        : commonElements.syncCompleterConstructor;
+
+    jsAst.Expression itemTypeExpression =
+        _fetchItemType(element, elementEnvironment);
+
+    var rewriter = new AsyncRewriter(reporter, element,
+        asyncStart: emitter.staticFunctionAccess(startFunction),
+        asyncAwait:
+            emitter.staticFunctionAccess(commonElements.asyncHelperAwait),
+        asyncReturn:
+            emitter.staticFunctionAccess(commonElements.asyncHelperReturn),
+        asyncRethrow:
+            emitter.staticFunctionAccess(commonElements.asyncHelperRethrow),
+        wrapBody: emitter.staticFunctionAccess(commonElements.wrapBody),
+        completerFactory: emitter.staticFunctionAccess(completerConstructor),
+        completerFactoryTypeArgument: itemTypeExpression,
+        safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
+        bodyName: namer.deriveAsyncBodyName(name));
+
+    return rewriter;
+  }
+
   /// Creates an impact strategy to use for compilation.
   ImpactStrategy createImpactStrategy(
       {bool supportDeferredLoad: true, bool supportDumpInfo: true}) {
diff --git a/pkg/compiler/lib/src/js_backend/backend_usage.dart b/pkg/compiler/lib/src/js_backend/backend_usage.dart
index 056757e..c69a632 100644
--- a/pkg/compiler/lib/src/js_backend/backend_usage.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_usage.dart
@@ -47,6 +47,9 @@
 
   /// `true` if `noSuchMethod` is used.
   bool get isNoSuchMethodUsed;
+
+  /// `true` if generic instantiation is used.
+  bool get isGenericInstantiationUsed;
 }
 
 abstract class BackendUsageBuilder {
@@ -87,6 +90,9 @@
   /// `true` if `noSuchMethod` is used.
   bool isNoSuchMethodUsed;
 
+  /// `true` if generic instantiation is used.
+  bool isGenericInstantiationUsed;
+
   BackendUsage close();
 }
 
@@ -126,6 +132,9 @@
   /// `true` if `noSuchMethod` is used.
   bool isNoSuchMethodUsed = false;
 
+  /// `true` if generic instantiation is used.
+  bool isGenericInstantiationUsed = false;
+
   BackendUsageBuilderImpl(this._commonElements);
 
   @override
@@ -284,7 +293,8 @@
         isIsolateInUse: isIsolateInUse,
         isFunctionApplyUsed: isFunctionApplyUsed,
         isMirrorsUsed: isMirrorsUsed,
-        isNoSuchMethodUsed: isNoSuchMethodUsed);
+        isNoSuchMethodUsed: isNoSuchMethodUsed,
+        isGenericInstantiationUsed: isGenericInstantiationUsed);
   }
 }
 
@@ -323,6 +333,9 @@
   /// `true` if `noSuchMethod` is used.
   final bool isNoSuchMethodUsed;
 
+  /// `true` if generic instantiation is used.
+  final bool isGenericInstantiationUsed;
+
   BackendUsageImpl(
       {Set<FunctionEntity> globalFunctionDependencies,
       Set<ClassEntity> globalClassDependencies,
@@ -336,7 +349,8 @@
       this.isIsolateInUse,
       this.isFunctionApplyUsed,
       this.isMirrorsUsed,
-      this.isNoSuchMethodUsed})
+      this.isNoSuchMethodUsed,
+      this.isGenericInstantiationUsed})
       : this._globalFunctionDependencies = globalFunctionDependencies,
         this._globalClassDependencies = globalClassDependencies,
         this._helperFunctionsUsed = helperFunctionsUsed,
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 c2c7d83..4aec501 100644
--- a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
+++ b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
@@ -296,7 +296,7 @@
       return 'list$suffix';
     }
 
-    if (commonElements.isListSupertype(element)) {
+    if (commonElements.isListSupertype(element) && type.treatAsRaw) {
       return nativeCheck ? 'listSuperNative$suffix' : 'listSuper$suffix';
     }
 
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 29c6db8..4b27e24 100644
--- a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
@@ -73,7 +73,7 @@
 
   void registerStaticUse(MemberEntity element) {
     assert(element != null);
-    if (element == _commonElements.findIndexForNativeSubclassType) {
+    if (_commonElements.isFindIndexForNativeSubclassType(element)) {
       join.demanded = true;
     }
   }
diff --git a/pkg/compiler/lib/src/js_backend/enqueuer.dart b/pkg/compiler/lib/src/js_backend/enqueuer.dart
index ae9ab20..4e72531 100644
--- a/pkg/compiler/lib/src/js_backend/enqueuer.dart
+++ b/pkg/compiler/lib/src/js_backend/enqueuer.dart
@@ -50,6 +50,10 @@
   /// All declaration elements that have been processed by codegen.
   final Set<MemberEntity> _processedEntities = new Set<MemberEntity>();
 
+  // If not `null` this is called when the queue has been emptied. It allows for
+  // applying additional impacts before re-emptying the queue.
+  void Function() onEmptyForTesting;
+
   static const ImpactUseCase IMPACT_USE =
       const ImpactUseCase('CodegenEnqueuer');
 
@@ -228,7 +232,7 @@
     _worldBuilder.registerClosurizedMember(element);
   }
 
-  void forEach(void f(WorkItem work)) {
+  void _forEach(void f(WorkItem work)) {
     do {
       while (_queue.isNotEmpty) {
         // TODO(johnniwinther): Find an optimal process order.
@@ -248,6 +252,14 @@
         _queue.isNotEmpty || _recentClasses.isNotEmpty || _recentConstants);
   }
 
+  void forEach(void f(WorkItem work)) {
+    _forEach(f);
+    if (onEmptyForTesting != null) {
+      onEmptyForTesting();
+      _forEach(f);
+    }
+  }
+
   /// [_onQueueEmpty] is called whenever the queue is drained. [recentClasses]
   /// contains the set of all classes seen for the first time since
   /// [_onQueueEmpty] was called last. A return value of [true] indicates that
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index 32282b9..27b074b 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -41,7 +41,7 @@
   final BackendImpacts _impacts;
   final NativeBasicData _nativeBasicData;
   final NativeResolutionEnqueuer _nativeResolutionEnqueuer;
-  final BackendUsageBuilder _backendUsageBuider;
+  final BackendUsageBuilder _backendUsageBuilder;
   final MirrorsDataBuilder _mirrorsDataBuilder;
   final CustomElementsResolutionAnalysis _customElementsResolutionAnalysis;
   final RuntimeTypesNeedBuilder _rtiNeedBuilder;
@@ -54,7 +54,7 @@
       this._impacts,
       this._nativeBasicData,
       this._nativeResolutionEnqueuer,
-      this._backendUsageBuider,
+      this._backendUsageBuilder,
       this._mirrorsDataBuilder,
       this._customElementsResolutionAnalysis,
       this._rtiNeedBuilder,
@@ -67,7 +67,7 @@
 
     void registerImpact(BackendImpact impact) {
       impact.registerImpact(transformed, _elementEnvironment);
-      _backendUsageBuider.processBackendImpact(impact);
+      _backendUsageBuilder.processBackendImpact(impact);
     }
 
     for (Feature feature in worldImpact.features) {
@@ -110,6 +110,7 @@
           break;
         case Feature.GENERIC_INSTANTIATION:
           registerImpact(_impacts.genericInstantiation);
+          _backendUsageBuilder.isGenericInstantiationUsed = true;
           break;
         case Feature.LAZY_FIELD:
           registerImpact(_impacts.lazyField);
@@ -251,7 +252,9 @@
           Local closure = staticUse.element;
           FunctionType type = _elementEnvironment.getLocalFunctionType(closure);
           if (type.containsTypeVariables ||
-              (_options.strongMode && !optimizeLocalSignaturesForStrongMode)) {
+              // TODO(johnniwinther): Can we avoid the need for signatures in
+              // Dart 2?
+              _options.strongMode) {
             registerImpact(_impacts.computeSignature);
           }
           break;
@@ -300,7 +303,7 @@
   void onIsCheck(DartType type, TransformedWorldImpact transformed) {
     void registerImpact(BackendImpact impact) {
       impact.registerImpact(transformed, _elementEnvironment);
-      _backendUsageBuider.processBackendImpact(impact);
+      _backendUsageBuilder.processBackendImpact(impact);
     }
 
     type = _elementEnvironment.getUnaliasedType(type);
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 813ea76..9c3dd7b 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -27,10 +27,6 @@
 
 bool cacheRtiDataForTesting = false;
 
-// TODO(johnniwinther): Remove this when local signatures are optimized for
-// Dart 2.
-const bool optimizeLocalSignaturesForStrongMode = false;
-
 /// For each class, stores the possible class subtype tests that could succeed.
 abstract class TypeChecks {
   /// Get the set of checks required for class [element].
@@ -1412,6 +1408,12 @@
       });
     }
 
+    Set<Local> localFunctions = strongMode
+        ? resolutionWorldBuilder.localFunctions.toSet()
+        : resolutionWorldBuilder.localFunctionsWithFreeTypeVariables.toSet();
+    Set<FunctionEntity> closurizedMembers =
+        resolutionWorldBuilder.closurizedMembersWithFreeTypeVariables.toSet();
+
     // Check local functions and closurized members.
     void checkClosures({DartType potentialSubtypeOf}) {
       bool checkFunctionType(FunctionType functionType) {
@@ -1426,32 +1428,51 @@
         return false;
       }
 
+      Set<Local> localFunctionsToRemove;
+      Set<FunctionEntity> closurizedMembersToRemove;
       if (strongMode) {
-        assert(!optimizeLocalSignaturesForStrongMode);
-        // TODO(johnniwinther): Optimize generation of signatures for Dart 2.
-        for (Local function in resolutionWorldBuilder.localFunctions) {
+        for (Local function in localFunctions) {
           FunctionType functionType =
               _elementEnvironment.getLocalFunctionType(function);
-          functionType.forEachTypeVariable((TypeVariableType typeVariable) {
-            potentiallyNeedTypeArguments(typeVariable.element.typeDeclaration);
-          });
-          localFunctionsNeedingSignature.add(function);
+          if (potentialSubtypeOf == null ||
+              closedWorld.dartTypes.isPotentialSubtype(
+                  functionType, potentialSubtypeOf,
+                  assumeInstantiations:
+                      closedWorld.backendUsage.isGenericInstantiationUsed)) {
+            functionType.forEachTypeVariable((TypeVariableType typeVariable) {
+              Entity typeDeclaration = typeVariable.element.typeDeclaration;
+              if (!processedEntities.contains(typeDeclaration)) {
+                potentiallyNeedTypeArguments(typeDeclaration);
+              }
+            });
+            localFunctionsNeedingSignature.add(function);
+            localFunctionsToRemove ??= new Set<Local>();
+            localFunctionsToRemove.add(function);
+          }
         }
       } else {
-        for (Local function
-            in resolutionWorldBuilder.localFunctionsWithFreeTypeVariables) {
+        for (Local function in localFunctions) {
           if (checkFunctionType(
               _elementEnvironment.getLocalFunctionType(function))) {
             localFunctionsNeedingSignature.add(function);
+            localFunctionsToRemove ??= new Set<Local>();
+            localFunctionsToRemove.add(function);
           }
         }
       }
-      for (FunctionEntity function
-          in resolutionWorldBuilder.closurizedMembersWithFreeTypeVariables) {
+      for (FunctionEntity function in closurizedMembers) {
         if (checkFunctionType(_elementEnvironment.getFunctionType(function))) {
           methodsNeedingSignature.add(function);
+          closurizedMembersToRemove ??= new Set<FunctionEntity>();
+          closurizedMembersToRemove.add(function);
         }
       }
+      if (localFunctionsToRemove != null) {
+        localFunctions.removeAll(localFunctionsToRemove);
+      }
+      if (closurizedMembersToRemove != null) {
+        closurizedMembers.removeAll(closurizedMembersToRemove);
+      }
     }
 
     // Compute the set of all classes and methods that need runtime type
diff --git a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
index 14177b0..eae6858 100644
--- a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
@@ -315,7 +315,10 @@
         return null;
       }
       jsAst.Expression arrayCheck = js('receiver.constructor == Array');
-      jsAst.Expression indexableCheck =
+
+      // Lazy generation of the indexable check. If indexable behavior isn't
+      // used, the isJsIndexable function isn't part of the closed world.
+      jsAst.Expression genericIndexableCheck() =>
           _generateIsJsIndexableCall(js('receiver'), js('receiver'));
 
       jsAst.Expression orExp(left, right) {
@@ -333,7 +336,7 @@
         }
 
         if (containsJsIndexable) {
-          typeCheck = orExp(typeCheck, indexableCheck);
+          typeCheck = orExp(typeCheck, genericIndexableCheck());
         }
 
         return js.statement('''
@@ -349,7 +352,7 @@
         }
 
         if (containsJsIndexable) {
-          typeCheck = orExp(typeCheck, indexableCheck);
+          typeCheck = orExp(typeCheck, genericIndexableCheck());
         }
 
         return js.statement(r'''
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 ad8f33b..5e3279f 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
@@ -635,6 +635,7 @@
 
     List<StaticMethod> statics = memberElements
         .where((e) => !e.isField)
+        .cast<FunctionEntity>()
         .map(_buildStaticMethod)
         .toList();
 
diff --git a/pkg/compiler/lib/src/js_emitter/sorter.dart b/pkg/compiler/lib/src/js_emitter/sorter.dart
index d3cfff6..70fbd51 100644
--- a/pkg/compiler/lib/src/js_emitter/sorter.dart
+++ b/pkg/compiler/lib/src/js_emitter/sorter.dart
@@ -19,7 +19,7 @@
   Iterable<TypedefEntity> sortTypedefs(Iterable<TypedefEntity> typedefs);
 
   /// Returns a sorted list of [members].
-  Iterable<MemberEntity> sortMembers(Iterable<MemberEntity> members);
+  Iterable<T> sortMembers<T extends MemberEntity>(Iterable<T> members);
 
   int compareLibrariesByLocation(LibraryEntity a, LibraryEntity b);
   int compareClassesByLocation(ClassEntity a, ClassEntity b);
@@ -63,7 +63,7 @@
   }
 
   @override
-  List<MemberEntity> sortMembers(Iterable<MemberEntity> members) {
+  Iterable<T> sortMembers<T extends MemberEntity>(Iterable<T> members) {
     return Elements.sortedByPosition(new List.from(members, growable: false));
   }
 
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index a56afcf..9334b52 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -16,6 +16,7 @@
 import '../kernel/env.dart';
 import '../options.dart';
 import '../ssa/type_builder.dart';
+import '../universe/selector.dart';
 import '../world.dart';
 import 'elements.dart';
 import 'closure_visitors.dart';
@@ -77,6 +78,7 @@
 class KernelClosureConversionTask extends ClosureConversionTask<ir.Node> {
   final KernelToElementMapForBuilding _elementMap;
   final GlobalLocalsMap _globalLocalsMap;
+  final CompilerOptions _options;
 
   /// Map of the scoping information that corresponds to a particular entity.
   Map<MemberEntity, ScopeInfo> _scopeMap = <MemberEntity, ScopeInfo>{};
@@ -93,19 +95,8 @@
   Map<ir.TreeNode, ClosureRepresentationInfo> _localClosureRepresentationMap =
       <ir.TreeNode, ClosureRepresentationInfo>{};
 
-  /// If true add type assertions to assert that at runtime the type is in line
-  /// with the stated type.
-  final bool _addTypeChecks;
-
-  /// If true, we are compiling using strong mode, and therefore we will create
-  /// a "signatureMethod" for a closure that can output the type. In this
-  /// instance, we may need access to a type variable that has not otherwise
-  /// been captured, and therefore we need to mark it as being used so that the
-  /// RTI optimization doesn't optimize it away..
-  final bool _strongMode;
-
-  KernelClosureConversionTask(Measurer measurer, this._elementMap,
-      this._globalLocalsMap, this._addTypeChecks, this._strongMode)
+  KernelClosureConversionTask(
+      Measurer measurer, this._elementMap, this._globalLocalsMap, this._options)
       : super(measurer);
 
   /// The combined steps of generating our intermediate representation of
@@ -118,68 +109,127 @@
   void convertClosures(Iterable<MemberEntity> processedEntities,
       ClosedWorldRefiner closedWorldRefiner) {}
 
-  void _updateScopeBasedOnRtiNeed(
-      KernelScopeInfo scope,
-      bool Function(ClassEntity) classNeedsTypeArguments,
-      bool Function(MemberEntity) methodNeedsTypeArguments,
-      bool Function(ir.Node) localFunctionNeedsTypeArguments,
+  void _updateScopeBasedOnRtiNeed(KernelScopeInfo scope, ClosureRtiNeed rtiNeed,
       MemberEntity outermostEntity) {
-    if (scope.thisUsedAsFreeVariableIfNeedsRti &&
-        (classNeedsTypeArguments(outermostEntity.enclosingClass) ||
-            // TODO(johnniwinther): Instead of _strongMode, make this branch test
-            // if an added signature method needs type arguments (see comment in
-            // TypeVariableKind.method branch below.
-            _strongMode)) {
-      scope.thisUsedAsFreeVariable = true;
-    }
-    if (_addTypeChecks) {
-      scope.freeVariables.addAll(scope.freeVariablesForRti);
-    } else {
-      for (TypeVariableTypeWithContext typeVariable
-          in scope.freeVariablesForRti) {
-        switch (typeVariable.kind) {
-          case TypeVariableKind.cls:
-            if (classNeedsTypeArguments(
-                _elementMap.getClass(typeVariable.typeDeclaration))) {
-              scope.freeVariables.add(typeVariable);
+    bool includeForRti(Set<VariableUse> useSet) {
+      for (VariableUse usage in useSet) {
+        switch (usage.kind) {
+          case VariableUseKind.explicit:
+            return true;
+            break;
+          case VariableUseKind.implicitCast:
+            if (_options.implicitDowncastCheckPolicy.isEmitted) {
+              return true;
             }
             break;
-          case TypeVariableKind.method:
-            if (methodNeedsTypeArguments(
-                    _elementMap.getMember(typeVariable.typeDeclaration)) ||
-                // In Dart 2, we have the notion of generic methods. This is
-                // partly implemented by adding a "method signature" function to
-                // closure classes. This signature reports the type of the
-                // method, and therefore may access the type variable of the
-                // parameter, which might otherwise not be used (and therefore
-                // isn't captured in the set that `methodNeedsTypeArguments`
-                // compares against.
-                // TODO(johnniwinther): Include this reasoning inside
-                // [methodNeedsTypeArguments] rather than an add on here.
-                _strongMode &&
-                    scope.freeVariablesForRti.contains(typeVariable)) {
-              scope.freeVariables.add(typeVariable);
+          case VariableUseKind.localType:
+            if (_options.assignmentCheckPolicy.isEmitted) {
+              return true;
             }
             break;
-          case TypeVariableKind.local:
-            if (localFunctionNeedsTypeArguments(typeVariable.typeDeclaration)) {
-              scope.freeVariables.add(typeVariable);
+
+          case VariableUseKind.constructorTypeArgument:
+            ConstructorEntity constructor =
+                _elementMap.getConstructor(usage.member);
+            if (rtiNeed.classNeedsTypeArguments(constructor.enclosingClass)) {
+              return true;
             }
             break;
-          case TypeVariableKind.function:
+          case VariableUseKind.staticTypeArgument:
+            FunctionEntity method = _elementMap.getMethod(usage.member);
+            if (rtiNeed.methodNeedsTypeArguments(method)) {
+              return true;
+            }
+            break;
+          case VariableUseKind.instanceTypeArgument:
+            Selector selector = _elementMap.getSelector(usage.invocation);
+            if (rtiNeed.selectorNeedsTypeArguments(selector)) {
+              return true;
+            }
+            break;
+          case VariableUseKind.localTypeArgument:
+            // TODO(johnniwinther): We should be able to track direct local
+            // function invocations and not have to use the selector here.
+            Selector selector = _elementMap.getSelector(usage.invocation);
+            if (rtiNeed.localFunctionNeedsTypeArguments(usage.localFunction) ||
+                rtiNeed.selectorNeedsTypeArguments(selector)) {
+              return true;
+            }
+            break;
+          case VariableUseKind.memberParameter:
+            if (_options.parameterCheckPolicy.isEmitted) {
+              return true;
+            } else {
+              FunctionEntity method = _elementMap.getMethod(usage.member);
+              if (rtiNeed.methodNeedsSignature(method)) {
+                return true;
+              }
+            }
+            break;
+          case VariableUseKind.localParameter:
+            if (_options.parameterCheckPolicy.isEmitted) {
+              return true;
+            } else if (rtiNeed
+                .localFunctionNeedsSignature(usage.localFunction)) {
+              return true;
+            }
+            break;
+          case VariableUseKind.memberReturnType:
+            if (_options.assignmentCheckPolicy.isEmitted) {
+              return true;
+            } else {
+              FunctionEntity method = _elementMap.getMethod(usage.member);
+              if (rtiNeed.methodNeedsSignature(method)) {
+                return true;
+              }
+            }
+            break;
+          case VariableUseKind.localReturnType:
+            if (_options.assignmentCheckPolicy.isEmitted) {
+              return true;
+            } else if (rtiNeed
+                .localFunctionNeedsSignature(usage.localFunction)) {
+              return true;
+            }
+            break;
+          case VariableUseKind.fieldType:
+            if (_options.assignmentCheckPolicy.isEmitted ||
+                _options.parameterCheckPolicy.isEmitted) {
+              return true;
+            }
+            break;
+          case VariableUseKind.listLiteral:
+            if (rtiNeed.classNeedsTypeArguments(
+                _elementMap.commonElements.jsArrayClass)) {
+              return true;
+            }
+            break;
+          case VariableUseKind.mapLiteral:
+            if (rtiNeed.classNeedsTypeArguments(
+                _elementMap.commonElements.mapLiteralClass)) {
+              return true;
+            }
             break;
         }
       }
+      return false;
     }
+
+    if (includeForRti(scope.thisUsedAsFreeVariableIfNeedsRti)) {
+      scope.thisUsedAsFreeVariable = true;
+    }
+    scope.freeVariablesForRti.forEach(
+        (TypeVariableTypeWithContext typeVariable, Set<VariableUse> useSet) {
+      if (includeForRti(useSet)) {
+        scope.freeVariables.add(typeVariable);
+      }
+    });
   }
 
   Iterable<FunctionEntity> createClosureEntities(
       JsClosedWorldBuilder closedWorldBuilder,
       Map<MemberEntity, ScopeModel> closureModels,
-      {bool Function(ir.Node) localFunctionNeedsSignature,
-      bool Function(ClassEntity) classNeedsTypeArguments,
-      bool Function(FunctionEntity) methodNeedsTypeArguments,
-      bool Function(ir.Node) localFunctionNeedsTypeArguments}) {
+      ClosureRtiNeed rtiNeed) {
     List<FunctionEntity> callMethods = <FunctionEntity>[];
     closureModels.forEach((MemberEntity member, ScopeModel model) {
       KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(member);
@@ -192,8 +242,7 @@
           .forEach((ir.Node node, KernelCapturedScope scope) {
         Map<Local, JRecordField> boxedVariables =
             _elementMap.makeRecordContainer(scope, member, localsMap);
-        _updateScopeBasedOnRtiNeed(scope, classNeedsTypeArguments,
-            methodNeedsTypeArguments, localFunctionNeedsTypeArguments, member);
+        _updateScopeBasedOnRtiNeed(scope, rtiNeed, member);
 
         if (scope is KernelCapturedLoopScope) {
           _capturedScopesMap[node] = new JsCapturedLoopScope.from(
@@ -222,11 +271,9 @@
             functionNode,
             closuresToGenerate[node],
             allBoxedVariables,
-            classNeedsTypeArguments,
-            methodNeedsTypeArguments,
-            localFunctionNeedsTypeArguments,
+            rtiNeed,
             createSignatureMethod:
-                localFunctionNeedsSignature(functionNode.parent));
+                rtiNeed.localFunctionNeedsSignature(functionNode.parent));
         // Add also for the call method.
         _scopeMap[closureClassInfo.callMethod] = closureClassInfo;
         _scopeMap[closureClassInfo.signatureMethod] = closureClassInfo;
@@ -234,19 +281,14 @@
         // Set up capturedScope for signature method. This is distinct from
         // _capturedScopesMap because there is no corresponding ir.Node for the
         // signature.
-        if (localFunctionNeedsSignature(functionNode.parent) &&
+        if (rtiNeed.localFunctionNeedsSignature(functionNode.parent) &&
             model.capturedScopesMap[functionNode] != null) {
           KernelCapturedScope capturedScope =
               model.capturedScopesMap[functionNode];
           assert(capturedScope is! KernelCapturedLoopScope);
           KernelCapturedScope signatureCapturedScope =
               new KernelCapturedScope.forSignature(capturedScope);
-          _updateScopeBasedOnRtiNeed(
-              signatureCapturedScope,
-              classNeedsTypeArguments,
-              methodNeedsTypeArguments,
-              localFunctionNeedsTypeArguments,
-              member);
+          _updateScopeBasedOnRtiNeed(signatureCapturedScope, rtiNeed, member);
           _capturedScopeForSignatureMap[closureClassInfo.signatureMethod] =
               new JsCapturedScope.from(
                   {}, signatureCapturedScope, localsMap, _elementMap);
@@ -269,12 +311,9 @@
       ir.FunctionNode node,
       KernelScopeInfo info,
       Map<Local, JRecordField> boxedVariables,
-      bool Function(ClassEntity) classNeedsTypeArguments,
-      bool Function(FunctionEntity) methodNeedsTypeArguments,
-      bool Function(ir.Node) localFunctionNeedsTypeArguments,
+      ClosureRtiNeed rtiNeed,
       {bool createSignatureMethod}) {
-    _updateScopeBasedOnRtiNeed(info, classNeedsTypeArguments,
-        methodNeedsTypeArguments, localFunctionNeedsTypeArguments, member);
+    _updateScopeBasedOnRtiNeed(info, rtiNeed, member);
     KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(member);
     KernelClosureClassInfo closureClassInfo =
         closedWorldBuilder.buildClosureClass(
@@ -355,6 +394,150 @@
   }
 }
 
+enum VariableUseKind {
+  /// An explicit variable use.
+  ///
+  /// For type variable this is an explicit as-cast, an is-test or a type
+  /// literal.
+  explicit,
+
+  /// A type variable used in the type of a local variable.
+  localType,
+
+  /// A type variable used in an implicit cast.
+  implicitCast,
+
+  /// A type variable passed as the type argument of a list literal.
+  listLiteral,
+
+  /// A type variable passed as the type argument of a map literal.
+  mapLiteral,
+
+  /// A type variable passed as a type argument to a constructor.
+  constructorTypeArgument,
+
+  /// A type variable passed as a type argument to a static method.
+  staticTypeArgument,
+
+  /// A type variable passed as a type argument to an instance method.
+  instanceTypeArgument,
+
+  /// A type variable passed as a type argument to a local function.
+  localTypeArgument,
+
+  /// A type variable in a parameter type of a member.
+  memberParameter,
+
+  /// A type variable in a parameter type of a local function.
+  localParameter,
+
+  /// A type variable used in a return type of a member.
+  memberReturnType,
+
+  /// A type variable used in a return type of a local function.
+  localReturnType,
+
+  /// A type variable in a field type.
+  fieldType,
+}
+
+class VariableUse {
+  final VariableUseKind kind;
+  final ir.Member member;
+  final ir.TreeNode /*ir.FunctionDeclaration|ir.FunctionExpression*/
+      localFunction;
+  final ir.MethodInvocation invocation;
+
+  const VariableUse._simple(this.kind)
+      : this.member = null,
+        this.localFunction = null,
+        this.invocation = null;
+
+  VariableUse.memberParameter(this.member)
+      : this.kind = VariableUseKind.memberParameter,
+        this.localFunction = null,
+        this.invocation = null;
+
+  VariableUse.localParameter(this.localFunction)
+      : this.kind = VariableUseKind.localParameter,
+        this.member = null,
+        this.invocation = null {
+    assert(localFunction is ir.FunctionDeclaration ||
+        localFunction is ir.FunctionExpression);
+  }
+
+  VariableUse.memberReturnType(this.member)
+      : this.kind = VariableUseKind.memberReturnType,
+        this.localFunction = null,
+        this.invocation = null;
+
+  VariableUse.localReturnType(this.localFunction)
+      : this.kind = VariableUseKind.localReturnType,
+        this.member = null,
+        this.invocation = null {
+    assert(localFunction is ir.FunctionDeclaration ||
+        localFunction is ir.FunctionExpression);
+  }
+
+  VariableUse.constructorTypeArgument(this.member)
+      : this.kind = VariableUseKind.constructorTypeArgument,
+        this.localFunction = null,
+        this.invocation = null;
+
+  VariableUse.staticTypeArgument(this.member)
+      : this.kind = VariableUseKind.staticTypeArgument,
+        this.localFunction = null,
+        this.invocation = null;
+
+  VariableUse.instanceTypeArgument(this.invocation)
+      : this.kind = VariableUseKind.instanceTypeArgument,
+        this.member = null,
+        this.localFunction = null;
+
+  VariableUse.localTypeArgument(this.localFunction, this.invocation)
+      : this.kind = VariableUseKind.localTypeArgument,
+        this.member = null {
+    assert(localFunction is ir.FunctionDeclaration ||
+        localFunction is ir.FunctionExpression);
+  }
+
+  static const VariableUse explicit =
+      const VariableUse._simple(VariableUseKind.explicit);
+
+  static const VariableUse localType =
+      const VariableUse._simple(VariableUseKind.localType);
+
+  static const VariableUse implicitCast =
+      const VariableUse._simple(VariableUseKind.implicitCast);
+
+  static const VariableUse listLiteral =
+      const VariableUse._simple(VariableUseKind.listLiteral);
+
+  static const VariableUse mapLiteral =
+      const VariableUse._simple(VariableUseKind.mapLiteral);
+
+  static const VariableUse fieldType =
+      const VariableUse._simple(VariableUseKind.fieldType);
+
+  int get hashCode =>
+      kind.hashCode * 11 +
+      member.hashCode * 13 +
+      localFunction.hashCode * 17 +
+      invocation.hashCode * 19;
+
+  bool operator ==(other) {
+    if (identical(this, other)) return true;
+    if (other is! VariableUse) return false;
+    return kind == other.kind &&
+        member == other.member &&
+        localFunction == other.localFunction &&
+        invocation == other.invocation;
+  }
+
+  String toString() => 'VariableUse(kind=$kind,member=$member,'
+      'localFunction=$localFunction,invocation=$invocation)';
+}
+
 class KernelScopeInfo {
   final Set<ir.VariableDeclaration> localsUsedInTryOrSync;
   final bool hasThisLocal;
@@ -375,8 +558,8 @@
   /// freeVariables set. Whether these variables are actually used as
   /// freeVariables will be set by the time this structure is converted to a
   /// JsScopeInfo, so JsScopeInfo does not need to use them.
-  Set<TypeVariableTypeWithContext> freeVariablesForRti =
-      new Set<TypeVariableTypeWithContext>();
+  Map<TypeVariableTypeWithContext, Set<VariableUse>> freeVariablesForRti =
+      <TypeVariableTypeWithContext, Set<VariableUse>>{};
 
   /// If true, `this` is used as a free variable, in this scope. It is stored
   /// separately from [freeVariables] because there is no single
@@ -387,7 +570,7 @@
   /// performing runtime type checks. It is stored
   /// separately from [thisUsedAsFreeVariable] because we don't know at this
   /// stage if we will be needing type checks for this scope.
-  bool thisUsedAsFreeVariableIfNeedsRti = false;
+  Set<VariableUse> thisUsedAsFreeVariableIfNeedsRti = new Set<VariableUse>();
 
   KernelScopeInfo(this.hasThisLocal)
       : localsUsedInTryOrSync = new Set<ir.VariableDeclaration>(),
@@ -411,10 +594,16 @@
 
   String toString() {
     StringBuffer sb = new StringBuffer();
-    sb.write('this=$hasThisLocal,');
+    sb.write('KernelScopeInfo(this=$hasThisLocal,');
     sb.write('freeVriables=$freeVariables,');
     sb.write('localsUsedInTryOrSync={${localsUsedInTryOrSync.join(', ')}}');
-    sb.write('freeVariablesForRti={${freeVariablesForRti.join(', ')}}');
+    String comma = '';
+    sb.write('freeVariablesForRti={');
+    freeVariablesForRti.forEach((key, value) {
+      sb.write('$comma$key:$value');
+      comma = ',';
+    });
+    sb.write('})');
     return sb.toString();
   }
 }
@@ -482,11 +671,11 @@
       Set<ir.VariableDeclaration> boxedVariables,
       NodeBox capturedVariablesAccessor,
       Set<ir.VariableDeclaration> localsUsedInTryOrSync,
-      Set<ir.Node /* VariableDeclaration | TypeParameterTypeWithContext */ >
+      Set<ir.Node /* VariableDeclaration | TypeVariableTypeWithContext */ >
           freeVariables,
-      Set<TypeVariableTypeWithContext> freeVariablesForRti,
+      Map<TypeVariableTypeWithContext, Set<VariableUse>> freeVariablesForRti,
       bool thisUsedAsFreeVariable,
-      bool thisUsedAsFreeVariableIfNeedsRti,
+      Set<VariableUse> thisUsedAsFreeVariableIfNeedsRti,
       bool hasThisLocal)
       : super.withBoxedVariables(
             boxedVariables,
@@ -541,11 +730,11 @@
       NodeBox capturedVariablesAccessor,
       this.boxedLoopVariables,
       Set<ir.VariableDeclaration> localsUsedInTryOrSync,
-      Set<ir.Node /* VariableDeclaration | TypeParameterTypeWithContext */ >
+      Set<ir.Node /* VariableDeclaration | TypeVariableTypeWithContext */ >
           freeVariables,
-      Set<TypeVariableTypeWithContext> freeVariablesForRti,
+      Map<TypeVariableTypeWithContext, Set<VariableUse>> freeVariablesForRti,
       bool thisUsedAsFreeVariable,
-      bool thisUsedAsFreeVariableIfNeedsRti,
+      Set<VariableUse> thisUsedAsFreeVariableIfNeedsRti,
       bool hasThisLocal)
       : super(
             boxedVariables,
@@ -959,3 +1148,17 @@
       'TypeVariableTypeWithContext(type=$type,context=$context,'
       'kind=$kind,typeDeclaration=$typeDeclaration)';
 }
+
+abstract class ClosureRtiNeed {
+  bool classNeedsTypeArguments(ClassEntity cls);
+
+  bool methodNeedsTypeArguments(FunctionEntity method);
+
+  bool methodNeedsSignature(MemberEntity method);
+
+  bool localFunctionNeedsTypeArguments(ir.Node node);
+
+  bool localFunctionNeedsSignature(ir.Node node);
+
+  bool selectorNeedsTypeArguments(Selector selector);
+}
diff --git a/pkg/compiler/lib/src/js_model/closure_visitors.dart b/pkg/compiler/lib/src/js_model/closure_visitors.dart
index 28bd0f1..ea35aaf 100644
--- a/pkg/compiler/lib/src/js_model/closure_visitors.dart
+++ b/pkg/compiler/lib/src/js_model/closure_visitors.dart
@@ -68,18 +68,16 @@
   /// have unique names.
   int _boxCounter = 0;
 
-  /// Set to `true` in the visitor if a type annotation is always needed.
+  /// The current usage of a type annotation.
   ///
-  /// This is for instance the case for expressions like `o is T` and `o as T`.
-  bool _contextNeedsType = false;
+  /// This is updated in the visitor to distinguish between unconditional
+  /// type variable usage, such as type literals and is tests, and conditional
+  /// type variable usage, such as type argument in method invocations.
+  VariableUse _currentTypeUsage;
 
   CapturedScopeBuilder(this._model, this._options, {bool hasThisLocal})
       : this._hasThisLocal = hasThisLocal;
 
-  /// If true add type assetions to assert that at runtime the type is in line
-  /// with the stated type.
-  bool get _addTypeChecks => _options.enableTypeAssertions;
-
   /// Update the [CapturedScope] object corresponding to
   /// this node if any variables are captured.
   void attachCapturedScopeVariables(ir.TreeNode node) {
@@ -179,25 +177,31 @@
 
   @override
   visitVariableGet(ir.VariableGet node) {
-    _markVariableAsUsed(node.variable);
-    node.visitChildren(this);
+    _markVariableAsUsed(node.variable, VariableUse.explicit);
+    // Don't visit `node.promotedType`.
   }
 
   @override
   visitVariableSet(ir.VariableSet node) {
     _mutatedVariables.add(node.variable);
-    _markVariableAsUsed(node.variable);
-    if (_addTypeChecks) node.variable.type.accept(this);
+    _markVariableAsUsed(node.variable, VariableUse.explicit);
+    visitInContext(node.variable.type, VariableUse.localType);
     node.visitChildren(this);
   }
 
-  @override
-  visitVariableDeclaration(ir.VariableDeclaration declaration) {
-    if (!declaration.isFieldFormal) {
-      _scopeVariables.add(declaration);
+  void handleVariableDeclaration(
+      ir.VariableDeclaration node, VariableUse usage) {
+    if (!node.isFieldFormal) {
+      _scopeVariables.add(node);
     }
 
-    declaration.visitChildren(this);
+    visitInContext(node.type, usage);
+    node.initializer?.accept(this);
+  }
+
+  @override
+  visitVariableDeclaration(ir.VariableDeclaration node) {
+    handleVariableDeclaration(node, VariableUse.localType);
   }
 
   /// Add this variable to the set of free variables if appropriate and add to
@@ -207,9 +211,10 @@
   /// checked.
   void _markVariableAsUsed(
       ir.Node /* VariableDeclaration | TypeParameterTypeWithContext */ variable,
-      {bool onlyForRtiChecks = false}) {
+      VariableUse usage) {
     assert(variable is ir.VariableDeclaration ||
         variable is TypeVariableTypeWithContext);
+    assert(usage != null);
     if (_isInsideClosure && !_inCurrentContext(variable)) {
       // If the element is not declared in the current function and the element
       // is not the closure itself we need to mark the element as free variable.
@@ -217,10 +222,12 @@
       // optimization: factories have type parameters as function
       // parameters, and type parameters are declared in the class, not
       // the factory.
-      if (!onlyForRtiChecks) {
+      if (usage == VariableUse.explicit) {
         _currentScopeInfo.freeVariables.add(variable);
       } else {
-        _currentScopeInfo.freeVariablesForRti.add(variable);
+        _currentScopeInfo.freeVariablesForRti
+            .putIfAbsent(variable, () => new Set<VariableUse>())
+            .add(usage);
       }
     }
     if (_inTry && variable is ir.VariableDeclaration) {
@@ -230,41 +237,36 @@
 
   @override
   void visitThisExpression(ir.ThisExpression thisExpression) {
-    if (_hasThisLocal) _registerNeedsThis();
+    if (_hasThisLocal) _registerNeedsThis(VariableUse.explicit);
   }
 
   @override
   void visitTypeParameter(ir.TypeParameter typeParameter) {
-    if (_addTypeChecks) {
-      ir.TreeNode context = _executableContext;
-      TypeVariableTypeWithContext typeVariable =
-          new TypeVariableTypeWithContext(
-              new ir.TypeParameterType(typeParameter),
-              // If this typeParameter is part of a typedef then its parent is
-              // null because it has no context. Just pass in null for the
-              // context in that case.
-              typeParameter.parent != null
-                  ? typeParameter.parent.parent
-                  : null);
-      if (_isInsideClosure && context is ir.Procedure && context.isFactory) {
-        // This is a closure in a factory constructor.  Since there is no
-        // [:this:], we have to mark the type arguments as free variables to
-        // capture them in the closure.
-        _useTypeVariableAsLocal(typeVariable);
-      }
+    ir.TreeNode context = _executableContext;
+    TypeVariableTypeWithContext typeVariable = new TypeVariableTypeWithContext(
+        new ir.TypeParameterType(typeParameter),
+        // If this typeParameter is part of a typedef then its parent is
+        // null because it has no context. Just pass in null for the
+        // context in that case.
+        typeParameter.parent != null ? typeParameter.parent.parent : null);
+    if (_isInsideClosure && context is ir.Procedure && context.isFactory) {
+      // This is a closure in a factory constructor.  Since there is no
+      // [:this:], we have to mark the type arguments as free variables to
+      // capture them in the closure.
+      _useTypeVariableAsLocal(typeVariable, _currentTypeUsage);
+    }
 
-      if (_executableContext is ir.Member && _executableContext is! ir.Field) {
-        // In checked mode, using a type variable in a type annotation may lead
-        // to a runtime type check that needs to access the type argument and
-        // therefore the closure needs a this-element, if it is not in a field
-        // initializer; field initializers are evaluated in a context where
-        // the type arguments are available in locals.
+    if (_executableContext is ir.Member && _executableContext is! ir.Field) {
+      // In checked mode, using a type variable in a type annotation may lead
+      // to a runtime type check that needs to access the type argument and
+      // therefore the closure needs a this-element, if it is not in a field
+      // initializer; field initializers are evaluated in a context where
+      // the type arguments are available in locals.
 
-        if (_hasThisLocal) {
-          _registerNeedsThis();
-        } else {
-          _useTypeVariableAsLocal(typeVariable);
-        }
+      if (_hasThisLocal) {
+        _registerNeedsThis(_currentTypeUsage);
+      } else {
+        _useTypeVariableAsLocal(typeVariable, _currentTypeUsage);
       }
     }
   }
@@ -274,12 +276,12 @@
   /// If [onlyIfNeedsRti] is true, set thisUsedAsFreeVariableIfNeedsRti to true
   /// instead of thisUsedAsFreeVariable as we will only use `this` if runtime
   /// type information is checked.
-  void _registerNeedsThis({bool onlyIfNeedsRti = false}) {
+  void _registerNeedsThis(VariableUse usage) {
     if (_isInsideClosure) {
-      if (!onlyIfNeedsRti) {
+      if (usage == VariableUse.explicit) {
         _currentScopeInfo.thisUsedAsFreeVariable = true;
       } else {
-        _currentScopeInfo.thisUsedAsFreeVariableIfNeedsRti = true;
+        _currentScopeInfo.thisUsedAsFreeVariableIfNeedsRti.add(usage);
       }
     }
   }
@@ -362,19 +364,30 @@
         scope.hasThisLocal);
   }
 
-  void visitSuperMethodInvocation(ir.SuperMethodInvocation invocation) {
-    if (_hasThisLocal) _registerNeedsThis();
-    invocation.visitChildren(this);
+  void visitSuperMethodInvocation(ir.SuperMethodInvocation node) {
+    if (_hasThisLocal) {
+      _registerNeedsThis(VariableUse.explicit);
+    }
+    if (node.arguments.types.isNotEmpty) {
+      visitListInContext(node.arguments.types,
+          new VariableUse.staticTypeArgument(node.interfaceTarget));
+    }
+    ir.visitList(node.arguments.positional, this);
+    ir.visitList(node.arguments.named, this);
   }
 
-  void visitSuperPropertySet(ir.SuperPropertySet propertySet) {
-    if (_hasThisLocal) _registerNeedsThis();
-    propertySet.visitChildren(this);
+  void visitSuperPropertySet(ir.SuperPropertySet node) {
+    if (_hasThisLocal) {
+      _registerNeedsThis(VariableUse.explicit);
+    }
+    node.visitChildren(this);
   }
 
-  void visitSuperPropertyGet(ir.SuperPropertyGet propertyGet) {
-    if (_hasThisLocal) _registerNeedsThis();
-    propertyGet.visitChildren(this);
+  void visitSuperPropertyGet(ir.SuperPropertyGet node) {
+    if (_hasThisLocal) {
+      _registerNeedsThis(VariableUse.explicit);
+    }
+    node.visitChildren(this);
   }
 
   void visitInvokable(ir.TreeNode node) {
@@ -417,16 +430,21 @@
     assert(freeVariables.isEmpty || savedIsInsideClosure);
     for (ir.Node freeVariable in freeVariables) {
       _capturedVariables.add(freeVariable);
-      _markVariableAsUsed(freeVariable);
+      _markVariableAsUsed(freeVariable, VariableUse.explicit);
     }
-    for (ir.Node freeVariableForRti in savedScopeInfo.freeVariablesForRti) {
-      _markVariableAsUsed(freeVariableForRti, onlyForRtiChecks: true);
-    }
+    savedScopeInfo.freeVariablesForRti.forEach(
+        (TypeVariableTypeWithContext freeVariableForRti,
+            Set<VariableUse> useSet) {
+      for (VariableUse usage in useSet) {
+        _markVariableAsUsed(freeVariableForRti, usage);
+      }
+    });
     if (_isInsideClosure && savedScopeInfo.thisUsedAsFreeVariable) {
       _currentScopeInfo.thisUsedAsFreeVariable = true;
     }
-    if (_isInsideClosure && savedScopeInfo.thisUsedAsFreeVariableIfNeedsRti) {
-      _currentScopeInfo.thisUsedAsFreeVariableIfNeedsRti = true;
+    if (_isInsideClosure) {
+      _currentScopeInfo.thisUsedAsFreeVariableIfNeedsRti
+          .addAll(savedScopeInfo.thisUsedAsFreeVariableIfNeedsRti);
     }
   }
 
@@ -447,7 +465,9 @@
 
   @override
   void visitField(ir.Field field) {
+    _currentTypeUsage = VariableUse.fieldType;
     visitInvokable(field);
+    _currentTypeUsage = null;
   }
 
   @override
@@ -472,32 +492,141 @@
 
   @override
   visitTypeParameterType(ir.TypeParameterType type) {
-    _analyzeTypeVariable(type, onlyIfNeedsRti: !_contextNeedsType);
+    _analyzeTypeVariable(type, _currentTypeUsage);
+  }
+
+  visitInContext(ir.Node node, VariableUse use) {
+    VariableUse oldCurrentTypeUsage = _currentTypeUsage;
+    _currentTypeUsage = use;
+    node?.accept(this);
+    _currentTypeUsage = oldCurrentTypeUsage;
+  }
+
+  visitListInContext(List<ir.Node> nodes, VariableUse use) {
+    VariableUse oldCurrentTypeUsage = _currentTypeUsage;
+    _currentTypeUsage = use;
+    ir.visitList(nodes, this);
+    _currentTypeUsage = oldCurrentTypeUsage;
+  }
+
+  visitChildrenInContext(ir.Node node, VariableUse use) {
+    VariableUse oldCurrentTypeUsage = _currentTypeUsage;
+    _currentTypeUsage = use;
+    node.visitChildren(this);
+    _currentTypeUsage = oldCurrentTypeUsage;
   }
 
   @override
   visitTypeLiteral(ir.TypeLiteral node) {
-    bool oldContextNeedsType = _contextNeedsType;
-    _contextNeedsType = true;
-    node.visitChildren(this);
-    _contextNeedsType = oldContextNeedsType;
+    visitChildrenInContext(node, VariableUse.explicit);
   }
 
   @override
   visitIsExpression(ir.IsExpression node) {
-    bool oldContextNeedsType = _contextNeedsType;
-    _contextNeedsType = true;
-    node.visitChildren(this);
-    _contextNeedsType = oldContextNeedsType;
+    node.operand.accept(this);
+    visitInContext(node.type, VariableUse.explicit);
   }
 
   @override
   visitAsExpression(ir.AsExpression node) {
-    bool oldContextNeedsType = _contextNeedsType;
-    _contextNeedsType =
-        !node.isTypeError || _options.implicitDowncastCheckPolicy.isEmitted;
-    node.visitChildren(this);
-    _contextNeedsType = oldContextNeedsType;
+    node.operand.accept(this);
+    visitInContext(node.type,
+        node.isTypeError ? VariableUse.implicitCast : VariableUse.explicit);
+  }
+
+  @override
+  visitFunctionNode(ir.FunctionNode node) {
+    VariableUse parameterUsage = node.parent is ir.Member
+        ? new VariableUse.memberParameter(node.parent)
+        : new VariableUse.localParameter(node.parent);
+    visitListInContext(node.typeParameters, parameterUsage);
+    for (ir.VariableDeclaration declaration in node.positionalParameters) {
+      handleVariableDeclaration(declaration, parameterUsage);
+    }
+    for (ir.VariableDeclaration declaration in node.namedParameters) {
+      handleVariableDeclaration(declaration, parameterUsage);
+    }
+    visitInContext(
+        node.returnType,
+        node.parent is ir.Member
+            ? new VariableUse.memberReturnType(node.parent)
+            : new VariableUse.localReturnType(node.parent));
+    node.body?.accept(this);
+  }
+
+  @override
+  visitListLiteral(ir.ListLiteral node) {
+    visitInContext(node.typeArgument, VariableUse.listLiteral);
+    ir.visitList(node.expressions, this);
+  }
+
+  @override
+  visitMapLiteral(ir.MapLiteral node) {
+    visitInContext(node.keyType, VariableUse.mapLiteral);
+    visitInContext(node.valueType, VariableUse.mapLiteral);
+    ir.visitList(node.entries, this);
+  }
+
+  @override
+  visitStaticInvocation(ir.StaticInvocation node) {
+    if (node.arguments.types.isNotEmpty) {
+      VariableUse usage;
+      if (node.target.kind == ir.ProcedureKind.Factory) {
+        usage = new VariableUse.constructorTypeArgument(node.target);
+      } else {
+        usage = new VariableUse.staticTypeArgument(node.target);
+      }
+
+      visitListInContext(node.arguments.types, usage);
+    }
+    ir.visitList(node.arguments.positional, this);
+    ir.visitList(node.arguments.named, this);
+  }
+
+  @override
+  visitConstructorInvocation(ir.ConstructorInvocation node) {
+    if (node.arguments.types.isNotEmpty) {
+      visitListInContext(node.arguments.types,
+          new VariableUse.constructorTypeArgument(node.target));
+    }
+    ir.visitList(node.arguments.positional, this);
+    ir.visitList(node.arguments.named, this);
+  }
+
+  @override
+  visitConditionalExpression(ir.ConditionalExpression node) {
+    node.condition.accept(this);
+    node.then.accept(this);
+    node.otherwise.accept(this);
+    // Don't visit `node.staticType`.
+  }
+
+  @override
+  visitMethodInvocation(ir.MethodInvocation node) {
+    ir.TreeNode receiver = node.receiver;
+    receiver.accept(this);
+    if (node.arguments.types.isNotEmpty) {
+      VariableUse usage;
+      if (receiver is ir.VariableGet &&
+          (receiver.variable.parent is ir.FunctionDeclaration ||
+              receiver.variable.parent is ir.FunctionExpression)) {
+        usage =
+            new VariableUse.localTypeArgument(receiver.variable.parent, node);
+      } else {
+        usage = new VariableUse.instanceTypeArgument(node);
+      }
+      visitListInContext(node.arguments.types, usage);
+    }
+    ir.visitList(node.arguments.positional, this);
+    ir.visitList(node.arguments.named, this);
+  }
+
+  @override
+  visitCatch(ir.Catch node) {
+    visitInContext(node.guard, VariableUse.explicit);
+    node.exception?.accept(this);
+    node.stackTrace?.accept(this);
+    node.body.accept(this);
   }
 
   /// Returns true if the node is a field, or a constructor (factory or
@@ -507,8 +636,8 @@
       node is ir.Field ||
       (node is ir.Procedure && node.isFactory);
 
-  void _analyzeTypeVariable(ir.TypeParameterType type,
-      {bool onlyIfNeedsRti: true}) {
+  void _analyzeTypeVariable(ir.TypeParameterType type, VariableUse usage) {
+    assert(usage != null);
     if (_outermostNode is ir.Member) {
       TypeVariableTypeWithContext typeVariable =
           new TypeVariableTypeWithContext(type, _outermostNode);
@@ -516,17 +645,15 @@
         case TypeVariableKind.cls:
           if (_isFieldOrConstructor(_outermostNode)) {
             // Class type variable used in a field or constructor.
-            _useTypeVariableAsLocal(typeVariable,
-                onlyForRtiChecks: onlyIfNeedsRti);
+            _useTypeVariableAsLocal(typeVariable, usage);
           } else {
             // Class type variable used in a method.
-            _registerNeedsThis(onlyIfNeedsRti: onlyIfNeedsRti);
+            _registerNeedsThis(usage);
           }
           break;
         case TypeVariableKind.method:
         case TypeVariableKind.local:
-          _useTypeVariableAsLocal(typeVariable,
-              onlyForRtiChecks: onlyIfNeedsRti);
+          _useTypeVariableAsLocal(typeVariable, usage);
           break;
         case TypeVariableKind.function:
         // The type variable is a function type variable, like `T` in
@@ -540,11 +667,11 @@
 
   /// If [onlyForRtiChecks] is true, the variable will be added to a list
   /// indicating it *may* be used only if runtime type information is checked.
-  void _useTypeVariableAsLocal(TypeVariableTypeWithContext typeVariable,
-      {bool onlyForRtiChecks: false}) {
+  void _useTypeVariableAsLocal(
+      TypeVariableTypeWithContext typeVariable, VariableUse usage) {
     if (typeVariable.kind != TypeVariableKind.cls && !_options.strongMode) {
       return;
     }
-    _markVariableAsUsed(typeVariable, onlyForRtiChecks: onlyForRtiChecks);
+    _markVariableAsUsed(typeVariable, usage);
   }
 }
diff --git a/pkg/compiler/lib/src/js_model/elements.dart b/pkg/compiler/lib/src/js_model/elements.dart
index 3e762b9..fdda596 100644
--- a/pkg/compiler/lib/src/js_model/elements.dart
+++ b/pkg/compiler/lib/src/js_model/elements.dart
@@ -18,31 +18,42 @@
 ///
 /// Querying for the frontend element for a backend-only element throws an
 /// exception.
-class JsToFrontendMap {
-  LibraryEntity toBackendLibrary(LibraryEntity library) => library;
+abstract class JsToFrontendMap {
+  LibraryEntity toBackendLibrary(LibraryEntity library);
 
-  ClassEntity toBackendClass(ClassEntity cls) => cls;
+  ClassEntity toBackendClass(ClassEntity cls);
 
-  MemberEntity toBackendMember(MemberEntity member) => member;
+  /// Returns the backend member corresponding to [member]. If a member isn't
+  /// live, it doesn't have a corresponding backend member and `null` is
+  /// returned instead.
+  MemberEntity toBackendMember(MemberEntity member);
 
-  DartType toBackendType(DartType type) => type;
+  DartType toBackendType(DartType type);
 
   Set<LibraryEntity> toBackendLibrarySet(Iterable<LibraryEntity> set) {
     return set.map(toBackendLibrary).toSet();
   }
 
   Set<ClassEntity> toBackendClassSet(Iterable<ClassEntity> set) {
+    // TODO(johnniwinther): Filter unused classes.
     return set.map(toBackendClass).toSet();
   }
 
   Set<MemberEntity> toBackendMemberSet(Iterable<MemberEntity> set) {
-    return set.map(toBackendMember).toSet();
+    return set.map(toBackendMember).where((MemberEntity member) {
+      // Members that are not live don't have a corresponding backend member.
+      return member != null;
+    }).toSet();
   }
 
   Set<FunctionEntity> toBackendFunctionSet(Iterable<FunctionEntity> set) {
     Set<FunctionEntity> newSet = new Set<FunctionEntity>();
     for (FunctionEntity element in set) {
-      newSet.add(toBackendMember(element));
+      FunctionEntity backendFunction = toBackendMember(element);
+      if (backendFunction != null) {
+        // Members that are not live don't have a corresponding backend member.
+        newSet.add(backendFunction);
+      }
     }
     return newSet;
   }
@@ -69,7 +80,12 @@
     Map<K, V> map, K convertKey(K key), V convertValue(V value)) {
   Map<K, V> newMap = <K, V>{};
   map.forEach((K key, V value) {
-    newMap[convertKey(key)] = convertValue(value);
+    K newKey = convertKey(key);
+    V newValue = convertValue(value);
+    if (newKey != null && newValue != null) {
+      // Entities that are not used don't have a corresponding backend entity.
+      newMap[newKey] = newValue;
+    }
   });
   return newMap;
 }
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index 888b04b..9572c32 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -72,15 +72,14 @@
   ClosedWorldRefiner createClosedWorldRefiner(ClosedWorld closedWorld) {
     KernelFrontEndStrategy strategy = _compiler.frontendStrategy;
     _elementMap = new JsKernelToElementMap(
-        _compiler.reporter, _compiler.environment, strategy.elementMap);
+        _compiler.reporter,
+        _compiler.environment,
+        strategy.elementMap,
+        closedWorld.processedMembers);
     _elementEnvironment = _elementMap.elementEnvironment;
     _commonElements = _elementMap.commonElements;
     _closureDataLookup = new KernelClosureConversionTask(
-        _compiler.measurer,
-        _elementMap,
-        _globalLocalsMap,
-        _compiler.options.enableTypeAssertions,
-        _compiler.options.strongMode);
+        _compiler.measurer, _elementMap, _globalLocalsMap, _compiler.options);
     JsClosedWorldBuilder closedWorldBuilder = new JsClosedWorldBuilder(
         _elementMap, _closureDataLookup, _compiler.options);
     return closedWorldBuilder._convertClosedWorld(
@@ -115,7 +114,12 @@
           result[closureInfo.closureClassEntity] = unit;
           result[closureInfo.callMethod] = unit;
         } else {
-          result[toBackendEntity(entity)] = unit;
+          Entity backendEntity = toBackendEntity(entity);
+          if (backendEntity != null) {
+            // If [entity] isn't used it doesn't have a corresponding backend
+            // entity.
+            result[backendEntity] = unit;
+          }
         }
       });
       return result;
@@ -281,11 +285,9 @@
     if (_options.disableRtiOptimization) {
       rtiNeed = new TrivialRuntimeTypesNeed();
       callMethods = _closureConversionTask.createClosureEntities(
-          this, map.toBackendMemberMap(closureModels, identity),
-          localFunctionNeedsSignature: (_) => true,
-          classNeedsTypeArguments: (_) => true,
-          methodNeedsTypeArguments: (_) => true,
-          localFunctionNeedsTypeArguments: (_) => true);
+          this,
+          map.toBackendMemberMap(closureModels, identity),
+          const TrivialClosureRtiNeed());
     } else {
       RuntimeTypesNeedImpl kernelRtiNeed = closedWorld.rtiNeed;
       Set<ir.Node> localFunctionsNodesNeedingSignature = new Set<ir.Node>();
@@ -308,23 +310,14 @@
       RuntimeTypesNeedImpl jRtiNeed =
           _convertRuntimeTypesNeed(map, backendUsage, kernelRtiNeed);
       callMethods = _closureConversionTask.createClosureEntities(
-          this, map.toBackendMemberMap(closureModels, identity),
-          localFunctionNeedsSignature: (ir.Node node) {
-            assert(node is ir.FunctionDeclaration ||
-                node is ir.FunctionExpression);
-            return backendUsage.isRuntimeTypeUsed
-                ? true
-                : localFunctionsNodesNeedingSignature.contains(node);
-          },
-          classNeedsTypeArguments: jRtiNeed.classNeedsTypeArguments,
-          methodNeedsTypeArguments: jRtiNeed.methodNeedsTypeArguments,
-          localFunctionNeedsTypeArguments: (ir.Node node) {
-            assert(node is ir.FunctionDeclaration ||
-                node is ir.FunctionExpression);
-            return backendUsage.isRuntimeTypeUsed
-                ? true
-                : localFunctionsNodesNeedingTypeArguments.contains(node);
-          });
+          this,
+          map.toBackendMemberMap(closureModels, identity),
+          new JsClosureRtiNeed(
+            backendUsage,
+            jRtiNeed,
+            localFunctionsNodesNeedingTypeArguments,
+            localFunctionsNodesNeedingSignature,
+          ));
 
       List<FunctionEntity> callMethodsNeedingSignature = <FunctionEntity>[];
       for (ir.Node node in localFunctionsNodesNeedingSignature) {
@@ -463,8 +456,12 @@
         <FunctionEntity, NativeBehavior>{};
     nativeData.nativeMethodBehavior
         .forEach((FunctionEntity method, NativeBehavior behavior) {
-      nativeMethodBehavior[map.toBackendMember(method)] =
-          convertNativeBehavior(behavior);
+      FunctionEntity backendMethod = map.toBackendMember(method);
+      if (backendMethod != null) {
+        // If [method] isn't used it doesn't have a corresponding backend
+        // method.
+        nativeMethodBehavior[backendMethod] = convertNativeBehavior(behavior);
+      }
     });
     Map<MemberEntity, NativeBehavior> nativeFieldLoadBehavior =
         map.toBackendMemberMap(
@@ -773,3 +770,53 @@
   List<DartType> _visitList(List<DartType> list) =>
       list.map<DartType>((t) => t.accept(this, null)).toList();
 }
+
+class TrivialClosureRtiNeed implements ClosureRtiNeed {
+  const TrivialClosureRtiNeed();
+
+  bool localFunctionNeedsSignature(ir.Node node) => true;
+  bool classNeedsTypeArguments(ClassEntity cls) => true;
+  bool methodNeedsTypeArguments(FunctionEntity method) => true;
+  bool localFunctionNeedsTypeArguments(ir.Node node) => true;
+  bool selectorNeedsTypeArguments(Selector selector) => true;
+  bool methodNeedsSignature(MemberEntity method) => true;
+}
+
+class JsClosureRtiNeed implements ClosureRtiNeed {
+  final BackendUsage backendUsage;
+  final RuntimeTypesNeed rtiNeed;
+  final Set<ir.Node> localFunctionsNodesNeedingTypeArguments;
+  final Set<ir.Node> localFunctionsNodesNeedingSignature;
+
+  JsClosureRtiNeed(
+      this.backendUsage,
+      this.rtiNeed,
+      this.localFunctionsNodesNeedingTypeArguments,
+      this.localFunctionsNodesNeedingSignature);
+
+  bool localFunctionNeedsSignature(ir.Node node) {
+    assert(node is ir.FunctionDeclaration || node is ir.FunctionExpression);
+    return backendUsage.isRuntimeTypeUsed
+        ? true
+        : localFunctionsNodesNeedingSignature.contains(node);
+  }
+
+  bool classNeedsTypeArguments(ClassEntity cls) =>
+      rtiNeed.classNeedsTypeArguments(cls);
+
+  bool methodNeedsTypeArguments(FunctionEntity method) =>
+      rtiNeed.methodNeedsTypeArguments(method);
+
+  bool localFunctionNeedsTypeArguments(ir.Node node) {
+    assert(node is ir.FunctionDeclaration || node is ir.FunctionExpression);
+    return backendUsage.isRuntimeTypeUsed
+        ? true
+        : localFunctionsNodesNeedingTypeArguments.contains(node);
+  }
+
+  bool selectorNeedsTypeArguments(Selector selector) =>
+      rtiNeed.selectorNeedsTypeArguments(selector);
+
+  bool methodNeedsSignature(MemberEntity method) =>
+      rtiNeed.methodNeedsSignature(method);
+}
diff --git a/pkg/compiler/lib/src/js_model/locals.dart b/pkg/compiler/lib/src/js_model/locals.dart
index af6f30a..8c7e543 100644
--- a/pkg/compiler/lib/src/js_model/locals.dart
+++ b/pkg/compiler/lib/src/js_model/locals.dart
@@ -223,6 +223,29 @@
     JJumpTarget target;
     ir.TreeNode body = node.target.body;
     ir.TreeNode parent = node.target.parent;
+
+    // TODO(johnniwinther): Coordinate with CFE-team to avoid such arbitrary
+    // reverse engineering mismatches:
+    if (parent is ir.Block && parent.statements.last == node.target) {
+      // In strong mode for code like this:
+      //
+      //     for (int i in list) {
+      //       continue;
+      //     }
+      //
+      // an implicit cast may be inserted before the label statement, resulting
+      // in code like this:
+      //
+      //     for (var i in list) {
+      //       var #1 = i as int;
+      //       l1: {
+      //          break l1:
+      //       }
+      //     }
+      //
+      // for which we should still use the for loop as a continue target.
+      parent = parent.parent;
+    }
     if (canBeBreakTarget(body)) {
       // We have code like
       //
diff --git a/pkg/compiler/lib/src/kernel/element_map.dart b/pkg/compiler/lib/src/kernel/element_map.dart
index 48a25e7..d9c3e7a 100644
--- a/pkg/compiler/lib/src/kernel/element_map.dart
+++ b/pkg/compiler/lib/src/kernel/element_map.dart
@@ -185,6 +185,10 @@
 
   /// Returns the definition information for [cls].
   ClassDefinition getClassDefinition(covariant ClassEntity cls);
+
+  /// Returns the static type of [node].
+  // TODO(johnniwinther): This should be provided directly from kernel.
+  DartType getStaticType(ir.Expression node);
 }
 
 /// Interface that translates between Kernel IR nodes and entities used for
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index ecf8d0a..e7791c6 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -5,6 +5,9 @@
 library dart2js.kernel.element_map;
 
 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_environment.dart' as ir;
 
 import '../closure.dart' show BoxLocal, ThisLocal;
 import '../common.dart';
@@ -202,6 +205,10 @@
     });
   }
 
+  void ensureClassMembers(ir.Class node) {
+    _classes.getEnv(_getClass(node)).ensureMembers(this);
+  }
+
   MemberEntity lookupClassMember(IndexedClass cls, String name,
       {bool setter: false}) {
     assert(checkFamily(cls));
@@ -342,17 +349,24 @@
   MemberEntity getSuperMember(
       MemberEntity context, ir.Name name, ir.Member target,
       {bool setter: false}) {
-    if (target != null) {
+    if (target != null && !target.isAbstract && target.isInstanceMember) {
       return getMember(target);
     }
     ClassEntity cls = context.enclosingClass;
+    assert(
+        cls != null,
+        failedAt(context,
+            "No enclosing class for super member access in $context."));
     IndexedClass superclass = _getSuperType(cls)?.element;
     while (superclass != null) {
       ClassEnv env = _classes.getEnv(superclass);
       MemberEntity superMember =
           env.lookupMember(this, name.name, setter: setter);
-      if (superMember != null && !superMember.isAbstract) {
-        return superMember;
+      if (superMember != null) {
+        if (!superMember.isInstanceMember) return null;
+        if (!superMember.isAbstract) {
+          return superMember;
+        }
       }
       superclass = _getSuperType(superclass)?.element;
     }
@@ -1187,11 +1201,37 @@
         KElementCreatorMixin {
   native.BehaviorBuilder _nativeBehaviorBuilder;
   FrontendStrategy _frontendStrategy;
+  ir.TypeEnvironment _typeEnvironment;
+  bool _isStaticTypePrepared = false;
 
   KernelToElementMapForImpactImpl(DiagnosticReporter reporter,
       Environment environment, this._frontendStrategy, CompilerOptions options)
       : super(options, reporter, environment);
 
+  DartType getStaticType(ir.Expression node) {
+    if (!_isStaticTypePrepared) {
+      _isStaticTypePrepared = true;
+      try {
+        _typeEnvironment ??= new ir.TypeEnvironment(
+            new ir.CoreTypes(_env.mainComponent),
+            new ir.ClassHierarchy(_env.mainComponent),
+            strongMode: options.strongMode);
+      } catch (e) {}
+    }
+    if (_typeEnvironment == null) {
+      // The class hierarchy crashes on multiple inheritance. Use `dynamic`
+      // as static type.
+      return commonElements.dynamicType;
+    }
+    ir.TreeNode enclosingClass = node;
+    while (enclosingClass != null && enclosingClass is! ir.Class) {
+      enclosingClass = enclosingClass.parent;
+    }
+    _typeEnvironment.thisType =
+        enclosingClass is ir.Class ? enclosingClass.thisType : null;
+    return getDartType(node.getStaticType(_typeEnvironment));
+  }
+
   @override
   bool checkFamily(Entity entity) {
     assert(
@@ -1409,6 +1449,39 @@
   }
 
   @override
+  DartType getFunctionAsyncOrSyncStarElementType(FunctionEntity function) {
+    DartType returnType = getFunctionType(function).returnType;
+    switch (function.asyncMarker) {
+      case AsyncMarker.SYNC:
+        return returnType;
+      case AsyncMarker.SYNC_STAR:
+        if (returnType is InterfaceType) {
+          if (returnType.element == elementMap.commonElements.iterableClass) {
+            return returnType.typeArguments.first;
+          }
+        }
+        return dynamicType;
+      case AsyncMarker.ASYNC:
+        if (returnType is FutureOrType) return returnType.typeArgument;
+        if (returnType is InterfaceType) {
+          if (returnType.element == elementMap.commonElements.futureClass) {
+            return returnType.typeArguments.first;
+          }
+        }
+        return dynamicType;
+      case AsyncMarker.ASYNC_STAR:
+        if (returnType is InterfaceType) {
+          if (returnType.element == elementMap.commonElements.streamClass) {
+            return returnType.typeArguments.first;
+          }
+        }
+        return dynamicType;
+    }
+    assert(false, 'Unexpected marker ${function.asyncMarker}');
+    return null;
+  }
+
+  @override
   DartType getFieldType(FieldEntity field) {
     return elementMap._getFieldType(field);
   }
@@ -2159,8 +2232,11 @@
 
   NativeBasicData nativeBasicData;
 
-  JsKernelToElementMap(DiagnosticReporter reporter, Environment environment,
-      KernelToElementMapForImpactImpl _elementMap)
+  JsKernelToElementMap(
+      DiagnosticReporter reporter,
+      Environment environment,
+      KernelToElementMapForImpactImpl _elementMap,
+      Iterable<MemberEntity> liveMembers)
       : super(_elementMap.options, reporter, environment) {
     _env = _elementMap._env;
     for (int libraryIndex = 0;
@@ -2173,7 +2249,11 @@
       IndexedLibrary newLibrary = convertLibrary(oldLibrary);
       _libraryMap[env.library] =
           _libraries.register<IndexedLibrary, LibraryData, LibraryEnv>(
-              newLibrary, data.copy(), env);
+              newLibrary,
+              data.copy(),
+              options.strongMode && useStrongModeWorldStrategy
+                  ? env.copyLive(_elementMap, liveMembers)
+                  : env);
       assert(newLibrary.libraryIndex == oldLibrary.libraryIndex);
     }
     for (int classIndex = 0;
@@ -2185,7 +2265,12 @@
       IndexedLibrary oldLibrary = oldClass.library;
       LibraryEntity newLibrary = _libraries.getEntity(oldLibrary.libraryIndex);
       IndexedClass newClass = convertClass(newLibrary, oldClass);
-      _classMap[env.cls] = _classes.register(newClass, data.copy(), env);
+      _classMap[env.cls] = _classes.register(
+          newClass,
+          data.copy(),
+          options.strongMode && useStrongModeWorldStrategy
+              ? env.copyLive(_elementMap, liveMembers)
+              : env);
       assert(newClass.classIndex == oldClass.classIndex);
     }
     for (int typedefIndex = 0;
@@ -2211,6 +2296,12 @@
         memberIndex < _elementMap._members.length;
         memberIndex++) {
       IndexedMember oldMember = _elementMap._members.getEntity(memberIndex);
+      if (options.strongMode &&
+          useStrongModeWorldStrategy &&
+          !liveMembers.contains(oldMember)) {
+        _members.skipIndex(oldMember.memberIndex);
+        continue;
+      }
       MemberDataImpl data = _elementMap._members.getData(oldMember);
       IndexedLibrary oldLibrary = oldMember.library;
       IndexedClass oldClass = oldMember.enclosingClass;
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index 90077cb..da925b6 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -32,6 +32,8 @@
   /// TODO(johnniwinther): Handle arbitrary load order if needed.
   ir.Member get mainMethod => _components.first?.mainMethod;
 
+  ir.Component get mainComponent => _components.first;
+
   void addComponent(ir.Component component) {
     if (_components.add(component)) {
       if (_libraryMap != null) {
@@ -84,6 +86,9 @@
 
   LibraryEnv(this.library);
 
+  LibraryEnv.internal(
+      this.library, this._classMap, this._memberMap, this._setterMap);
+
   void _ensureClassMap() {
     if (_classMap == null) {
       _classMap = <String, ClassEnv>{};
@@ -150,6 +155,45 @@
       }
     }
   }
+
+  /// Creates a new [LibraryEnv] containing only the members in [liveMembers].
+  ///
+  /// Currently all classes are copied.
+  // TODO(johnniwinther): Filter unused classes.
+  LibraryEnv copyLive(
+      KernelToElementMap elementMap, Iterable<MemberEntity> liveMembers) {
+    Map<String, ClassEnv> classMap;
+    Map<String, ir.Member> memberMap;
+    Map<String, ir.Member> setterMap;
+    if (_classMap == null) {
+      classMap = const <String, ClassEnv>{};
+    } else {
+      classMap = _classMap;
+    }
+    if (_memberMap == null) {
+      memberMap = const <String, ir.Member>{};
+    } else {
+      memberMap = <String, ir.Member>{};
+      _memberMap.forEach((String name, ir.Member node) {
+        MemberEntity member = elementMap.getMember(node);
+        if (liveMembers.contains(member)) {
+          memberMap[name] = node;
+        }
+      });
+    }
+    if (_setterMap == null) {
+      setterMap = const <String, ir.Member>{};
+    } else {
+      setterMap = <String, ir.Member>{};
+      _setterMap.forEach((String name, ir.Member node) {
+        MemberEntity member = elementMap.getMember(node);
+        if (liveMembers.contains(member)) {
+          setterMap[name] = node;
+        }
+      });
+    }
+    return new LibraryEnv.internal(library, classMap, memberMap, setterMap);
+  }
 }
 
 class LibraryData {
@@ -196,6 +240,9 @@
   /// Whether the class is an unnamed mixin application.
   bool get isUnnamedMixinApplication;
 
+  /// Ensures that all members have been computed for [cls].
+  void ensureMembers(KernelToElementMapBase elementMap);
+
   /// Return the [MemberEntity] for the member [name] in the class. If [setter]
   /// is `true`, the setter or assignable field corresponding to [name] is
   /// returned.
@@ -217,6 +264,10 @@
   /// Calls [f] for each constructor body for the live constructors in the
   /// class.
   void forEachConstructorBody(void f(ConstructorBodyEntity constructor));
+
+  /// Creates a new [ClassEnv] containing only the members in [liveMembers].
+  ClassEnv copyLive(
+      KernelToElementMap elementMap, Iterable<MemberEntity> liveMembers);
 }
 
 int orderByFileOffset(ir.TreeNode a, ir.TreeNode b) {
@@ -243,6 +294,9 @@
 
   ClassEnvImpl(this.cls);
 
+  ClassEnvImpl.internal(this.cls, this._constructorMap, this._memberMap,
+      this._setterMap, this._members);
+
   bool get isUnnamedMixinApplication => cls.isSyntheticMixinImplementation;
 
   /// Copied from 'package:kernel/transformations/mixin_full_resolution.dart'.
@@ -291,6 +345,10 @@
         initializers: <ir.Initializer>[superInitializer]);
   }
 
+  void ensureMembers(KernelToElementMapBase elementMap) {
+    _ensureMaps(elementMap);
+  }
+
   void _ensureMaps(KernelToElementMapBase elementMap) {
     if (_memberMap != null) return;
 
@@ -364,6 +422,7 @@
 
     int mixinMemberCount = 0;
     if (cls.mixedInClass != null) {
+      elementMap.ensureClassMembers(cls.mixedInClass);
       addFields(cls.mixedInClass.mixin, includeStatic: false);
       addProcedures(cls.mixedInClass.mixin, includeStatic: false);
       mergeSort(members, compare: orderByFileOffset);
@@ -446,6 +505,60 @@
   void forEachConstructorBody(void f(ConstructorBodyEntity constructor)) {
     _constructorBodyList?.forEach(f);
   }
+
+  ClassEnv copyLive(
+      KernelToElementMap elementMap, Iterable<MemberEntity> liveMembers) {
+    Map<String, ir.Member> constructorMap;
+    Map<String, ir.Member> memberMap;
+    Map<String, ir.Member> setterMap;
+    List<ir.Member> members;
+    if (_constructorMap == null) {
+      constructorMap = const <String, ir.Member>{};
+    } else {
+      constructorMap = <String, ir.Member>{};
+      _constructorMap.forEach((String name, ir.Member node) {
+        MemberEntity member = elementMap.getMember(node);
+        if (liveMembers.contains(member)) {
+          constructorMap[name] = node;
+        }
+      });
+    }
+    if (_memberMap == null) {
+      memberMap = const <String, ir.Member>{};
+    } else {
+      memberMap = <String, ir.Member>{};
+      _memberMap.forEach((String name, ir.Member node) {
+        MemberEntity member = elementMap.getMember(node);
+        if (liveMembers.contains(member)) {
+          memberMap[name] = node;
+        }
+      });
+    }
+    if (_setterMap == null) {
+      setterMap = const <String, ir.Member>{};
+    } else {
+      setterMap = <String, ir.Member>{};
+      _setterMap.forEach((String name, ir.Member node) {
+        MemberEntity member = elementMap.getMember(node);
+        if (liveMembers.contains(member)) {
+          setterMap[name] = node;
+        }
+      });
+    }
+    if (_members == null) {
+      members = const <ir.Member>[];
+    } else {
+      members = <ir.Member>[];
+      _members.forEach((ir.Member node) {
+        MemberEntity member = elementMap.getMember(node);
+        if (liveMembers.contains(member)) {
+          members.add(node);
+        }
+      });
+    }
+    return new ClassEnvImpl.internal(
+        cls, constructorMap, memberMap, setterMap, members);
+  }
 }
 
 class ClosureClassEnv extends RecordEnv {
@@ -460,6 +573,11 @@
     }
     return super.lookupMember(elementMap, name, setter: setter);
   }
+
+  @override
+  ClassEnv copyLive(
+          KernelToElementMap elementMap, Iterable<MemberEntity> liveMembers) =>
+      this;
 }
 
 class RecordEnv implements ClassEnv {
@@ -468,6 +586,11 @@
   RecordEnv(this._memberMap);
 
   @override
+  void ensureMembers(KernelToElementMapBase elementMap) {
+    // All members have been computed at creation.
+  }
+
+  @override
   void forEachConstructorBody(void f(ConstructorBodyEntity constructor)) {
     // We do not create constructor bodies for containers.
   }
@@ -502,6 +625,12 @@
 
   @override
   ir.Class get cls => null;
+
+  @override
+  ClassEnv copyLive(
+      KernelToElementMap elementMap, Iterable<MemberEntity> liveMembers) {
+    return this;
+  }
 }
 
 class ClassData {
diff --git a/pkg/compiler/lib/src/kernel/indexed.dart b/pkg/compiler/lib/src/kernel/indexed.dart
index bf7be15..28545af 100644
--- a/pkg/compiler/lib/src/kernel/indexed.dart
+++ b/pkg/compiler/lib/src/kernel/indexed.dart
@@ -61,9 +61,10 @@
 
 /// Index based map of entities of type [E].
 class EntityMap<E extends _Indexed> extends EntityMapBase<E> {
-  /// Registers a new entity.
+  /// Registers a new [entity].
   ///
-  /// [createEntity] is called to create the entity with the given index.
+  /// The index of [entity] is set to match its index in the entity list in this
+  /// map.
   E0 register<E0 extends E>(E0 entity) {
     assert(entity != null);
     assert(entity._index == null);
@@ -93,11 +94,17 @@
 /// Index based map of entities of type [E] with a corresponding data object
 /// of type [D].
 class EntityDataMap<E extends _Indexed, D> extends EntityDataMapBase<E, D> {
-  /// Registers a new entity with an associated data object.
+  /// Mark entity [index] as missing
+  void skipIndex(int index) {
+    assert(index == _list.length);
+    _list.add(null);
+    _data.add(null);
+  }
+
+  /// Registers a new [entity] with an associated [data] object.
   ///
-  /// Firstly, [createEntity] is called to create the entity with the given
-  /// index. Secondly, [createData] is called with the newly created entity to
-  /// create the associated data object.
+  /// The index of [entity] is set to match its index in the entity and data
+  /// lists in this map.
   E0 register<E0 extends E, D0 extends D>(E0 entity, D0 data) {
     assert(entity != null);
     assert(entity._index == null);
@@ -130,12 +137,11 @@
 /// type [D] and an environment of type [V].
 class EntityDataEnvMap<E extends _Indexed, D, V>
     extends EntityDataEnvMapBase<E, D, V> {
-  /// Registers a new entity with an associated data object and environment.
+  /// Registers a new [entity] with an associated [data] object and environment
+  /// [env].
   ///
-  /// Firstly, [createEntity] is called to create the entity with the given
-  /// index. Secondly, [createData] is called with the newly created entity to
-  /// create the associated data object. Thirdly, [createEnv] is called with
-  /// the newly created entity to create the associated environment object.
+  /// The index of [entity] is set to match its index in the entity, data and
+  /// environment lists in this map.
   E0 register<E0 extends E, D0 extends D, V0 extends V>(
       E0 entity, D0 data, V0 env) {
     assert(entity != null);
diff --git a/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart
index d0de459..b575680 100644
--- a/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart
@@ -238,7 +238,7 @@
   }
 
   @override
-  Iterable<MemberEntity> sortMembers(Iterable<MemberEntity> members) {
+  Iterable<T> sortMembers<T extends MemberEntity>(Iterable<T> members) {
     return members.toList()..sort(compareMembersByLocation);
   }
 
diff --git a/pkg/compiler/lib/src/kernel/types.dart b/pkg/compiler/lib/src/kernel/types.dart
index 3f6a1a6..9f6efde 100644
--- a/pkg/compiler/lib/src/kernel/types.dart
+++ b/pkg/compiler/lib/src/kernel/types.dart
@@ -16,8 +16,10 @@
             new _KernelPotentialSubtypeVisitor(elementMap);
 
   @override
-  bool isPotentialSubtype(DartType t, DartType s) {
-    return potentialSubtypeVisitor.isSubtype(t, s);
+  bool isPotentialSubtype(DartType t, DartType s,
+      {bool assumeInstantiations: true}) {
+    return potentialSubtypeVisitor.isPotentialSubtype(t, s,
+        assumeInstantiations: assumeInstantiations);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/parser/element_listener.dart b/pkg/compiler/lib/src/parser/element_listener.dart
index 71ea505..081a066 100644
--- a/pkg/compiler/lib/src/parser/element_listener.dart
+++ b/pkg/compiler/lib/src/parser/element_listener.dart
@@ -852,7 +852,7 @@
   Token synthesizeIdentifier(Token token) {
     Token synthesizedToken =
         new StringToken.fromString(TokenType.IDENTIFIER, '?', token.charOffset);
-    synthesizedToken.next = token.next;
+    synthesizedToken.setNext(token.next);
     return synthesizedToken;
   }
 
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index e50aede..abda55c 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -4328,6 +4328,7 @@
             MessageKind.INVALID_AWAIT_FOR_IN);
       }
       registry.registerFeature(Feature.ASYNC_FOR_IN);
+      registry.registerDynamicUse(new DynamicUse(Selectors.cancel));
       registry.registerDynamicUse(new DynamicUse(Selectors.current));
       registry.registerDynamicUse(new DynamicUse(Selectors.moveNext));
     }
diff --git a/pkg/compiler/lib/src/resolution/resolution_strategy.dart b/pkg/compiler/lib/src/resolution/resolution_strategy.dart
index c4bfb96..b73f923 100644
--- a/pkg/compiler/lib/src/resolution/resolution_strategy.dart
+++ b/pkg/compiler/lib/src/resolution/resolution_strategy.dart
@@ -737,6 +737,11 @@
   }
 
   @override
+  DartType getFunctionAsyncOrSyncStarElementType(FunctionEntity function) {
+    return dynamicType;
+  }
+
+  @override
   DartType getFieldType(covariant FieldElement field) {
     field.computeType(_resolution);
     return field.type;
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 37c4541..23353e6 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -4126,7 +4126,7 @@
       }
     }
 
-    bool isOptimizableOperation(Selector selector, Element element) {
+    bool isOptimizableOperation(Selector selector, MemberElement element) {
       ClassElement cls = element.enclosingClass;
       if (isOptimizableOperationOnIndexable(selector, element)) return true;
       if (!interceptorData.interceptedClasses.contains(cls)) return false;
@@ -4136,7 +4136,7 @@
       if (selector.isIndexSet) return true;
       if (element == commonElements.jsArrayAdd ||
           element == commonElements.jsArrayRemoveLast ||
-          element == commonElements.jsStringSplit) {
+          commonElements.isJsStringSplit(element)) {
         return true;
       }
       return false;
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index efed6ee..06ebbe7 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -2787,14 +2787,17 @@
     node.value.accept(this);
     HInstruction value = pop();
 
-    if (node.interfaceTarget == null) {
+    MemberEntity member = _elementMap.getSuperMember(
+        _currentFrame.member, node.name, node.interfaceTarget,
+        setter: true);
+    if (member == null) {
       _generateSuperNoSuchMethod(node, _elementMap.getSelector(node).name + "=",
           <HInstruction>[value], const <DartType>[], sourceInformation);
     } else {
       _buildInvokeSuper(
           _elementMap.getSelector(node),
           _elementMap.getClass(_containingClass(node)),
-          _elementMap.getMember(node.interfaceTarget),
+          member,
           <HInstruction>[value],
           const <DartType>[],
           sourceInformation);
@@ -3811,7 +3814,7 @@
       if (selector.isIndexSet) return true;
       if (element == commonElements.jsArrayAdd ||
           element == commonElements.jsArrayRemoveLast ||
-          element == commonElements.jsStringSplit) {
+          commonElements.isJsStringSplit(element)) {
         return true;
       }
       return false;
@@ -4170,14 +4173,16 @@
   void visitSuperPropertyGet(ir.SuperPropertyGet node) {
     SourceInformation sourceInformation =
         _sourceInformationBuilder.buildGet(node);
-    if (node.interfaceTarget == null) {
+    MemberEntity member = _elementMap.getSuperMember(
+        _currentFrame.member, node.name, node.interfaceTarget);
+    if (member == null) {
       _generateSuperNoSuchMethod(node, _elementMap.getSelector(node).name,
           const <HInstruction>[], const <DartType>[], sourceInformation);
     } else {
       _buildInvokeSuper(
           _elementMap.getSelector(node),
           _elementMap.getClass(_containingClass(node)),
-          _elementMap.getMember(node.interfaceTarget),
+          member,
           const <HInstruction>[],
           const <DartType>[],
           sourceInformation);
@@ -4188,7 +4193,9 @@
   void visitSuperMethodInvocation(ir.SuperMethodInvocation node) {
     SourceInformation sourceInformation =
         _sourceInformationBuilder.buildCall(node, node);
-    if (node.interfaceTarget == null) {
+    MemberEntity member = _elementMap.getSuperMember(
+        _currentFrame.member, node.name, node.interfaceTarget);
+    if (member == null) {
       Selector selector = _elementMap.getSelector(node);
       List<DartType> typeArguments = <DartType>[];
       selector =
@@ -4199,9 +4206,8 @@
           node, selector.name, arguments, typeArguments, sourceInformation);
       return;
     }
-    FunctionEntity function = _elementMap.getMethod(node.interfaceTarget);
     List<DartType> typeArguments =
-        _getStaticTypeArguments(function, node.arguments);
+        _getStaticTypeArguments(member, node.arguments);
     List<HInstruction> arguments = _visitArgumentsForStaticTarget(
         node.interfaceTarget.function,
         node.arguments,
@@ -4210,7 +4216,7 @@
     _buildInvokeSuper(
         _elementMap.getSelector(node),
         _elementMap.getClass(_containingClass(node)),
-        function,
+        member,
         arguments,
         typeArguments,
         sourceInformation);
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index f108912..2e4c056 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -1738,7 +1738,7 @@
         methodName = 'push';
       } else if (target == _commonElements.jsArrayRemoveLast) {
         methodName = 'pop';
-      } else if (target == _commonElements.jsStringSplit) {
+      } else if (_commonElements.isJsStringSplit(target)) {
         methodName = 'split';
         // Split returns a List, so we make sure the backend knows the
         // list class is instantiated.
diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
index c476754..f02b6c6 100644
--- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
+++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
@@ -122,16 +122,52 @@
       CompilerOptions options,
       CommonElements commonElements,
       ClosedWorld closedWorld) {
-    if (instruction.inputs[1].isMutableIndexable(closedWorld)) {
-      if (!instruction.inputs[2].isInteger(closedWorld) &&
-          options.enableTypeAssertions) {
-        // We want the right checked mode error.
+    HInstruction receiver = instruction.inputs[1];
+    HInstruction index = instruction.inputs[2];
+    if (!receiver.isMutableIndexable(closedWorld)) return null;
+    if (!index.isInteger(closedWorld) && options.enableTypeAssertions) {
+      // We want the right checked mode error.
+      return null;
+    }
+
+    HInstruction value = instruction.inputs[3];
+    if (options.parameterCheckPolicy.isEmitted) {
+      if (!_valueParameterCheckAlwaysSucceeds(
+          instruction, receiver, value, commonElements, closedWorld)) {
         return null;
       }
-      return new HIndexAssign(instruction.inputs[1], instruction.inputs[2],
-          instruction.inputs[3], instruction.selector);
     }
-    return null;
+    return new HIndexAssign(receiver, index, value, instruction.selector);
+  }
+
+  /// Returns [true] if [value] meets the requirements for being stored into
+  /// indexable [receiver].
+  bool _valueParameterCheckAlwaysSucceeds(
+      HInvokeDynamic instruction,
+      HInstruction receiver,
+      HInstruction value,
+      CommonElements commonElements,
+      ClosedWorld closedWorld) {
+    // Handle typed arrays by recognizing the exact implementation of `[]=` and
+    // checking if [value] has the appropriate type.
+    if (instruction.element != null) {
+      ClassEntity cls = instruction.element.enclosingClass;
+      if (cls == commonElements.typedArrayOfIntClass) {
+        return value.isInteger(closedWorld);
+      } else if (cls == commonElements.typedArrayOfDoubleClass) {
+        return value.isNumber(closedWorld);
+      }
+    }
+
+    // The type check will pass if it passed before. We know it passed before if
+    // the value was loaded from the same indexable.
+    if (value is HIndex) {
+      if (value.receiver.nonCheck() == receiver.nonCheck()) {
+        return true;
+      }
+    }
+
+    return false;
   }
 }
 
@@ -212,8 +248,18 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       ClosedWorld closedWorld) {
-    TypeMask operandType = instruction.inputs[1].instructionType;
-    if (instruction.inputs[1].isNumberOrNull(closedWorld)) return operandType;
+    HInstruction operand = instruction.inputs[1];
+    if (operand.isNumberOrNull(closedWorld)) {
+      // We have integer subclasses that represent ranges, so widen any int
+      // subclass to full integer.
+      if (operand.isIntegerOrNull(closedWorld)) {
+        return closedWorld.commonMasks.intType;
+      }
+      if (operand.isDoubleOrNull(closedWorld)) {
+        return closedWorld.commonMasks.doubleType;
+      }
+      return closedWorld.commonMasks.numType;
+    }
     return super
         .computeTypeFromInputTypes(instruction, results, options, closedWorld);
   }
@@ -227,7 +273,11 @@
       ClosedWorld closedWorld) {
     HInstruction input = instruction.inputs[1];
     if (input.isNumber(closedWorld)) {
-      return new HNegate(input, instruction.selector, input.instructionType);
+      return new HNegate(
+          input,
+          instruction.selector,
+          computeTypeFromInputTypes(
+              instruction, results, options, closedWorld));
     }
     return null;
   }
diff --git a/pkg/compiler/lib/src/ssa/kernel_impact.dart b/pkg/compiler/lib/src/ssa/kernel_impact.dart
index 3e93ba2..6f96104 100644
--- a/pkg/compiler/lib/src/ssa/kernel_impact.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_impact.dart
@@ -19,6 +19,7 @@
 import '../universe/feature.dart';
 import '../universe/selector.dart';
 import '../universe/use.dart';
+import '../universe/world_builder.dart';
 
 ResolutionImpact buildKernelImpact(
     ir.Member member,
@@ -438,9 +439,16 @@
     List<DartType> typeArguments = _visitArguments(node.arguments);
     // TODO(johnniwinther): Restrict the dynamic use to only match the known
     // target.
-    impactBuilder.registerDynamicUse(new GenericDynamicUse(
-        new Selector.call(elementMap.getMember(node.target).memberName,
-            elementMap.getCallStructure(node.arguments)),
+    ReceiverConstraint constraint;
+    MemberEntity member = elementMap.getMember(node.target);
+    if (_options.strongMode && useStrongModeWorldStrategy) {
+      // TODO(johnniwinther): Restrict this to subclasses?
+      constraint = new StrongModeConstraint(member.enclosingClass);
+    }
+    impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+        new Selector.call(
+            member.memberName, elementMap.getCallStructure(node.arguments)),
+        constraint,
         typeArguments));
   }
 
@@ -514,10 +522,10 @@
   }
 
   @override
-  void visitMethodInvocation(ir.MethodInvocation invocation) {
-    Selector selector = elementMap.getSelector(invocation);
-    List<DartType> typeArguments = _visitArguments(invocation.arguments);
-    var receiver = invocation.receiver;
+  void visitMethodInvocation(ir.MethodInvocation node) {
+    Selector selector = elementMap.getSelector(node);
+    List<DartType> typeArguments = _visitArguments(node.arguments);
+    var receiver = node.receiver;
     if (receiver is ir.VariableGet &&
         receiver.variable.isFinal &&
         receiver.variable.parent is ir.FunctionDeclaration) {
@@ -530,25 +538,49 @@
             localFunction, selector.callStructure, typeArguments));
       }
     } else {
-      visitNode(invocation.receiver);
-      impactBuilder
-          .registerDynamicUse(new GenericDynamicUse(selector, typeArguments));
+      visitNode(node.receiver);
+      ReceiverConstraint constraint;
+      if (_options.strongMode && useStrongModeWorldStrategy) {
+        DartType receiverType = elementMap.getStaticType(node.receiver);
+        if (receiverType is InterfaceType) {
+          constraint = new StrongModeConstraint(receiverType.element);
+        }
+      }
+
+      impactBuilder.registerDynamicUse(
+          new ConstrainedDynamicUse(selector, constraint, typeArguments));
     }
   }
 
   @override
   void visitPropertyGet(ir.PropertyGet node) {
     visitNode(node.receiver);
-    impactBuilder.registerDynamicUse(
-        new DynamicUse(new Selector.getter(elementMap.getName(node.name))));
+    ReceiverConstraint constraint;
+    if (_options.strongMode && useStrongModeWorldStrategy) {
+      DartType receiverType = elementMap.getStaticType(node.receiver);
+      if (receiverType is InterfaceType) {
+        constraint = new StrongModeConstraint(receiverType.element);
+      }
+    }
+    impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+        new Selector.getter(elementMap.getName(node.name)),
+        constraint, const <DartType>[]));
   }
 
   @override
   void visitPropertySet(ir.PropertySet node) {
     visitNode(node.receiver);
     visitNode(node.value);
-    impactBuilder.registerDynamicUse(
-        new DynamicUse(new Selector.setter(elementMap.getName(node.name))));
+    ReceiverConstraint constraint;
+    if (_options.strongMode && useStrongModeWorldStrategy) {
+      DartType receiverType = elementMap.getStaticType(node.receiver);
+      if (receiverType is InterfaceType) {
+        constraint = new StrongModeConstraint(receiverType.element);
+      }
+    }
+    impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+        new Selector.setter(elementMap.getName(node.name)),
+        constraint, const <DartType>[]));
   }
 
   @override
@@ -561,6 +593,7 @@
 
   @override
   void visitInstantiation(ir.Instantiation node) {
+    // TODO(johnniwinther): Track which arities are used in instantiation.
     impactBuilder.registerFeature(Feature.GENERIC_INSTANTIATION);
     node.visitChildren(this);
   }
@@ -632,8 +665,11 @@
     visitNode(node.variable);
     visitNode(node.iterable);
     visitNode(node.body);
+    // TODO(johnniwinther): Use receiver constraints for the dynamic uses in
+    // strong mode.
     if (node.isAsync) {
       impactBuilder.registerFeature(Feature.ASYNC_FOR_IN);
+      impactBuilder.registerDynamicUse(new DynamicUse(Selectors.cancel));
     } else {
       impactBuilder.registerFeature(Feature.SYNC_FOR_IN);
       impactBuilder.registerDynamicUse(new DynamicUse(Selectors.iterator));
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 40c6687..5aa3fc6 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -420,7 +420,8 @@
           }
         }
       } else if (input.isStringOrNull(_closedWorld)) {
-        if (applies(commonElements.jsStringSplit)) {
+        if (commonElements.appliesToJsStringSplit(
+            selector, mask, _closedWorld)) {
           return handleStringSplit(node);
         } else if (applies(commonElements.jsStringOperatorAdd)) {
           // `operator+` is turned into a JavaScript '+' so we need to
@@ -456,7 +457,7 @@
         return result;
       }
     } else if (selector.isGetter) {
-      if (selector.applies(commonElements.jsIndexableLength)) {
+      if (commonElements.appliesToJsIndexableLength(selector)) {
         HInstruction optimized = tryOptimizeLengthInterceptedGetter(node);
         if (optimized != null) return optimized;
       }
@@ -2672,12 +2673,20 @@
   }
 
   void visitGetLength(HGetLength instruction) {
-    _visitFieldGet(closedWorld.commonElements.jsIndexableLength,
-        instruction.receiver.nonCheck(), instruction);
+    HInstruction receiver = instruction.receiver.nonCheck();
+    HInstruction existing =
+        memorySet.lookupFieldValue(MemoryFeature.length, receiver);
+    if (existing != null) {
+      checkNewGvnCandidates(instruction, existing);
+      instruction.block.rewriteWithBetterUser(instruction, existing);
+      instruction.block.remove(instruction);
+    } else {
+      memorySet.registerFieldValue(MemoryFeature.length, receiver, instruction);
+    }
   }
 
   void _visitFieldGet(
-      MemberEntity element, HInstruction receiver, HInstruction instruction) {
+      FieldEntity element, HInstruction receiver, HInstruction instruction) {
     HInstruction existing = memorySet.lookupFieldValue(element, receiver);
     if (existing != null) {
       checkNewGvnCandidates(instruction, existing);
@@ -2831,50 +2840,48 @@
   void visitTypeInfoExpression(HTypeInfoExpression instruction) {}
 }
 
-/**
- * Holds values of memory places.
- *
- * Generally, values that name a place (a receiver) have type refinements and
- * other checks removed to ensure that checks and type refinements do not
- * confuse aliasing.  Values stored into a memory place keep the type
- * refinements to help further optimizations.
- */
+/// A non-field based feature of an object.
+enum MemoryFeature {
+  // Access to the `length` property of a `JSIndexable`.
+  length,
+}
+
+/// Holds values of memory places.
+///
+/// Generally, values that name a place (a receiver) have type refinements and
+/// other checks removed to ensure that checks and type refinements do not
+/// confuse aliasing.  Values stored into a memory place keep the type
+/// refinements to help further optimizations.
 class MemorySet {
   final ClosedWorld closedWorld;
 
-  /**
-   * Maps a field to a map of receiver to value.
-   */
-  // The key is [MemberEntity] rather than [FieldEntity] so that HGetLength can
-  // be modeled as the JSIndexable.length abstract getter.
+  /// Maps a field to a map of receivers to their current field values.
+  ///
+  /// The field is either a [FieldEntity], a [FunctionEntity] in case of
+  /// instance methods, or a [MemoryFeature] for `length` access on
+  /// `JSIndexable`.
+  ///
   // TODO(25544): Split length effects from other effects and model lengths
   // separately.
-  final Map<MemberEntity, Map<HInstruction, HInstruction>> fieldValues =
-      <MemberEntity, Map<HInstruction, HInstruction>>{};
+  final Map<Object /*MemberEntity|MemoryFeature*/,
+          Map<HInstruction, HInstruction>>
+      fieldValues = <Object, Map<HInstruction, HInstruction>>{};
 
-  /**
-   * Maps a receiver to a map of keys to value.
-   */
+  /// Maps a receiver to a map of keys to value.
   final Map<HInstruction, Map<HInstruction, HInstruction>> keyedValues =
       <HInstruction, Map<HInstruction, HInstruction>>{};
 
-  /**
-   * Set of objects that we know don't escape the current function.
-   */
+  /// Set of objects that we know don't escape the current function.
   final Setlet<HInstruction> nonEscapingReceivers = new Setlet<HInstruction>();
 
   MemorySet(this.closedWorld);
 
-  /**
-   * Returns whether [first] and [second] always alias to the same object.
-   */
+  /// Returns whether [first] and [second] always alias to the same object.
   bool mustAlias(HInstruction first, HInstruction second) {
     return first == second;
   }
 
-  /**
-   * Returns whether [first] and [second] may alias to the same object.
-   */
+  /// Returns whether [first] and [second] may alias to the same object.
   bool mayAlias(HInstruction first, HInstruction second) {
     if (mustAlias(first, second)) return true;
     if (isConcrete(first) && isConcrete(second)) return false;
@@ -2886,8 +2893,8 @@
         .isDisjoint(second.instructionType, closedWorld);
   }
 
-  bool isFinal(MemberEntity element) {
-    return closedWorld.fieldNeverChanges(element);
+  bool isFinal(Object element) {
+    return element is MemberEntity && closedWorld.fieldNeverChanges(element);
   }
 
   bool isConcrete(HInstruction instruction) {
@@ -2900,9 +2907,7 @@
     return closedWorld.commonMasks.couldBeTypedArray(receiver.instructionType);
   }
 
-  /**
-   * Returns whether [receiver] escapes the current function.
-   */
+  /// Returns whether [receiver] escapes the current function.
   bool escapes(HInstruction receiver) {
     assert(receiver == null || receiver == receiver.nonCheck());
     return !nonEscapingReceivers.contains(receiver);
@@ -2913,21 +2918,22 @@
     nonEscapingReceivers.add(instruction);
   }
 
-  /**
-   * Sets `receiver.element` to contain [value]. Kills all potential places that
-   * may be affected by this update. Returns `true` if the update is redundant.
-   */
+  /// Sets the [field] on [receiver] to contain [value]. Kills all potential
+  /// places that may be affected by this update. Returns `true` if the update
+  /// is redundant.
   bool registerFieldValueUpdate(
-      MemberEntity element, HInstruction receiver, HInstruction value) {
+      Object field, HInstruction receiver, HInstruction value) {
+    assert(field is MemberEntity || field is MemoryFeature,
+        "Unexpected member/feature: $field");
     assert(receiver == null || receiver == receiver.nonCheck());
-    if (closedWorld.nativeData.isNativeMember(element)) {
+    if (closedWorld.nativeData.isNativeMember(field)) {
       return false; // TODO(14955): Remove this restriction?
     }
     // [value] is being set in some place in memory, we remove it from the
     // non-escaping set.
     nonEscapingReceivers.remove(value.nonCheck());
     Map<HInstruction, HInstruction> map =
-        fieldValues.putIfAbsent(element, () => <HInstruction, HInstruction>{});
+        fieldValues.putIfAbsent(field, () => <HInstruction, HInstruction>{});
     bool isRedundant = map[receiver] == value;
     map.forEach((key, value) {
       if (mayAlias(receiver, key)) map[key] = null;
@@ -2936,35 +2942,33 @@
     return isRedundant;
   }
 
-  /**
-   * Registers that `receiver.element` is now [value].
-   */
+  /// Registers that the [field] on [receiver] is now [value].
   void registerFieldValue(
-      MemberEntity element, HInstruction receiver, HInstruction value) {
+      Object field, HInstruction receiver, HInstruction value) {
+    assert(field is MemberEntity || field is MemoryFeature,
+        "Unexpected member/feature: $field");
     assert(receiver == null || receiver == receiver.nonCheck());
-    if (closedWorld.nativeData.isNativeMember(element)) {
+    if (field is MemberEntity && closedWorld.nativeData.isNativeMember(field)) {
       return; // TODO(14955): Remove this restriction?
     }
     Map<HInstruction, HInstruction> map =
-        fieldValues.putIfAbsent(element, () => <HInstruction, HInstruction>{});
+        fieldValues.putIfAbsent(field, () => <HInstruction, HInstruction>{});
     map[receiver] = value;
   }
 
-  /**
-   * Returns the value stored in `receiver.element`. Returns `null` if we don't
-   * know.
-   */
-  HInstruction lookupFieldValue(MemberEntity element, HInstruction receiver) {
+  /// Returns the value stored for [field] on [receiver]. Returns `null` if we
+  /// don't know.
+  HInstruction lookupFieldValue(Object field, HInstruction receiver) {
+    assert(field is MemberEntity || field is MemoryFeature,
+        "Unexpected member/feature: $field");
     assert(receiver == null || receiver == receiver.nonCheck());
-    Map<HInstruction, HInstruction> map = fieldValues[element];
+    Map<HInstruction, HInstruction> map = fieldValues[field];
     return (map == null) ? null : map[receiver];
   }
 
-  /**
-   * Kill all places that may be affected by this [instruction]. Also update the
-   * set of non-escaping objects in case [instruction] has non-escaping objects
-   * in its inputs.
-   */
+  /// Kill all places that may be affected by this [instruction]. Also update
+  /// the set of non-escaping objects in case [instruction] has non-escaping
+  /// objects in its inputs.
   void killAffectedBy(HInstruction instruction) {
     // Even if [instruction] does not have side effects, it may use non-escaping
     // objects and store them in a new object, which make these objects
@@ -2975,9 +2979,10 @@
 
     if (instruction.sideEffects.changesInstanceProperty() ||
         instruction.sideEffects.changesStaticProperty()) {
-      List<MemberEntity> fieldsToRemove;
       List<HInstruction> receiversToRemove = <HInstruction>[];
-      fieldValues.forEach((MemberEntity element, map) {
+
+      List<Object> fieldsToRemove;
+      fieldValues.forEach((Object element, map) {
         if (isFinal(element)) return;
         map.forEach((receiver, value) {
           if (escapes(receiver)) {
@@ -2986,7 +2991,7 @@
         });
         if (receiversToRemove.length == map.length) {
           // Remove them all by removing the entire map.
-          (fieldsToRemove ??= <MemberEntity>[]).add(element);
+          (fieldsToRemove ??= <Object>[]).add(element);
         } else {
           receiversToRemove.forEach(map.remove);
         }
@@ -3006,18 +3011,14 @@
     }
   }
 
-  /**
-   * Returns the value stored in `receiver[index]`. Returns null if
-   * we don't know.
-   */
+  /// Returns the value stored in `receiver[index]`. Returns null if we don't
+  /// know.
   HInstruction lookupKeyedValue(HInstruction receiver, HInstruction index) {
     Map<HInstruction, HInstruction> map = keyedValues[receiver];
     return (map == null) ? null : map[index];
   }
 
-  /**
-   * Registers that `receiver[index]` is now [value].
-   */
+  /// Registers that `receiver[index]` is now [value].
   void registerKeyedValue(
       HInstruction receiver, HInstruction index, HInstruction value) {
     Map<HInstruction, HInstruction> map =
@@ -3025,10 +3026,8 @@
     map[index] = value;
   }
 
-  /**
-   * Sets `receiver[index]` to contain [value]. Kills all potential
-   * places that may be affected by this update.
-   */
+  /// Sets `receiver[index]` to contain [value]. Kills all potential places that
+  /// may be affected by this update.
   void registerKeyedValueUpdate(
       HInstruction receiver, HInstruction index, HInstruction value) {
     nonEscapingReceivers.remove(value.nonCheck());
@@ -3053,11 +3052,11 @@
     map[index] = value;
   }
 
-  /**
-   * Returns null if either [first] or [second] is null. Otherwise
-   * returns [first] if [first] and [second] are equal. Otherwise
-   * creates or re-uses a phi in [block] that holds [first] and [second].
-   */
+  /// Returns a common instruction for [first] and [second].
+  ///
+  /// Returns `null` if either [first] or [second] is null. Returns [first] if
+  /// [first] and [second] are equal. Otherwise creates or re-uses a phi in
+  /// [block] that holds [first] and [second].
   HInstruction findCommonInstruction(HInstruction first, HInstruction second,
       HBasicBlock block, int predecessorIndex) {
     if (first == null || second == null) return null;
@@ -3110,9 +3109,7 @@
     }
   }
 
-  /**
-   * Returns the intersection between [this] and [other].
-   */
+  /// Returns the intersection between [this] and the [other] memory set.
   MemorySet intersectionFor(
       MemorySet other, HBasicBlock block, int predecessorIndex) {
     MemorySet result = new MemorySet(closedWorld);
@@ -3195,9 +3192,7 @@
     return result;
   }
 
-  /**
-   * Returns a copy of [this].
-   */
+  /// Returns a copy of [this] memory set.
   MemorySet clone() {
     MemorySet result = new MemorySet(closedWorld);
 
diff --git a/pkg/compiler/lib/src/ssa/ssa.dart b/pkg/compiler/lib/src/ssa/ssa.dart
index c87eae7..4dd04bc 100644
--- a/pkg/compiler/lib/src/ssa/ssa.dart
+++ b/pkg/compiler/lib/src/ssa/ssa.dart
@@ -48,9 +48,9 @@
     if (element is FunctionEntity) {
       SourceInformationBuilder sourceInformationBuilder =
           backend.sourceInformationStrategy.createBuilderForContext(element);
-
       result = backend.rewriteAsync(
           closedWorld.commonElements,
+          closedWorld.elementEnvironment,
           element,
           result,
           sourceInformationBuilder.buildAsyncBody(),
diff --git a/pkg/compiler/lib/src/types/type_mask.dart b/pkg/compiler/lib/src/types/type_mask.dart
index 7af49b4..bf79fb9 100644
--- a/pkg/compiler/lib/src/types/type_mask.dart
+++ b/pkg/compiler/lib/src/types/type_mask.dart
@@ -44,9 +44,7 @@
       _masks = null;
       return true;
     }
-    if (_masks == null) {
-      _masks = new Setlet<TypeMask>();
-    }
+    _masks ??= new Set<TypeMask>();
     return _masks.add(mask);
   }
 
diff --git a/pkg/compiler/lib/src/universe/class_hierarchy_builder.dart b/pkg/compiler/lib/src/universe/class_hierarchy_builder.dart
index e45c3ac..c6cf563 100644
--- a/pkg/compiler/lib/src/universe/class_hierarchy_builder.dart
+++ b/pkg/compiler/lib/src/universe/class_hierarchy_builder.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 '../common.dart';
 import '../common_elements.dart';
 import '../elements/elements.dart' show ClassElement, MixinApplicationElement;
 import '../elements/entities.dart';
@@ -53,11 +54,21 @@
       }
 
       ClassEntity appliedMixin = _classQueries.getAppliedMixin(cls);
-      if (appliedMixin != null) {
-        // TODO(johnniwinther): Store this in the [ClassSet].
+      while (appliedMixin != null) {
+        // TODO(johnniwinther): Use the data stored in [ClassSet].
         registerMixinUse(cls, appliedMixin);
-      }
+        ClassSet mixinSet = _ensureClassSet(appliedMixin);
+        mixinSet.addMixinApplication(node);
 
+        // In case of
+        //
+        //    class A {}
+        //    class B = Object with A;
+        //    class C = Object with B;
+        //
+        // we need to register that C not only mixes in B but also A.
+        appliedMixin = _classQueries.getAppliedMixin(appliedMixin);
+      }
       return classSet;
     });
   }
@@ -78,7 +89,7 @@
 
   void updateClassHierarchyNodeForClass(ClassEntity cls,
       {bool directlyInstantiated: false, bool abstractlyInstantiated: false}) {
-    ClassHierarchyNode node = _ensureClassHierarchyNode(cls);
+    ClassHierarchyNode node = _ensureClassSet(cls).node;
     _updateSuperClassHierarchyNodeForClass(node);
     if (directlyInstantiated) {
       node.isDirectlyInstantiated = true;
@@ -95,6 +106,50 @@
         mixinUses.putIfAbsent(mixin, () => new Set<ClassEntity>());
     users.add(mixinApplication);
   }
+
+  bool _isSubtypeOf(ClassEntity x, ClassEntity y) {
+    assert(
+        classSets.containsKey(x), "ClassSet for $x has not been computed yet.");
+    ClassSet classSet = classSets[y];
+    assert(classSet != null,
+        failedAt(y, "No ClassSet for $y (${y.runtimeType}): ${classSets}"));
+    ClassHierarchyNode classHierarchyNode = classHierarchyNodes[x];
+    assert(classHierarchyNode != null,
+        failedAt(x, "No ClassHierarchyNode for $x"));
+    return classSet.hasSubtype(classHierarchyNode);
+  }
+
+  bool isInheritedInSubtypeOf(ClassEntity x, ClassEntity y) {
+    ClassSet classSet = classSets[x];
+    assert(classSet != null,
+        failedAt(x, "No ClassSet for $x (${x.runtimeType}): ${classSets}"));
+
+    if (_isSubtypeOf(x, y)) {
+      // [x] implements [y] itself, possible through supertypes.
+      return true;
+    }
+
+    /// Returns `true` if any live subclass of [node] implements [y].
+    bool subclassImplements(ClassHierarchyNode node, {bool strict}) {
+      return node.anySubclass((ClassEntity z) => _isSubtypeOf(z, y),
+          ClassHierarchyNode.INSTANTIATED,
+          strict: strict);
+    }
+
+    if (subclassImplements(classSet.node, strict: true)) {
+      // A subclass of [x] implements [y].
+      return true;
+    }
+
+    for (ClassHierarchyNode mixinApplication
+        in classSet.mixinApplicationNodes) {
+      if (subclassImplements(mixinApplication, strict: false)) {
+        // A subclass of [mixinApplication] implements [y].
+        return true;
+      }
+    }
+    return false;
+  }
 }
 
 abstract class ClassQueries {
@@ -105,6 +160,11 @@
   ClassEntity getDeclaration(covariant ClassEntity cls);
 
   /// Returns the class mixed into [cls] if any.
+  // TODO(johnniwinther): Replace this by a `getAppliedMixins` function that
+  // return transitively mixed in classes like in:
+  //     class A {}
+  //     class B = Object with A;
+  //     class C = Object with B;
   ClassEntity getAppliedMixin(covariant ClassEntity cls);
 
   /// Returns the hierarchy depth of [cls].
diff --git a/pkg/compiler/lib/src/universe/class_set.dart b/pkg/compiler/lib/src/universe/class_set.dart
index 13a0cdb..c5a4869 100644
--- a/pkg/compiler/lib/src/universe/class_set.dart
+++ b/pkg/compiler/lib/src/universe/class_set.dart
@@ -482,6 +482,22 @@
   ///
   List<ClassHierarchyNode> _subtypes;
 
+  /// A list of the class hierarchy nodes for the class that directly mix in
+  /// [cls].
+  ///
+  /// For instance
+  ///
+  ///     class A {}
+  ///     class B extends Object with A {}
+  ///     class C = Object with A;
+  ///     class D extends B {}
+  ///     class E extends C {}
+  ///
+  /// The class hierarchy nodes for the unnamed mixin application `Object+A` and
+  /// the named mixin application `C` are in [_mixinApplications].
+  ///
+  List<ClassHierarchyNode> _mixinApplications;
+
   ClassSet(this.node);
 
   ClassEntity get cls => node.cls;
@@ -531,6 +547,10 @@
     return _subtypes ?? const <ClassHierarchyNode>[];
   }
 
+  Iterable<ClassHierarchyNode> get mixinApplicationNodes {
+    return _mixinApplications ?? const <ClassHierarchyNode>[];
+  }
+
   /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
   ///
   /// Subclasses are included if their instantiation properties intersect with
@@ -701,6 +721,15 @@
     }
   }
 
+  /// Adds [mixinApplication] as a class that mixes in [cls].
+  void addMixinApplication(ClassHierarchyNode mixinApplication) {
+    if (_mixinApplications == null) {
+      _mixinApplications = <ClassHierarchyNode>[mixinApplication];
+    } else {
+      _mixinApplications.add(mixinApplication);
+    }
+  }
+
   /// Returns the most specific subtype of [cls] (including [cls]) that is
   /// directly instantiated or a superclass of all directly instantiated
   /// subtypes. If no subtypes of [cls] are instantiated, `null` is returned.
@@ -743,11 +772,19 @@
     node.printOn(sb, '  ');
     sb.write('\n');
     if (_subtypes != null) {
+      sb.write('  subtypes:\n');
       for (ClassHierarchyNode node in _subtypes) {
         node.printOn(sb, '  ');
         sb.write('\n');
       }
     }
+    if (_mixinApplications != null) {
+      sb.write('  mixin-applications:\n');
+      for (ClassHierarchyNode node in _mixinApplications) {
+        node.printOn(sb, '  ');
+        sb.write('\n');
+      }
+    }
     sb.write(']');
     return sb.toString();
   }
diff --git a/pkg/compiler/lib/src/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
index fa33d69..d679a67 100644
--- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
@@ -463,6 +463,9 @@
 
   _MemberUsage _getMemberUsage(
       covariant MemberEntity member, MemberUsedCallback memberUsed) {
+    // TODO(johnniwinther): Change [TypeMask] to not apply to a superclass
+    // member unless the class has been instantiated. Similar to
+    // [StrongModeConstraint].
     return _instanceMemberUsage.putIfAbsent(member, () {
       String memberName = member.name;
       ClassEntity cls = member.enclosingClass;
@@ -470,13 +473,13 @@
       _MemberUsage usage = new _MemberUsage(member, isNative: isNative);
       EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
       useSet.addAll(usage.appliedUse);
-      if (hasInvokedGetter(member, _world)) {
+      if (!usage.hasRead && hasInvokedGetter(member, _world)) {
         useSet.addAll(usage.read());
       }
-      if (hasInvokedSetter(member, _world)) {
+      if (!usage.hasWrite && hasInvokedSetter(member, _world)) {
         useSet.addAll(usage.write());
       }
-      if (hasInvocation(member, _world)) {
+      if (!usage.hasInvoke && hasInvocation(member, _world)) {
         useSet.addAll(usage.invoke());
       }
 
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index 160f196..fc3502f 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -520,10 +520,17 @@
       } else {
         kind = Instantiation.DIRECTLY_INSTANTIATED;
       }
-      _processInstantiatedClass(cls, classUsed);
     }
     info.addInstantiation(constructor, type, kind,
         isRedirection: isRedirection);
+    if (kind != Instantiation.UNINSTANTIATED) {
+      if (_options.strongMode) {
+        classHierarchyBuilder.updateClassHierarchyNodeForClass(cls,
+            directlyInstantiated: info.isDirectlyInstantiated,
+            abstractlyInstantiated: info.isAbstractlyInstantiated);
+      }
+      _processInstantiatedClass(cls, classUsed);
+    }
 
     // TODO(johnniwinther): Use [_instantiationInfo] to compute this information
     // instead.
@@ -617,14 +624,14 @@
       Map<String, Map<Selector, SelectorConstraints>> selectorMap) {
     Selector selector = dynamicUse.selector;
     String name = selector.name;
-    ReceiverConstraint mask = dynamicUse.mask;
+    ReceiverConstraint constraint = dynamicUse.mask;
     Map<Selector, SelectorConstraints> selectors = selectorMap.putIfAbsent(
         name, () => new Maplet<Selector, SelectorConstraints>());
     UniverseSelectorConstraints constraints =
         selectors.putIfAbsent(selector, () {
       return selectorConstraintsStrategy.createSelectorConstraints(selector);
     });
-    return constraints.addReceiverConstraint(mask);
+    return constraints.addReceiverConstraint(constraint);
   }
 
   void registerIsCheck(covariant DartType type) {
@@ -799,10 +806,12 @@
     // its metadata parsed and analyzed.
     // Note: this assumes that there are no non-native fields on native
     // classes, which may not be the case when a native class is subclassed.
-    _memberUsage.putIfAbsent(member, () {
+    bool newUsage = false;
+    _MemberUsage usage = _memberUsage.putIfAbsent(member, () {
+      newUsage = true;
       bool isNative = _nativeBasicData.isNativeClass(cls);
-      _MemberUsage usage = new _MemberUsage(member, isNative: isNative);
       EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
+      _MemberUsage usage = new _MemberUsage(member, isNative: isNative);
       useSet.addAll(usage.appliedUse);
       if (member.isField && isNative) {
         registerUsedElement(member);
@@ -813,13 +822,13 @@
         closurizedMembersWithFreeTypeVariables.add(member);
       }
 
-      if (_hasInvokedGetter(member)) {
+      if (!usage.hasRead && _hasInvokedGetter(member)) {
         useSet.addAll(usage.read());
       }
-      if (_hasInvocation(member)) {
+      if (!usage.hasInvoke && _hasInvocation(member)) {
         useSet.addAll(usage.invoke());
       }
-      if (hasInvokedSetter(member)) {
+      if (!usage.hasWrite && hasInvokedSetter(member)) {
         useSet.addAll(usage.write());
       }
 
@@ -837,10 +846,28 @@
             .putIfAbsent(memberName, () => new Set<_MemberUsage>())
             .add(usage);
       }
-
       memberUsed(usage.entity, useSet);
       return usage;
     });
+    if (!newUsage) {
+      EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
+      if (!usage.hasRead && _hasInvokedGetter(member)) {
+        useSet.addAll(usage.read());
+      }
+      if (!usage.hasInvoke && _hasInvocation(member)) {
+        useSet.addAll(usage.invoke());
+      }
+      if (!usage.hasWrite && hasInvokedSetter(member)) {
+        useSet.addAll(usage.write());
+      }
+      if (!usage.pendingUse.contains(MemberUse.NORMAL)) {
+        _instanceMembersByName[memberName]?.remove(usage);
+      }
+      if (!usage.pendingUse.contains(MemberUse.CLOSURIZE_INSTANCE)) {
+        _instanceFunctionsByName[memberName]?.remove(usage);
+      }
+      memberUsed(usage.entity, useSet);
+    }
   }
 
   /// Returns an iterable over all mixin applications that mixin [cls].
@@ -926,6 +953,15 @@
   void registerClass(ClassEntity cls) {
     classHierarchyBuilder.registerClass(cls);
   }
+
+  bool isInheritedInSubtypeOf(MemberEntity member, ClassEntity type) {
+    // TODO(johnniwinther): Use the [member] itself to avoid enqueueing members
+    // that are overridden.
+    classHierarchyBuilder.registerClass(member.enclosingClass);
+    classHierarchyBuilder.registerClass(type);
+    return classHierarchyBuilder.isInheritedInSubtypeOf(
+        member.enclosingClass, type);
+  }
 }
 
 abstract class KernelResolutionWorldBuilderBase
diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart
index 4feb2a8..031baf2 100644
--- a/pkg/compiler/lib/src/universe/world_builder.dart
+++ b/pkg/compiler/lib/src/universe/world_builder.dart
@@ -169,6 +169,98 @@
   }
 }
 
+bool useStrongModeWorldStrategy = false;
+
+/// Open world strategy that constrains instance member access to subtypes of
+/// the static type of the receiver.
+///
+/// This strategy is used for Dart 2.
+class StrongModeWorldStrategy implements SelectorConstraintsStrategy {
+  const StrongModeWorldStrategy();
+
+  StrongModeWorldConstraints createSelectorConstraints(Selector selector) {
+    return new StrongModeWorldConstraints();
+  }
+}
+
+class StrongModeWorldConstraints extends UniverseSelectorConstraints {
+  bool isAll = false;
+  Set<StrongModeConstraint> _constraints;
+
+  @override
+  bool applies(MemberEntity element, Selector selector, World world) {
+    if (isAll) return true;
+    if (_constraints == null) return false;
+    for (StrongModeConstraint constraint in _constraints) {
+      if (constraint.canHit(element, selector, world)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @override
+  bool needsNoSuchMethodHandling(Selector selector, World world) {
+    if (isAll) {
+      return true;
+    }
+    if (_constraints != null) {
+      for (StrongModeConstraint constraint in _constraints) {
+        if (constraint.needsNoSuchMethodHandling(selector, world)) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  @override
+  bool addReceiverConstraint(StrongModeConstraint constraint) {
+    if (isAll) return false;
+    if (constraint?.cls == null) {
+      isAll = true;
+      _constraints = null;
+      return true;
+    }
+    _constraints ??= new Set<StrongModeConstraint>();
+    return _constraints.add(constraint);
+  }
+
+  String toString() {
+    if (isAll) {
+      return '<all>';
+    } else if (_constraints != null) {
+      return '<${_constraints.map((c) => c.cls).join(',')}>';
+    } else {
+      return '<none>';
+    }
+  }
+}
+
+class StrongModeConstraint implements ReceiverConstraint {
+  final ClassEntity cls;
+
+  const StrongModeConstraint(this.cls);
+
+  @override
+  bool needsNoSuchMethodHandling(Selector selector, World world) => true;
+
+  @override
+  bool canHit(MemberEntity element, Selector selector, OpenWorld world) {
+    return world.isInheritedInSubtypeOf(element, cls);
+  }
+
+  bool operator ==(other) {
+    if (identical(this, other)) return true;
+    if (other is! StrongModeConstraint) return false;
+    return cls == other.cls;
+  }
+
+  int get hashCode => cls.hashCode * 13;
+
+  String toString() => 'StrongModeConstraint($cls)';
+}
+
 /// The [WorldBuilder] is an auxiliary class used in the process of computing
 /// the [ClosedWorld].
 // TODO(johnniwinther): Move common implementation to a [WorldBuilderBase] when
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 183575c..bfe1a5d 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -404,6 +404,21 @@
 
   /// Returns an iterable over all mixin applications that mixin [cls].
   Iterable<ClassEntity> allMixinUsesOf(ClassEntity cls);
+
+  /// Returns `true` if [member] is inherited into a subtype of [type].
+  ///
+  /// For instance:
+  ///
+  ///     class A { m() {} }
+  ///     class B extends A implements I {}
+  ///     class C extends Object with A implements I {}
+  ///     abstract class I { m(); }
+  ///     abstract class J implements A { }
+  ///
+  /// Here `A.m` is inherited into `A`, `B`, and `C`. Becausec `B` and
+  /// `C` implement `I`, `isInheritedInSubtypeOf(A.M, I)` is true, but
+  /// `isInheritedInSubtypeOf(A.M, J)` is false.
+  bool isInheritedInSubtypeOf(MemberEntity member, ClassEntity type);
 }
 
 /// Enum values defining subset of classes included in queries.
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/generators.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/generators.dart
index d8f20d7..e6cfecf 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/generators.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/generators.dart
@@ -13,8 +13,8 @@
 
 // TODO(vsm): Remove once this flag is the default.
 bool startAsyncSynchronously = false;
-void setStartAsyncSynchronously() {
-  startAsyncSynchronously = true;
+void setStartAsyncSynchronously([bool value = true]) {
+  startAsyncSynchronously = value;
 }
 
 final _jsIterator = JS('', 'Symbol("_jsIterator")');
diff --git a/pkg/dev_compiler/tool/input_sdk/private/isolate_helper.dart b/pkg/dev_compiler/tool/input_sdk/private/isolate_helper.dart
index 3facf9e..dec36ce 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/isolate_helper.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/isolate_helper.dart
@@ -35,13 +35,13 @@
   if (args == null) args = <String>[];
   if (args is List) {
     if (args is! List<String>) args = new List<String>.from(args);
-    if (main is _MainFunction) {
-      main();
-    } else if (main is _MainFunctionArgs) {
-      main(args);
-    } else if (main is _MainFunctionArgsMessage) {
-      main(args, null);
+    // DDC attaches signatures only when torn off, and the typical way of
+    // getting `main` via the JS ABI won't do this. So use JS to invoke main.
+    if (JS<bool>('!', 'typeof # == "function"', main)) {
+      // JS will ignore extra arguments.
+      JS('', '#(#, #)', main, args, null);
     } else {
+      // Not a function. Use a dynamic call to throw an error.
       (main as dynamic)(args);
     }
   } else {
@@ -53,10 +53,6 @@
 // those uses to just refer to the one in dart:runtime.
 final global = dart.global_;
 
-typedef _MainFunction();
-typedef _MainFunctionArgs(List<String> args);
-typedef _MainFunctionArgsMessage(List<String> args, Null message);
-
 class TimerImpl implements Timer {
   final bool _once;
   int _handle;
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 41f5b16..1513772 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -3656,6 +3656,69 @@
     tip: r"""Try adding a parameter list to the function declaration.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateMissingImplementationCause =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""'#name' is defined here.""",
+        withArguments: _withArgumentsMissingImplementationCause);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeMissingImplementationCause =
+    const Code<Message Function(String name)>(
+        "MissingImplementationCause", templateMissingImplementationCause,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsMissingImplementationCause(String name) {
+  return new Message(codeMissingImplementationCause,
+      message: """'$name' is defined here.""", arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String
+            string)> templateMissingImplementationNotAbstract = const Template<
+        Message Function(String name, String string)>(
+    messageTemplate:
+        r"""The non-abstract class '#name' is missing implementations for these members:
+  #string.""",
+    tipTemplate: r"""Try to either
+ - provide an implementation,
+ - inherit an implementation from a superclass or mixin,
+ - mark the class as abstract, or
+ - provide a 'noSuchMethod' implementation.
+""",
+    withArguments: _withArgumentsMissingImplementationNotAbstract);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String string)>
+    codeMissingImplementationNotAbstract =
+    const Code<Message Function(String name, String string)>(
+        "MissingImplementationNotAbstract",
+        templateMissingImplementationNotAbstract,
+        analyzerCode: "CONCRETE_CLASS_WITH_ABSTRACT_MEMBER",
+        dart2jsCode: "*fatal*",
+        severity: Severity.errorLegacyWarning);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsMissingImplementationNotAbstract(
+    String name, String string) {
+  return new Message(codeMissingImplementationNotAbstract,
+      message:
+          """The non-abstract class '$name' is missing implementations for these members:
+  $string.""",
+      tip: """Try to either
+ - provide an implementation,
+ - inherit an implementation from a superclass or mixin,
+ - mark the class as abstract, or
+ - provide a 'noSuchMethod' implementation.
+""",
+      arguments: {'name': name, 'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeMissingInput = messageMissingInput;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
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 be422f2..6584f7c 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
@@ -29,6 +29,8 @@
 
 import 'package:kernel/clone.dart' show CloneWithoutBody;
 
+import 'package:kernel/core_types.dart' show CoreTypes;
+
 import 'package:kernel/type_algebra.dart' show Substitution, getSubstitutionMap;
 
 import 'package:kernel/type_environment.dart' show TypeEnvironment;
@@ -37,12 +39,15 @@
 
 import '../fasta_codes.dart'
     show
+        LocatedMessage,
         Message,
         messagePatchClassOrigin,
         messagePatchClassTypeVariablesMismatch,
         messagePatchDeclarationMismatch,
         messagePatchDeclarationOrigin,
         noLength,
+        templateMissingImplementationCause,
+        templateMissingImplementationNotAbstract,
         templateOverriddenMethodCause,
         templateOverrideFewerNamedArguments,
         templateOverrideFewerPositionalArguments,
@@ -288,6 +293,66 @@
     });
   }
 
+  void checkAbstractMembers(CoreTypes coreTypes, ClassHierarchy hierarchy) {
+    if (isAbstract ||
+        hierarchy.getDispatchTarget(cls, noSuchMethodName).enclosingClass !=
+            coreTypes.objectClass) {
+      // Unimplemented members allowed
+      // TODO(dmitryas): Call hasUserDefinedNoSuchMethod instead when ready.
+      return;
+    }
+
+    List<LocatedMessage> context = null;
+
+    void findMissingImplementations({bool setters}) {
+      List<Member> dispatchTargets =
+          hierarchy.getDispatchTargets(cls, setters: setters);
+      int targetIndex = 0;
+      for (Member interfaceMember
+          in hierarchy.getInterfaceMembers(cls, setters: setters)) {
+        // Is this either a public member or a visible private member?
+        if (!interfaceMember.name.isPrivate ||
+            (interfaceMember.enclosingLibrary == cls.enclosingLibrary &&
+                interfaceMember.fileUri ==
+                    interfaceMember.enclosingClass.fileUri)) {
+          while (targetIndex < dispatchTargets.length &&
+              ClassHierarchy.compareMembers(
+                      dispatchTargets[targetIndex], interfaceMember) <
+                  0) {
+            targetIndex++;
+          }
+          if (targetIndex >= dispatchTargets.length ||
+              ClassHierarchy.compareMembers(
+                      dispatchTargets[targetIndex], interfaceMember) >
+                  0) {
+            Name name = interfaceMember.name;
+            String displayName = name.name + (setters ? "=" : "");
+            context ??= <LocatedMessage>[];
+            context.add(templateMissingImplementationCause
+                .withArguments(displayName)
+                .withLocation(interfaceMember.fileUri,
+                    interfaceMember.fileOffset, name.name.length));
+          }
+        }
+      }
+    }
+
+    findMissingImplementations(setters: false);
+    findMissingImplementations(setters: true);
+
+    if (context?.isNotEmpty ?? false) {
+      String memberString =
+          context.map((message) => "'${message.arguments["name"]}'").join(", ");
+      library.addProblem(
+          templateMissingImplementationNotAbstract.withArguments(
+              cls.name, memberString),
+          cls.fileOffset,
+          cls.name.length,
+          cls.fileUri,
+          context: context);
+    }
+  }
+
   // TODO(dmitryas): Find a better place for this routine.
   static bool hasUserDefinedNoSuchMethod(
       Class klass, ClassHierarchy hierarchy) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index cfeaeab..4255dbc 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -262,6 +262,7 @@
         loader.performTopLevelInference(myClasses);
       }
       loader.checkOverrides(myClasses);
+      loader.checkAbstractMembers(myClasses);
       loader.addNoSuchMethodForwarders(myClasses);
     } on deprecated_InputError catch (e) {
       ticker.logMs("Got deprecated_InputError");
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
index b72575b..b2969e2 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
@@ -64,8 +64,7 @@
 
   /// Identifier is a field initializer in a formal parameter list (i.e. it
   /// appears directly after `this.`).
-  static const fieldInitializer =
-      const IdentifierContext('fieldInitializer', isContinuation: true);
+  static const fieldInitializer = const FieldInitializerIdentifierContext();
 
   /// Identifier is a formal parameter being declared as part of a function,
   /// method, or typedef declaration.
@@ -246,7 +245,7 @@
 
   /// Identifier is a name being declared by a local variable declaration.
   static const localVariableDeclaration =
-      const IdentifierContext('localVariableDeclaration', inDeclaration: true);
+      const LocalVariableDeclarationIdentifierContext();
 
   /// Identifier is a reference to a label (e.g. `foo` in `break foo;`).
   /// Labels have their own scope.
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
index 8922d33..a5e4efa 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
@@ -63,12 +63,21 @@
   Token ensureIdentifier(Token token, Parser parser) {
     Token identifier = token.next;
     assert(identifier.kind != IDENTIFIER_TOKEN);
+    const followingValues = const ['.', '==', ')'];
+
     if (identifier.isIdentifier) {
-      return identifier;
+      // DottedNameIdentifierContext are only used in conditional import
+      // expressions. Although some top level keywords such as `import` can be
+      // used as identifiers, they are more likely the start of the next
+      // directive or declaration.
+      if (!identifier.isTopLevelKeyword ||
+          isOneOfOrEof(identifier.next, followingValues)) {
+        return identifier;
+      }
     }
 
     if (looksLikeStartOfNextDeclaration(identifier) ||
-        isOneOfOrEof(identifier, const ['.', '==', ')'])) {
+        isOneOfOrEof(identifier, followingValues)) {
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: fasta.templateExpectedIdentifier.withArguments(identifier));
     } else {
@@ -94,50 +103,64 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token next = token.next;
-    assert(next.kind != IDENTIFIER_TOKEN);
-    if (next.isIdentifier) {
-      if (optional('await', next) && next.next.isIdentifier) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      if (optional('await', identifier) && identifier.next.isIdentifier) {
         // Although the `await` can be used in an expression,
         // it is followed by another identifier which does not form
         // a valid expression. Report an error on the `await` token
         // rather than the token following it.
         parser.reportRecoverableErrorWithToken(
-            next, fasta.templateUnexpectedToken);
+            identifier, fasta.templateUnexpectedToken);
 
         // TODO(danrubel) Consider a new listener event so that analyzer
         // can represent this as an await expression in a context that does
         // not allow await.
-        return next.next;
-      } else if (!parser.inPlainSync && next.type.isPseudo) {
-        if (optional('await', next)) {
-          parser.reportRecoverableError(next, fasta.messageAwaitAsIdentifier);
-        } else if (optional('yield', next)) {
-          parser.reportRecoverableError(next, fasta.messageYieldAsIdentifier);
-        } else if (optional('async', next)) {
-          parser.reportRecoverableError(next, fasta.messageAsyncAsIdentifier);
-        }
+        return identifier.next;
+      } else {
+        checkAsyncAwaitYieldAsIdentifier(identifier, parser);
       }
-      return next;
+      return identifier;
     }
     parser.reportRecoverableErrorWithToken(
-        next, fasta.templateExpectedIdentifier);
-    if (next.isKeywordOrIdentifier) {
-      if (!isOneOfOrEof(next, const ['as', 'is'])) {
-        return next;
+        identifier, fasta.templateExpectedIdentifier);
+    if (identifier.isKeywordOrIdentifier) {
+      if (!isOneOfOrEof(identifier, const ['as', 'is'])) {
+        return identifier;
       }
-    } else if (!next.isOperator &&
-        !isOneOfOrEof(
-            next, const ['.', ',', '(', ')', '[', ']', '}', '?', ':', ';'])) {
+    } else if (!identifier.isOperator &&
+        !isOneOfOrEof(identifier,
+            const ['.', ',', '(', ')', '[', ']', '}', '?', ':', ';'])) {
       // When in doubt, consume the token to ensure we make progress
-      token = next;
-      next = token.next;
+      token = identifier;
+      identifier = token.next;
     }
     // Insert a synthetic identifier to satisfy listeners.
     return insertSyntheticIdentifierAfter(token, parser);
   }
 }
 
+/// See [IdentifierContext].fieldInitializer
+class FieldInitializerIdentifierContext extends IdentifierContext {
+  const FieldInitializerIdentifierContext()
+      : super('fieldInitializer', isContinuation: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    assert(optional('.', token));
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      return identifier;
+    }
+    parser.reportRecoverableErrorWithToken(
+        identifier, fasta.templateExpectedIdentifier);
+    // Insert a synthetic identifier to satisfy listeners.
+    return insertSyntheticIdentifierAfter(token, parser);
+  }
+}
+
 /// See [IdentifierContext].libraryName
 class LibraryIdentifierContext extends IdentifierContext {
   const LibraryIdentifierContext()
@@ -178,6 +201,36 @@
   }
 }
 
+/// See [IdentifierContext].localVariableDeclaration
+class LocalVariableDeclarationIdentifierContext extends IdentifierContext {
+  const LocalVariableDeclarationIdentifierContext()
+      : super('localVariableDeclaration', inDeclaration: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
+      return identifier;
+    }
+    if (isOneOfOrEof(identifier, const [';', '=', ',', '{', '}']) ||
+        looksLikeStartOfNextStatement(identifier)) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: fasta.templateExpectedIdentifier.withArguments(identifier));
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, fasta.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = insertSyntheticIdentifierAfter(identifier, parser);
+      }
+    }
+    return identifier;
+  }
+}
+
 /// See [IdentifierContext].typeReference
 class TypeReferenceIdentifierContext extends IdentifierContext {
   const TypeReferenceIdentifierContext()
@@ -210,20 +263,10 @@
       // annotation is not allowed before type arguments.
       parser.reportRecoverableErrorWithToken(
           next, fasta.templateUnexpectedToken);
-
-      Token annotation = next.next;
-      if (annotation.isIdentifier) {
-        if (optional('(', annotation.next)) {
-          if (annotation.next.endGroup.next.isIdentifier) {
-            token = annotation.next.endGroup;
-            next = token.next;
-          }
-        } else if (annotation.next.isIdentifier) {
-          token = annotation;
-          next = token.next;
-        }
-      }
+      token = skipMetadata(next);
+      next = token.next;
     }
+
     if (isValidTypeReference(next)) {
       return next;
     } else if (next.isKeywordOrIdentifier) {
@@ -251,6 +294,18 @@
   }
 }
 
+void checkAsyncAwaitYieldAsIdentifier(Token identifier, Parser parser) {
+  if (!parser.inPlainSync && identifier.type.isPseudo) {
+    if (optional('await', identifier)) {
+      parser.reportRecoverableError(identifier, fasta.messageAwaitAsIdentifier);
+    } else if (optional('yield', identifier)) {
+      parser.reportRecoverableError(identifier, fasta.messageYieldAsIdentifier);
+    } else if (optional('async', identifier)) {
+      parser.reportRecoverableError(identifier, fasta.messageAsyncAsIdentifier);
+    }
+  }
+}
+
 bool isOneOfOrEof(Token token, Iterable<String> followingValues) {
   for (String tokenValue in followingValues) {
     if (optional(tokenValue, token)) {
@@ -263,3 +318,42 @@
 bool looksLikeStartOfNextDeclaration(Token token) =>
     token.isTopLevelKeyword ||
     isOneOfOrEof(token, const ['const', 'get', 'final', 'set', 'var', 'void']);
+
+bool looksLikeStartOfNextStatement(Token token) => isOneOfOrEof(token, const [
+      'assert',
+      'break',
+      'const',
+      'continue',
+      'do',
+      'final',
+      'for',
+      'if',
+      'return',
+      'switch',
+      'try',
+      'var',
+      'void',
+      'while'
+    ]);
+
+Token skipMetadata(Token token) {
+  assert(optional('@', token));
+  Token next = token.next;
+  if (next.isIdentifier) {
+    token = next;
+    next = token.next;
+    while (optional('.', next)) {
+      token = next;
+      next = token.next;
+      if (next.isIdentifier) {
+        token = next;
+        next = token.next;
+      }
+    }
+    if (optional('(', next)) {
+      token = next.endGroup;
+      next = token.next;
+    }
+  }
+  return token;
+}
diff --git a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
index 9bf2da1..83d9a8d 100644
--- a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
@@ -4,8 +4,8 @@
 
 import '../../scanner/token.dart' show Token;
 import '../messages.dart' as fasta;
+import 'member_kind.dart' show MemberKind;
 import 'parser.dart' show Parser;
-import 'type_continuation.dart' show TypeContinuation;
 import 'util.dart' show optional;
 
 bool isModifier(Token token) {
@@ -28,25 +28,6 @@
   return true;
 }
 
-TypeContinuation typeContinuationAfterVar(TypeContinuation typeContinuation) {
-  switch (typeContinuation) {
-    case TypeContinuation.NormalFormalParameter:
-    case TypeContinuation.NormalFormalParameterAfterVar:
-      return TypeContinuation.NormalFormalParameterAfterVar;
-
-    case TypeContinuation.OptionalPositionalFormalParameter:
-    case TypeContinuation.OptionalPositionalFormalParameterAfterVar:
-      return TypeContinuation.OptionalPositionalFormalParameterAfterVar;
-
-    case TypeContinuation.NamedFormalParameter:
-    case TypeContinuation.NamedFormalParameterAfterVar:
-      return TypeContinuation.NamedFormalParameterAfterVar;
-
-    default:
-      return TypeContinuation.OptionalAfterVar;
-  }
-}
-
 /// This class is used to parse modifiers in most locations where modifiers
 /// can occur, but does not call handleModifier or handleModifiers.
 class ModifierRecoveryContext {
@@ -88,18 +69,27 @@
   }
 
   /// Parse modifiers for formal parameters.
-  Token parseFormalParameterModifiers(Token token, bool isStaticOrTopLevel,
+  Token parseFormalParameterModifiers(Token token, MemberKind memberKind,
       {Token covariantToken, Token varFinalOrConst}) {
     token = parseModifiers(token,
         covariantToken: covariantToken, varFinalOrConst: varFinalOrConst);
 
-    if (isStaticOrTopLevel) {
+    if (memberKind == MemberKind.StaticMethod ||
+        memberKind == MemberKind.TopLevelMethod) {
       reportExtraneousModifier(this.covariantToken);
       this.covariantToken = null;
     }
     if (constToken != null) {
       reportExtraneousModifier(constToken);
       varFinalOrConst = null;
+    } else if (memberKind == MemberKind.GeneralizedFunctionType) {
+      if (varFinalOrConst != null) {
+        parser.reportRecoverableError(
+            varFinalOrConst, fasta.messageFunctionTypedParameterVar);
+        varFinalOrConst = null;
+        finalToken = null;
+        varToken = null;
+      }
     }
     reportExtraneousModifier(abstractToken);
     reportExtraneousModifier(externalToken);
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 394e0d5..a23beb1 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -77,16 +77,14 @@
 
 import 'member_kind.dart' show MemberKind;
 
-import 'modifier_context.dart'
-    show ModifierRecoveryContext, isModifier, typeContinuationAfterVar;
+import 'modifier_context.dart' show ModifierRecoveryContext, isModifier;
 
 import 'recovery_listeners.dart'
     show ClassHeaderRecoveryListener, ImportRecoveryListener;
 
 import 'token_stream_rewriter.dart' show TokenStreamRewriter;
 
-import 'type_continuation.dart'
-    show TypeContinuation, typeContinuationFromFormalParameterKind;
+import 'type_continuation.dart' show TypeContinuation;
 
 import 'type_info.dart'
     show
@@ -94,7 +92,7 @@
         computeType,
         isGeneralizedFunctionType,
         isValidTypeReference,
-        noTypeInfo;
+        noType;
 
 import 'util.dart' show optional;
 
@@ -772,8 +770,7 @@
       next.setNext(leftParen);
       leftParen = openParen;
     }
-    token = leftParen;
-    token = parseDottedName(token);
+    token = parseDottedName(leftParen);
     Token next = token.next;
     Token equalitySign;
     if (optional('==', next)) {
@@ -782,17 +779,14 @@
       next = token.next;
     }
     if (next != leftParen.endGroup) {
-      reportRecoverableErrorWithToken(next, fasta.templateUnexpectedToken);
       Token endGroup = leftParen.endGroup;
       if (endGroup.isSynthetic) {
         // The scanner did not place the synthetic ')' correctly, so move it.
-
-        // TODO(danrubel): Its costly to find the token before the endGroup.
-        // Consider beforeSynthetic field that points to the previous token
-        // only for synthetic tokens such as ')', '}', ']' so that the parser
-        // can easily move these to the correct location.
+        next = rewriter.moveSynthetic(token, endGroup);
+      } else {
+        reportRecoverableErrorWithToken(next, fasta.templateUnexpectedToken);
+        next = endGroup;
       }
-      next = endGroup;
     }
     token = next;
     assert(optional(')', token));
@@ -1221,9 +1215,11 @@
     assert(parameterKind != null);
     token = parseMetadataStar(token);
     Token next = token.next;
+    Token start = next;
 
-    TypeContinuation typeContinuation =
-        typeContinuationFromFormalParameterKind(parameterKind);
+    final bool inFunctionType =
+        memberKind == MemberKind.GeneralizedFunctionType;
+
     Token covariantToken;
     Token varFinalOrConst;
     if (isModifier(next)) {
@@ -1236,38 +1232,171 @@
       }
 
       if (isModifier(next)) {
-        if (optional('var', next)) {
-          typeContinuation = typeContinuationAfterVar(typeContinuation);
-          varFinalOrConst = token = next;
-          next = token.next;
-        } else if (optional('final', next)) {
-          varFinalOrConst = token = next;
-          next = token.next;
+        if (!inFunctionType) {
+          if (optional('var', next)) {
+            varFinalOrConst = token = next;
+            next = token.next;
+          } else if (optional('final', next)) {
+            varFinalOrConst = token = next;
+            next = token.next;
+          }
         }
 
         if (isModifier(next)) {
           // Recovery
           ModifierRecoveryContext context = new ModifierRecoveryContext(this);
-          token = context.parseFormalParameterModifiers(
-              token,
-              memberKind == MemberKind.StaticMethod ||
-                  memberKind == MemberKind.TopLevelMethod,
-              covariantToken: covariantToken,
-              varFinalOrConst: varFinalOrConst);
+          token = context.parseFormalParameterModifiers(token, memberKind,
+              covariantToken: covariantToken, varFinalOrConst: varFinalOrConst);
           covariantToken = context.covariantToken;
           varFinalOrConst = context.varFinalOrConst;
-          if (varFinalOrConst != null && optional('var', varFinalOrConst)) {
-            typeContinuation = typeContinuationAfterVar(typeContinuation);
-          }
           context = null;
         }
       }
     }
-    listener.beginFormalParameter(
-        next, memberKind, covariantToken, varFinalOrConst);
 
-    return parseType(
-        token, typeContinuation, null, memberKind, varFinalOrConst);
+    listener.beginFormalParameter(
+        start, memberKind, covariantToken, varFinalOrConst);
+
+    // Type is required in a generalized function type, but optional otherwise.
+    final Token beforeType = token;
+    TypeInfo typeInfo = computeType(token, inFunctionType);
+    token = typeInfo.skipType(token);
+    next = token.next;
+    if (typeInfo == noType &&
+        (optional('.', next) ||
+            (next.isIdentifier && optional('.', next.next)))) {
+      // Recovery: Malformed type reference.
+      typeInfo = computeType(beforeType, true);
+      token = typeInfo.skipType(beforeType);
+      next = token.next;
+    }
+
+    final bool isNamedParameter =
+        parameterKind == FormalParameterKind.optionalNamed;
+
+    Token thisKeyword;
+    Token periodAfterThis;
+    IdentifierContext nameContext =
+        IdentifierContext.formalParameterDeclaration;
+
+    if (!inFunctionType && optional('this', next)) {
+      thisKeyword = token = next;
+      next = token.next;
+      if (!optional('.', next)) {
+        // Recover from a missing period by inserting one.
+        next = rewriteAndRecover(
+                token,
+                fasta.templateExpectedButGot.withArguments('.'),
+                new SyntheticToken(TokenType.PERIOD, next.charOffset))
+            .next;
+      }
+      periodAfterThis = token = next;
+      next = token.next;
+      nameContext = IdentifierContext.fieldInitializer;
+    }
+
+    if (next.isIdentifier) {
+      token = next;
+      next = token.next;
+    }
+    Token beforeInlineFunctionType;
+    if (optional("<", next)) {
+      Token closer = next.endGroup;
+      if (closer != null) {
+        if (optional("(", closer.next)) {
+          if (varFinalOrConst != null) {
+            reportRecoverableError(
+                varFinalOrConst, fasta.messageFunctionTypedParameterVar);
+          }
+          beforeInlineFunctionType = token;
+          token = closer.next.endGroup;
+          next = token.next;
+        }
+      }
+    } else if (optional("(", next)) {
+      if (varFinalOrConst != null) {
+        reportRecoverableError(
+            varFinalOrConst, fasta.messageFunctionTypedParameterVar);
+      }
+      beforeInlineFunctionType = token;
+      token = next.endGroup;
+      next = token.next;
+    }
+    if (typeInfo != noType &&
+        varFinalOrConst != null &&
+        optional('var', varFinalOrConst)) {
+      reportRecoverableError(varFinalOrConst, fasta.messageTypeAfterVar);
+    }
+
+    Token endInlineFunctionType;
+    if (beforeInlineFunctionType != null) {
+      endInlineFunctionType = parseTypeVariablesOpt(beforeInlineFunctionType);
+      listener.beginFunctionTypedFormalParameter(beforeInlineFunctionType.next);
+      token = typeInfo.parseType(beforeType, this);
+      endInlineFunctionType = parseFormalParametersRequiredOpt(
+          endInlineFunctionType, MemberKind.FunctionTypedParameter);
+      listener.endFunctionTypedFormalParameter();
+
+      // Generalized function types don't allow inline function types.
+      // The following isn't allowed:
+      //    int Function(int bar(String x)).
+      if (inFunctionType) {
+        reportRecoverableError(beforeInlineFunctionType.next,
+            fasta.messageInvalidInlineFunctionType);
+      }
+    } else if (inFunctionType) {
+      token = typeInfo.ensureTypeOrVoid(beforeType, this);
+    } else {
+      token = typeInfo.parseType(beforeType, this);
+    }
+
+    Token nameToken;
+    if (periodAfterThis != null) {
+      token = periodAfterThis;
+    }
+    next = token.next;
+    if (inFunctionType && !isNamedParameter && !next.isKeywordOrIdentifier) {
+      nameToken = token.next;
+      listener.handleNoName(nameToken);
+    } else {
+      nameToken = token = ensureIdentifier(token, nameContext);
+      if (isNamedParameter && nameToken.lexeme.startsWith("_")) {
+        reportRecoverableError(nameToken, fasta.messagePrivateNamedParameter);
+      }
+    }
+    if (endInlineFunctionType != null) {
+      token = endInlineFunctionType;
+    }
+    next = token.next;
+
+    String value = next.stringValue;
+    if ((identical('=', value)) || (identical(':', value))) {
+      Token equal = next;
+      listener.beginFormalParameterDefaultValueExpression();
+      token = parseExpression(equal);
+      next = token.next;
+      listener.endFormalParameterDefaultValueExpression();
+      // TODO(danrubel): Consider removing the last parameter from the
+      // handleValuedFormalParameter event... it appears to be unused.
+      listener.handleValuedFormalParameter(equal, next);
+      if (isMandatoryFormalParameterKind(parameterKind)) {
+        reportRecoverableError(
+            equal, fasta.messageRequiredParameterWithDefault);
+      } else if (isOptionalPositionalFormalParameterKind(parameterKind) &&
+          identical(':', value)) {
+        reportRecoverableError(
+            equal, fasta.messagePositionalParameterWithEquals);
+      } else if (inFunctionType ||
+          memberKind == MemberKind.FunctionTypeAlias ||
+          memberKind == MemberKind.FunctionTypedParameter) {
+        reportRecoverableError(equal, fasta.messageFunctionTypeDefaultValue);
+      }
+    } else {
+      listener.handleFormalParameterWithoutValue(next);
+    }
+    listener.endFormalParameter(
+        thisKeyword, periodAfterThis, nameToken, parameterKind, memberKind);
+    return token;
   }
 
   /// ```
@@ -1371,37 +1500,6 @@
     return token;
   }
 
-  /// Skip over the `Function` type parameter.
-  /// For example, `Function<E>(int foo)` or `Function(foo)` or just `Function`.
-  Token skipGenericFunctionType(Token token) {
-    Token last = token;
-    Token next = token.next;
-    while (optional('Function', next)) {
-      last = token;
-      token = next;
-      next = token.next;
-      if (optional('<', next)) {
-        next = next.endGroup;
-        if (next == null) {
-          // TODO(danrubel): Consider better recovery
-          // because this is probably a type reference.
-          return token;
-        }
-        token = next;
-        next = token.next;
-      }
-      if (optional('(', next)) {
-        token = next.endGroup;
-        next = token.next;
-      }
-    }
-    if (next.isKeywordOrIdentifier) {
-      return token;
-    } else {
-      return last;
-    }
-  }
-
   /// Returns `true` if [token] matches '<' type (',' type)* '>' '(', and
   /// otherwise returns `false`. The final '(' is not part of the grammar
   /// construct `typeArguments`, but it is required here such that type
@@ -1999,8 +2097,6 @@
     } else if (context == IdentifierContext.localFunctionDeclaration ||
         context == IdentifierContext.localFunctionDeclarationContinuation) {
       followingValues = ['.', '(', '{', '=>'];
-    } else if (context == IdentifierContext.localVariableDeclaration) {
-      followingValues = [';', '=', ',', '}'];
     } else if (context == IdentifierContext.methodDeclaration ||
         context == IdentifierContext.methodDeclarationContinuation) {
       followingValues = ['.', '(', '{', '=>'];
@@ -2084,8 +2180,6 @@
     } else if (context ==
         IdentifierContext.localFunctionDeclarationContinuation) {
       initialKeywords = statementKeywords();
-    } else if (context == IdentifierContext.localVariableDeclaration) {
-      initialKeywords = statementKeywords();
     } else if (context == IdentifierContext.methodDeclaration) {
       initialKeywords = classMemberKeywords();
     } else if (context == IdentifierContext.methodDeclarationContinuation) {
@@ -2143,26 +2237,6 @@
     return token;
   }
 
-  /// Returns `true` if the stringValue of the [token] is either [value1],
-  /// [value2], or [value3].
-  bool isOneOf3(Token token, String value1, String value2, String value3) {
-    String stringValue = token.stringValue;
-    return identical(value1, stringValue) ||
-        identical(value2, stringValue) ||
-        identical(value3, stringValue);
-  }
-
-  /// Returns `true` if the stringValue of the [token] is either [value1],
-  /// [value2], [value3], or [value4].
-  bool isOneOf4(
-      Token token, String value1, String value2, String value3, String value4) {
-    String stringValue = token.stringValue;
-    return identical(value1, stringValue) ||
-        identical(value2, stringValue) ||
-        identical(value3, stringValue) ||
-        identical(value4, stringValue);
-  }
-
   bool notEofOrValue(String value, Token token) {
     return !identical(token.kind, EOF_TOKEN) &&
         !identical(value, token.stringValue);
@@ -2361,7 +2435,6 @@
       return false;
     }
 
-    FormalParameterKind parameterKind;
     switch (continuation) {
       case TypeContinuation.Required:
         // If the token after the type is not an identifier,
@@ -2440,224 +2513,6 @@
         if (beforeName.next != name)
           throw new StateError("beforeName.next != name");
         return parseNamedFunctionRest(beforeName, begin, formals, true);
-
-      case TypeContinuation.NormalFormalParameter:
-      case TypeContinuation.NormalFormalParameterAfterVar:
-        parameterKind = FormalParameterKind.mandatory;
-        hasVar = continuation == TypeContinuation.NormalFormalParameterAfterVar;
-        continue handleParameters;
-
-      case TypeContinuation.OptionalPositionalFormalParameter:
-      case TypeContinuation.OptionalPositionalFormalParameterAfterVar:
-        parameterKind = FormalParameterKind.optionalPositional;
-        hasVar = continuation ==
-            TypeContinuation.OptionalPositionalFormalParameterAfterVar;
-        continue handleParameters;
-
-      case TypeContinuation.NamedFormalParameterAfterVar:
-        hasVar = true;
-        continue handleParameters;
-
-      handleParameters:
-      case TypeContinuation.NamedFormalParameter:
-        parameterKind ??= FormalParameterKind.optionalNamed;
-        bool inFunctionType = memberKind == MemberKind.GeneralizedFunctionType;
-        bool isNamedParameter =
-            parameterKind == FormalParameterKind.optionalNamed;
-
-        bool untyped = false;
-        if (!looksLikeType || optional("this", begin)) {
-          untyped = true;
-          beforeToken = beforeBegin;
-          token = begin;
-        }
-
-        Token thisKeyword;
-        Token periodAfterThis;
-        Token beforeNameToken = beforeToken;
-        Token nameToken = token;
-        IdentifierContext nameContext =
-            IdentifierContext.formalParameterDeclaration;
-        beforeToken = token;
-        token = token.next;
-        if (inFunctionType) {
-          if (isNamedParameter) {
-            nameContext = IdentifierContext.formalParameterDeclaration;
-            if (!nameToken.isKeywordOrIdentifier) {
-              beforeToken = beforeNameToken;
-              token = nameToken;
-            }
-          } else if (nameToken.isKeywordOrIdentifier) {
-            if (untyped) {
-              // Type is required in a function type but name is not.
-              untyped = false;
-              nameContext = null;
-              beforeNameToken = nameToken;
-              nameToken = nameToken.next;
-            } else {
-              nameContext = IdentifierContext.formalParameterDeclaration;
-            }
-          } else {
-            // No name required in a function type.
-            nameContext = null;
-            beforeToken = beforeNameToken;
-            token = nameToken;
-          }
-        } else if (optional('this', nameToken)) {
-          thisKeyword = nameToken;
-          if (!optional('.', token)) {
-            // Recover from a missing period by inserting one.
-            Message message = fasta.templateExpectedButGot.withArguments('.');
-            Token newToken =
-                new SyntheticToken(TokenType.PERIOD, token.charOffset);
-            periodAfterThis =
-                rewriteAndRecover(thisKeyword, message, newToken).next;
-          } else {
-            periodAfterThis = token;
-          }
-          beforeToken = periodAfterThis;
-          token = periodAfterThis.next;
-          nameContext = IdentifierContext.fieldInitializer;
-          if (!token.isIdentifier) {
-            // Recover from a missing identifier by inserting one.
-            token = insertSyntheticIdentifier(beforeToken, nameContext);
-          }
-          beforeNameToken = beforeToken;
-          beforeToken = nameToken = token;
-          token = token.next;
-        } else if (!nameToken.isIdentifier) {
-          if (optional('.', nameToken)) {
-            // Recovery:
-            // Looks like a prefixed type, but missing the type and param names.
-            // Set the nameToken so that a synthetic identifier is inserted
-            // after the `.` token.
-            beforeToken = beforeNameToken = nameToken;
-            token = nameToken = nameToken.next;
-          } else if (context == IdentifierContext.prefixedTypeReference) {
-            // Recovery:
-            // Looks like a prefixed type, but missing the parameter name.
-            beforeToken = nameToken =
-                insertSyntheticIdentifier(beforeNameToken, nameContext);
-            token = beforeToken.next;
-          } else {
-            untyped = true;
-            beforeNameToken = beforeBegin;
-            beforeToken = nameToken = begin;
-            token = nameToken.next;
-          }
-        }
-        if (isNamedParameter && nameToken.lexeme.startsWith("_")) {
-          // TODO(ahe): Move this to after committing the type.
-          reportRecoverableError(nameToken, fasta.messagePrivateNamedParameter);
-        }
-
-        Token inlineFunctionTypeStart;
-        if (optional("<", token)) {
-          Token closer = token.endGroup;
-          if (closer != null) {
-            if (optional("(", closer.next)) {
-              if (varFinalOrConst != null) {
-                reportRecoverableError(
-                    varFinalOrConst, fasta.messageFunctionTypedParameterVar);
-              }
-              inlineFunctionTypeStart = beforeToken;
-              beforeToken = token;
-              token = token.next;
-            }
-          }
-        } else if (optional("(", token)) {
-          if (varFinalOrConst != null) {
-            reportRecoverableError(
-                varFinalOrConst, fasta.messageFunctionTypedParameterVar);
-          }
-          inlineFunctionTypeStart = beforeToken;
-          beforeToken = token.endGroup;
-          token = beforeToken.next;
-        }
-
-        if (inlineFunctionTypeStart != null) {
-          token = parseTypeVariablesOpt(inlineFunctionTypeStart);
-          // TODO(brianwilkerson): Figure out how to remove the invocation of
-          // `previous`. The method `parseTypeVariablesOpt` returns the last
-          // consumed token.
-          beforeToken = token.previous;
-          listener
-              .beginFunctionTypedFormalParameter(inlineFunctionTypeStart.next);
-          if (!untyped) {
-            if (voidToken != null) {
-              listener.handleVoidKeyword(voidToken);
-            } else {
-              Token saved = token;
-              commitType();
-              token = saved;
-              // We need to recompute the before tokens because [commitType] can
-              // cause synthetic tokens to be inserted.
-              beforeToken = previousToken(beforeToken, token);
-              beforeNameToken = previousToken(beforeNameToken, nameToken);
-            }
-          } else {
-            listener.handleNoType(beforeToken);
-          }
-          beforeToken = parseFormalParametersRequiredOpt(
-              token, MemberKind.FunctionTypedParameter);
-          token = beforeToken.next;
-          listener.endFunctionTypedFormalParameter();
-
-          // Generalized function types don't allow inline function types.
-          // The following isn't allowed:
-          //    int Function(int bar(String x)).
-          if (memberKind == MemberKind.GeneralizedFunctionType) {
-            reportRecoverableError(inlineFunctionTypeStart.next,
-                fasta.messageInvalidInlineFunctionType);
-          }
-        } else if (untyped) {
-          listener.handleNoType(token);
-        } else {
-          Token saved = token;
-          commitType();
-          token = saved;
-          // We need to recompute the before tokens because [commitType] can
-          // cause synthetic tokens to be inserted.
-          beforeToken = previousToken(beforeToken, token);
-          beforeNameToken = previousToken(beforeNameToken, nameToken);
-        }
-
-        if (nameContext != null) {
-          nameToken = ensureIdentifier(beforeNameToken, nameContext);
-          // We need to recompute the before tokens because [ensureIdentifier]
-          // can cause synthetic tokens to be inserted.
-          beforeToken = previousToken(beforeToken, token);
-        } else {
-          listener.handleNoName(nameToken);
-        }
-
-        String value = token.stringValue;
-        if ((identical('=', value)) || (identical(':', value))) {
-          Token equal = token;
-          listener.beginFormalParameterDefaultValueExpression();
-          beforeToken = parseExpression(token);
-          listener.endFormalParameterDefaultValueExpression();
-          token = beforeToken.next;
-          listener.handleValuedFormalParameter(equal, token);
-          if (isMandatoryFormalParameterKind(parameterKind)) {
-            reportRecoverableError(
-                equal, fasta.messageRequiredParameterWithDefault);
-          } else if (isOptionalPositionalFormalParameterKind(parameterKind) &&
-              identical(':', value)) {
-            reportRecoverableError(
-                equal, fasta.messagePositionalParameterWithEquals);
-          } else if (inFunctionType ||
-              memberKind == MemberKind.FunctionTypeAlias ||
-              memberKind == MemberKind.FunctionTypedParameter) {
-            reportRecoverableError(
-                equal, fasta.messageFunctionTypeDefaultValue);
-          }
-        } else {
-          listener.handleFormalParameterWithoutValue(token);
-        }
-        listener.endFormalParameter(
-            thisKeyword, periodAfterThis, nameToken, parameterKind, memberKind);
-        return beforeToken;
     }
 
     throw "Internal error: Unhandled continuation '$continuation'.";
@@ -2884,7 +2739,7 @@
         covariantToken = null;
       }
     }
-    if (typeInfo == noTypeInfo) {
+    if (typeInfo == noType) {
       if (varFinalOrConst == null) {
         reportRecoverableError(
             beforeName.next, fasta.messageMissingConstFinalVarOrType);
@@ -3252,12 +3107,12 @@
     assert(value != '>');
     Token replacement = new Token(TokenType.GT, next.charOffset);
     if (identical(value, '>>')) {
-      replacement.next = new Token(TokenType.GT, next.charOffset + 1);
+      replacement.setNext(new Token(TokenType.GT, next.charOffset + 1));
     } else if (identical(value, '>=')) {
-      replacement.next = new Token(TokenType.EQ, next.charOffset + 1);
+      replacement.setNext(new Token(TokenType.EQ, next.charOffset + 1));
     } else if (identical(value, '>>=')) {
-      replacement.next = new Token(TokenType.GT, next.charOffset + 1);
-      replacement.next.next = new Token(TokenType.EQ, next.charOffset + 2);
+      replacement.setNext(new Token(TokenType.GT, next.charOffset + 1));
+      replacement.next.setNext(new Token(TokenType.EQ, next.charOffset + 2));
     } else {
       // Recovery
       rewriteAndRecover(token, fasta.templateExpectedToken.withArguments('>'),
@@ -3298,30 +3153,6 @@
     return expect(';', token);
   }
 
-  /// Provides a partial order on modifiers.
-  ///
-  /// The order is based on the order modifiers must appear in according to the
-  /// grammar. For example, `external` must come before `static`.
-  ///
-  /// In addition, if two modifiers have the same order, they can't both be
-  /// used together, for example, `final` and `var` can't be used together.
-  ///
-  /// If [token] isn't a modifier, 127 is returned.
-  int modifierOrder(Token token) {
-    final String value = token.stringValue;
-    if (identical('external', value)) return 0;
-    if (identical('static', value) || identical('covariant', value)) {
-      return 1;
-    }
-    if (identical('final', value) ||
-        identical('var', value) ||
-        identical('const', value)) {
-      return 2;
-    }
-    if (identical('abstract', value)) return 3;
-    return 127;
-  }
-
   Token parseNativeClause(Token token) {
     Token nativeToken = token = token.next;
     assert(optional('native', nativeToken));
@@ -3370,14 +3201,6 @@
     return token;
   }
 
-  bool isGetOrSet(Token token) {
-    final String value = token.stringValue;
-    return (identical(value, 'get')) || (identical(value, 'set'));
-  }
-
-  bool isModifierOrFactory(Token next) =>
-      optional('factory', next) || isModifier(next);
-
   bool isUnaryMinus(Token token) =>
       token.kind == IDENTIFIER_TOKEN &&
       token.lexeme == 'unary' &&
@@ -3533,7 +3356,7 @@
             typeInfo,
             getOrSet);
       }
-    } else if (typeInfo == noTypeInfo && varFinalOrConst == null) {
+    } else if (typeInfo == noType && varFinalOrConst == null) {
       Token next2 = next.next;
       if (next2.isUserDefinableOperator && next2.endGroup == null) {
         String value = next2.next.stringValue;
@@ -5358,7 +5181,7 @@
     assert(optional('const', constToken));
     if (!isModifier(constToken.next)) {
       TypeInfo typeInfo = computeType(constToken, false);
-      if (typeInfo == noTypeInfo) {
+      if (typeInfo == noType) {
         Token next = constToken.next;
         if (!next.isIdentifier) {
           return parseExpressionStatement(start);
@@ -5489,11 +5312,11 @@
       // identifier, then allow ensureIdentifier to report an error
       // and don't report errors here.
       if (varFinalOrConst == null) {
-        if (typeInfo == noTypeInfo) {
+        if (typeInfo == noType) {
           reportRecoverableError(next, fasta.messageMissingConstFinalVarOrType);
         }
       } else if (optional('var', varFinalOrConst)) {
-        if (typeInfo != noTypeInfo) {
+        if (typeInfo != noType) {
           reportRecoverableError(varFinalOrConst, fasta.messageTypeAfterVar);
         }
       }
@@ -6600,7 +6423,7 @@
   /// Create a short token chain from the [beginToken] and [endToken] and return
   /// the [beginToken].
   Token link(BeginToken beginToken, Token endToken) {
-    beginToken.next = endToken;
+    beginToken.setNext(endToken);
     beginToken.endGroup = endToken;
     return beginToken;
   }
diff --git a/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart b/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
index aa850f9..eb7f4d5 100644
--- a/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
+++ b/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
@@ -34,30 +34,38 @@
   /// after the [previousToken]. Return the [previousToken].
   Token insertTokenAfter(Token previousToken, Token insertedToken) {
     Token afterToken = previousToken.next;
-    previousToken.next = insertedToken;
-    insertedToken.previous = previousToken;
+    previousToken.setNext(insertedToken);
 
     Token lastReplacement = _lastTokenInChain(insertedToken);
-    lastReplacement.next = afterToken;
-    afterToken.previous = lastReplacement;
+    lastReplacement.setNext(afterToken);
 
     return previousToken;
   }
 
+  /// Move [endGroup] (a synthetic `)`, `]`, `}`, or `>` token) after [token]
+  /// in the token stream and return [endGroup].
+  Token moveSynthetic(Token token, Token endGroup) {
+    assert(endGroup.beforeSynthetic != null);
+
+    Token next = token.next;
+    endGroup.beforeSynthetic.setNext(endGroup.next);
+    token.setNext(endGroup);
+    endGroup.setNext(next);
+    endGroup.offset = next.offset;
+    return endGroup;
+  }
+
   /// Replace the single token immediately following the [previousToken] with
   /// the chain of tokens starting at the [replacementToken]. Return the
   /// [replacementToken].
   Token replaceTokenFollowing(Token previousToken, Token replacementToken) {
     Token replacedToken = previousToken.next;
-    previousToken.next = replacementToken;
-    replacementToken.previous = previousToken;
+    previousToken.setNext(replacementToken);
 
     (replacementToken as SimpleToken).precedingComments =
         replacedToken.precedingComments;
 
-    Token lastReplacement = _lastTokenInChain(replacementToken);
-    lastReplacement.next = replacedToken.next;
-    replacedToken.next.previous = lastReplacement;
+    _lastTokenInChain(replacementToken).setNext(replacedToken.next);
 
     return replacementToken;
   }
diff --git a/pkg/front_end/lib/src/fasta/parser/type_continuation.dart b/pkg/front_end/lib/src/fasta/parser/type_continuation.dart
index a825ae5..a8aafd2 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_continuation.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_continuation.dart
@@ -4,8 +4,6 @@
 
 library fasta.parser.type_continuation;
 
-import 'formal_parameter_kind.dart' show FormalParameterKind;
-
 /// Indication of how the parser should continue after (attempting) to parse a
 /// type.
 ///
@@ -34,42 +32,4 @@
   /// Indicates that the parser is parsing an expression and has just seen an
   /// identifier.
   SendOrFunctionLiteral,
-
-  /// Indicates that an optional type followed by a normal formal parameter is
-  /// expected.
-  NormalFormalParameter,
-
-  /// Indicates that an optional type followed by an optional positional formal
-  /// parameter is expected.
-  OptionalPositionalFormalParameter,
-
-  /// Indicates that an optional type followed by a named formal parameter is
-  /// expected.
-  NamedFormalParameter,
-
-  /// Same as [NormalFormalParameter], but we have seen `var`.
-  NormalFormalParameterAfterVar,
-
-  /// Same as [OptionalPositionalFormalParameter], but we have seen `var`.
-  OptionalPositionalFormalParameterAfterVar,
-
-  /// Same as [NamedFormalParameter], but we have seen `var`.
-  NamedFormalParameterAfterVar,
-}
-
-TypeContinuation typeContinuationFromFormalParameterKind(
-    FormalParameterKind type) {
-  if (type != null) {
-    switch (type) {
-      case FormalParameterKind.mandatory:
-        return TypeContinuation.NormalFormalParameter;
-
-      case FormalParameterKind.optionalNamed:
-        return TypeContinuation.NamedFormalParameter;
-
-      case FormalParameterKind.optionalPositional:
-        return TypeContinuation.OptionalPositionalFormalParameter;
-    }
-  }
-  return null;
 }
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info.dart b/pkg/front_end/lib/src/fasta/parser/type_info.dart
index 01e6edb..29a6a7a 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info.dart
@@ -10,15 +10,7 @@
 
 import 'parser.dart' show Parser;
 
-import 'type_info_impl.dart'
-    show
-        ComplexTypeInfo,
-        NoTypeInfo,
-        PrefixedTypeInfo,
-        SimpleTypeArgumentsInfo,
-        SimpleTypeInfo,
-        VoidTypeInfo,
-        looksLikeName;
+import 'type_info_impl.dart';
 
 import 'util.dart' show optional;
 
@@ -63,26 +55,26 @@
   Token skipType(Token token);
 }
 
-/// [NoTypeInfo] is a specialized [TypeInfo] returned by [computeType] when
+/// [NoType] is a specialized [TypeInfo] returned by [computeType] when
 /// there is no type information in the source.
-const TypeInfo noTypeInfo = const NoTypeInfo();
+const TypeInfo noType = const NoType();
 
-/// [VoidTypeInfo] is a specialized [TypeInfo] returned by [computeType] when
+/// [VoidType] is a specialized [TypeInfo] returned by [computeType] when
 /// there is a single identifier as the type reference.
-const TypeInfo voidTypeInfo = const VoidTypeInfo();
+const TypeInfo voidType = const VoidType();
 
-/// [SimpleTypeInfo] is a specialized [TypeInfo] returned by [computeType]
+/// [SimpleType] is a specialized [TypeInfo] returned by [computeType]
 /// when there is a single identifier as the type reference.
-const TypeInfo simpleTypeInfo = const SimpleTypeInfo();
+const TypeInfo simpleType = const SimpleType();
 
-/// [PrefixedTypeInfo] is a specialized [TypeInfo] returned by [computeType]
+/// [PrefixedType] is a specialized [TypeInfo] returned by [computeType]
 /// when the type reference is of the form: identifier `.` identifier.
-const TypeInfo prefixedTypeInfo = const PrefixedTypeInfo();
+const TypeInfo prefixedType = const PrefixedType();
 
-/// [SimpleTypeArgumentsInfo] is a specialized [TypeInfo] returned by
+/// [SimpleTypeWith1Argument] is a specialized [TypeInfo] returned by
 /// [computeType] when the type reference is of the form:
 /// identifier `<` identifier `>`.
-const TypeInfo simpleTypeArgumentsInfo = const SimpleTypeArgumentsInfo();
+const TypeInfo simpleTypeWith1Argument = const SimpleTypeWith1Argument();
 
 Token insertSyntheticIdentifierAfter(Token token, Parser parser) {
   Token identifier = new SyntheticStringToken(
@@ -138,8 +130,11 @@
           }
         }
       }
+    } else if (required && optional('.', next)) {
+      // Recovery: looks like prefixed type missing the prefix
+      return new ComplexTypeInfo(token).computePrefixedType(required);
     }
-    return noTypeInfo;
+    return noType;
   }
 
   if (optional('void', next)) {
@@ -149,7 +144,7 @@
       return new ComplexTypeInfo(token).computeVoidGFT(required);
     }
     // `void`
-    return voidTypeInfo;
+    return voidType;
   }
 
   if (isGeneralizedFunctionType(next)) {
@@ -173,10 +168,10 @@
           if (!isGeneralizedFunctionType(next)) {
             if (required || looksLikeName(next)) {
               // identifier `<` identifier `>` identifier
-              return simpleTypeArgumentsInfo;
+              return simpleTypeWith1Argument;
             } else {
               // identifier `<` identifier `>` non-identifier
-              return noTypeInfo;
+              return noType;
             }
           }
         }
@@ -190,7 +185,7 @@
           .computeSimpleWithTypeArguments(required);
     }
     // identifier `<`
-    return required ? simpleTypeInfo : noTypeInfo;
+    return required ? simpleType : noType;
   }
 
   if (optional('.', next)) {
@@ -201,17 +196,19 @@
       if (!optional('<', next) && !isGeneralizedFunctionType(next)) {
         if (required || looksLikeName(next)) {
           // identifier `.` identifier identifier
-          return prefixedTypeInfo;
+          return prefixedType;
         } else {
           // identifier `.` identifier non-identifier
-          return noTypeInfo;
+          return noType;
         }
       }
       // identifier `.` identifier
       return new ComplexTypeInfo(token).computePrefixedType(required);
     }
     // identifier `.` non-identifier
-    return required ? simpleTypeInfo : noTypeInfo;
+    return required
+        ? new ComplexTypeInfo(token).computePrefixedType(required)
+        : noType;
   }
 
   if (isGeneralizedFunctionType(next)) {
@@ -221,7 +218,7 @@
 
   if (required || looksLikeName(next)) {
     // identifier identifier
-    return simpleTypeInfo;
+    return simpleType;
   }
-  return noTypeInfo;
+  return noType;
 }
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
index 08b2cce..f0e77fb 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
@@ -22,9 +22,9 @@
 
 import 'util.dart' show optional;
 
-/// See documentation on the [noTypeInfo] const.
-class NoTypeInfo implements TypeInfo {
-  const NoTypeInfo();
+/// See documentation on the [noType] const.
+class NoType implements TypeInfo {
+  const NoType();
 
   @override
   bool get couldBeExpression => false;
@@ -34,7 +34,7 @@
     parser.reportRecoverableErrorWithToken(
         token.next, fasta.templateExpectedType);
     insertSyntheticIdentifierAfter(token, parser);
-    return simpleTypeInfo.parseType(token, parser);
+    return simpleType.parseType(token, parser);
   }
 
   @override
@@ -57,9 +57,9 @@
   }
 }
 
-/// See documentation on the [prefixedTypeInfo] const.
-class PrefixedTypeInfo implements TypeInfo {
-  const PrefixedTypeInfo();
+/// See documentation on the [prefixedType] const.
+class PrefixedType implements TypeInfo {
+  const PrefixedType();
 
   @override
   bool get couldBeExpression => true;
@@ -103,9 +103,9 @@
   }
 }
 
-/// See documentation on the [simpleTypeArgumentsInfo] const.
-class SimpleTypeArgumentsInfo implements TypeInfo {
-  const SimpleTypeArgumentsInfo();
+/// See documentation on the [simpleTypeWith1Argument] const.
+class SimpleTypeWith1Argument implements TypeInfo {
+  const SimpleTypeWith1Argument();
 
   @override
   bool get couldBeExpression => false;
@@ -133,7 +133,7 @@
     assert(optional('<', token));
     listener.beginTypeArguments(token);
 
-    token = simpleTypeInfo.parseTypeNotVoid(token, parser);
+    token = simpleType.parseTypeNotVoid(token, parser);
 
     token = token.next;
     assert(optional('>', token));
@@ -150,9 +150,9 @@
   }
 }
 
-/// See documentation on the [simpleTypeInfo] const.
-class SimpleTypeInfo implements TypeInfo {
-  const SimpleTypeInfo();
+/// See documentation on the [simpleType] const.
+class SimpleType implements TypeInfo {
+  const SimpleType();
 
   @override
   bool get couldBeExpression => true;
@@ -186,9 +186,9 @@
   }
 }
 
-/// See documentation on the [voidTypeInfo] const.
-class VoidTypeInfo implements TypeInfo {
-  const VoidTypeInfo();
+/// See documentation on the [voidType] const.
+class VoidType implements TypeInfo {
+  const VoidType();
 
   @override
   bool get couldBeExpression => false;
@@ -197,7 +197,7 @@
   Token ensureTypeNotVoid(Token token, Parser parser) {
     // Report an error, then parse `void` as if it were a type name.
     parser.reportRecoverableError(token.next, fasta.messageInvalidVoid);
-    return simpleTypeInfo.parseTypeNotVoid(token, parser);
+    return simpleType.parseTypeNotVoid(token, parser);
   }
 
   @override
@@ -224,28 +224,33 @@
 bool looksLikeName(Token token) =>
     token.isIdentifier || optional('this', token);
 
-Token skipTypeArguments(Token token) {
+Token skipTypeVariables(Token token) {
   assert(optional('<', token));
   Token endGroup = token.endGroup;
+  if (endGroup == null) {
+    return null;
+  }
 
   // The scanner sets the endGroup in situations like this: C<T && T>U;
   // Scan the type arguments to assert there are no operators.
-  // TODO(danrubel) Fix the scanner and remove this code.
-  if (endGroup != null) {
-    token = token.next;
-    while (token != endGroup) {
-      if (token.isOperator) {
-        String value = token.stringValue;
-        if (!identical(value, '<') &&
-            !identical(value, '>') &&
-            !identical(value, '>>')) {
-          return null;
-        }
-      }
-      token = token.next;
+  // TODO(danrubel): Fix the scanner to do this scanning.
+  token = token.next;
+  while (token != endGroup) {
+    if (token.isKeywordOrIdentifier ||
+        optional(',', token) ||
+        optional('.', token) ||
+        optional('<', token) ||
+        optional('>', token) ||
+        optional('>>', token) ||
+        optional('@', token)) {
+      // ok
+    } else if (optional('(', token)) {
+      token = token.endGroup;
+    } else {
+      return null;
     }
+    token = token.next;
   }
-
   return endGroup;
 }
 
@@ -253,7 +258,7 @@
 /// type references that cannot be represented by the constants above.
 class ComplexTypeInfo implements TypeInfo {
   /// The first token in the type reference.
-  final Token start;
+  Token start;
 
   /// The last token in the type reference.
   Token end;
@@ -291,6 +296,12 @@
   Token parseType(Token token, Parser parser) {
     assert(identical(token.next, start));
 
+    if (optional('.', start)) {
+      // Recovery: Insert missing identifier without sending events
+      start = parser.insertSyntheticIdentifier(
+          token, IdentifierContext.prefixedTypeReference);
+    }
+
     for (Link<Token> t = typeVariableStarters; t.isNotEmpty; t = t.tail) {
       parser.parseTypeVariablesOpt(t.head);
       parser.listener.beginFunctionType(start);
@@ -300,13 +311,14 @@
       // A function type without return type.
       // Push the non-existing return type first. The loop below will
       // generate the full type.
-      noTypeInfo.parseTypeNotVoid(token, parser);
+      noType.parseTypeNotVoid(token, parser);
     } else {
-      Token start = token.next;
-      if (optional('void', start)) {
-        token = voidTypeInfo.parseType(token, parser);
+      Token typeRefOrPrefix = token.next;
+      if (optional('void', typeRefOrPrefix)) {
+        token = voidType.parseType(token, parser);
       } else {
-        if (!optional('.', start.next)) {
+        if (!optional('.', typeRefOrPrefix) &&
+            !optional('.', typeRefOrPrefix.next)) {
           token =
               parser.ensureIdentifier(token, IdentifierContext.typeReference);
         } else {
@@ -314,9 +326,12 @@
               token, IdentifierContext.prefixedTypeReference);
           token = parser.parseQualifiedRest(
               token, IdentifierContext.typeReferenceContinuation);
+          if (token.isSynthetic && end == typeRefOrPrefix.next) {
+            end = token;
+          }
         }
         token = parser.parseTypeArgumentsOpt(token);
-        parser.listener.handleType(start, token.next);
+        parser.listener.handleType(typeRefOrPrefix, token.next);
       }
     }
 
@@ -358,7 +373,7 @@
     computeRest(start, required);
 
     if (gftHasReturnType == null) {
-      return required ? simpleTypeInfo : noTypeInfo;
+      return required ? simpleType : noType;
     }
     assert(end != null);
     return this;
@@ -372,7 +387,7 @@
     computeRest(start.next, required);
 
     if (gftHasReturnType == null) {
-      return voidTypeInfo;
+      return voidType;
     }
     assert(end != null);
     return this;
@@ -386,7 +401,7 @@
     Token token = start.next;
     if (optional('<', token)) {
       typeArguments = token;
-      token = skipTypeArguments(typeArguments);
+      token = skipTypeVariables(typeArguments);
       if (token == null) {
         token = typeArguments;
         typeArguments = null;
@@ -408,7 +423,7 @@
     computeRest(start.next, required);
 
     if (gftHasReturnType == null) {
-      return simpleTypeInfo;
+      return simpleType;
     }
     assert(end != null);
     return this;
@@ -421,15 +436,15 @@
     typeArguments = start.next;
     assert(optional('<', typeArguments));
 
-    Token token = skipTypeArguments(typeArguments);
+    Token token = skipTypeVariables(typeArguments);
     if (token == null) {
-      return required ? simpleTypeInfo : noTypeInfo;
+      return required ? simpleType : noType;
     }
     end = token;
     computeRest(token.next, required);
 
     if (!required && !looksLikeName(end.next) && gftHasReturnType == null) {
-      return noTypeInfo;
+      return noType;
     }
     assert(end != null);
     return this;
@@ -438,19 +453,23 @@
   /// Given identifier `.` identifier, compute the type
   /// and return the receiver or one of the [TypeInfo] constants.
   TypeInfo computePrefixedType(bool required) {
-    assert(isValidTypeReference(start));
-    Token token = start.next;
+    Token token = start;
+    if (!optional('.', token)) {
+      assert(isValidTypeReference(token));
+      token = token.next;
+    }
     assert(optional('.', token));
-    token = token.next;
-    assert(isValidTypeReference(token));
+    if (isValidTypeReference(token.next)) {
+      token = token.next;
+    }
 
     end = token;
     token = token.next;
     if (optional('<', token)) {
       typeArguments = token;
-      token = skipTypeArguments(token);
+      token = skipTypeVariables(token);
       if (token == null) {
-        return required ? prefixedTypeInfo : noTypeInfo;
+        return required ? prefixedType : noType;
       }
       end = token;
       token = token.next;
@@ -458,7 +477,7 @@
     computeRest(token, required);
 
     if (!required && !looksLikeName(end.next) && gftHasReturnType == null) {
-      return noTypeInfo;
+      return noType;
     }
     assert(end != null);
     return this;
@@ -469,7 +488,7 @@
       Token typeVariableStart = token;
       token = token.next;
       if (optional('<', token)) {
-        token = token.endGroup;
+        token = skipTypeVariables(token);
         if (token == null) {
           break; // Not a function type.
         }
diff --git a/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart
index 8f7100b..5d8487a 100644
--- a/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart
@@ -361,7 +361,7 @@
     //      v
     //     EOF
     TokenType type = closeBraceInfoFor(begin);
-    appendToken(new SyntheticToken(type, tokenStart));
+    appendToken(new SyntheticToken(type, tokenStart)..beforeSynthetic = tail);
     begin.endGroup = tail;
     appendErrorToken(new UnmatchedToken(begin));
   }
diff --git a/pkg/front_end/lib/src/fasta/scanner/recover.dart b/pkg/front_end/lib/src/fasta/scanner/recover.dart
index 5341f1b..d969362 100644
--- a/pkg/front_end/lib/src/fasta/scanner/recover.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/recover.dart
@@ -124,7 +124,7 @@
     }
     String value = new String.fromCharCodes(codeUnits);
     return synthesizeToken(charOffset, value, TokenType.IDENTIFIER)
-      ..next = next;
+      ..setNext(next);
   }
 
   recoverExponent() {
@@ -137,7 +137,7 @@
 
   recoverHexDigit() {
     return synthesizeToken(errorTail.charOffset, "0", TokenType.INT)
-      ..next = errorTail.next;
+      ..setNext(errorTail.next);
   }
 
   recoverStringInterpolation() {
@@ -164,8 +164,7 @@
         if (errorTail == null) {
           error = next;
         } else {
-          errorTail.next = next;
-          next.previous = errorTail;
+          errorTail.setNext(next);
         }
         errorTail = next;
         next = next.next;
@@ -204,23 +203,21 @@
     if (goodTail == null) {
       good = current;
     } else {
-      goodTail.next = current;
-      current.previous = goodTail;
+      goodTail.setNext(current);
     }
     beforeGoodTail = goodTail;
     goodTail = current;
   }
 
-  error.previous = new Token.eof(-1)..next = error;
+  new Token.eof(-1).setNext(error);
   Token tail;
   if (good != null) {
-    errorTail.next = good;
-    good.previous = errorTail;
+    errorTail.setNext(good);
     tail = goodTail;
   } else {
     tail = errorTail;
   }
-  if (!tail.isEof) tail.next = new Token.eof(tail.end)..previous = tail;
+  if (!tail.isEof) tail.setNext(new Token.eof(tail.end));
   return error;
 }
 
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 79676d4..687a738 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -636,6 +636,17 @@
     ticker.logMs("Checked overrides");
   }
 
+  void checkAbstractMembers(List<SourceClassBuilder> sourceClasses) {
+    if (!target.strongMode) return;
+    assert(hierarchy != null);
+    for (SourceClassBuilder builder in sourceClasses) {
+      if (builder.library.loader == this) {
+        builder.checkAbstractMembers(coreTypes, hierarchy);
+      }
+    }
+    ticker.logMs("Checked abstract members");
+  }
+
   void addNoSuchMethodForwarders(List<SourceClassBuilder> sourceClasses) {
     if (!target.backendTarget.enableNoSuchMethodForwarders) return;
 
diff --git a/pkg/front_end/lib/src/incremental/unlinked_unit.dart b/pkg/front_end/lib/src/incremental/unlinked_unit.dart
index 0b5753a..8d38da3 100644
--- a/pkg/front_end/lib/src/incremental/unlinked_unit.dart
+++ b/pkg/front_end/lib/src/incremental/unlinked_unit.dart
@@ -61,12 +61,15 @@
 
 /// Exclude all `native 'xyz';` token sequences.
 void _excludeNativeClauses(Token token) {
-  for (; token.kind != EOF_TOKEN; token = token.next) {
-    if (optional('native', token) &&
-        token.next.kind == STRING_TOKEN &&
-        optional(';', token.next.next)) {
-      token.previous.next = token.next.next;
+  while (token.kind != EOF_TOKEN) {
+    Token next = token.next;
+    if (optional('native', next) &&
+        next.next.kind == STRING_TOKEN &&
+        optional(';', next.next.next)) {
+      next = next.next.next;
+      token.setNext(next);
     }
+    token = next;
   }
 }
 
diff --git a/pkg/front_end/lib/src/scanner/token.dart b/pkg/front_end/lib/src/scanner/token.dart
index 4e858ff..530b6f0 100644
--- a/pkg/front_end/lib/src/scanner/token.dart
+++ b/pkg/front_end/lib/src/scanner/token.dart
@@ -493,6 +493,14 @@
   int get charEnd => end;
 
   @override
+  Token get beforeSynthetic => null;
+
+  @override
+  set beforeSynthetic(Token previous) {
+    // ignored
+  }
+
+  @override
   int get end => offset + length;
 
   @override
@@ -581,6 +589,7 @@
   Token setNext(Token token) {
     next = token;
     token.previous = this;
+    token.beforeSynthetic = this;
     return token;
   }
 
@@ -712,6 +721,12 @@
   SyntheticToken(TokenType type, int offset) : super(type, offset);
 
   @override
+  Token beforeSynthetic;
+
+  @override
+  bool get isSynthetic => true;
+
+  @override
   int get length => 0;
 
   @override
@@ -757,6 +772,18 @@
    */
   int get charEnd;
 
+  /**
+   * The token before this synthetic token,
+   * or `null` if this is not a synthetic `)`, `]`, `}`, or `>` token.
+   */
+  Token get beforeSynthetic;
+
+  /**
+   * Set token before this synthetic `)`, `]`, `}`, or `>` token,
+   * and ignored otherwise.
+   */
+  set beforeSynthetic(Token previous);
+
   @override
   int get end;
 
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 25bcdaa..bf341d7 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -338,7 +338,7 @@
   analyzerCode: TYPEDEF_IN_CLASS
   dart2jsCode: "*fatal*"
   script:
-    - "class C { typedef int F(int x); }"
+    - "abstract class C { typedef int F(int x); }"
 
 CovariantMember:
   template: "Getters, setters and methods can't be declared to be 'covariant'."
@@ -1071,6 +1071,26 @@
   template: "Factory redirects to class '#name', which is abstract and can't be instantiated."
   severity: ERROR_LEGACY_WARNING
 
+MissingImplementationNotAbstract:
+  template: |
+    The non-abstract class '#name' is missing implementations for these members:
+      #string.
+  tip: |
+    Try to either
+     - provide an implementation,
+     - inherit an implementation from a superclass or mixin,
+     - mark the class as abstract, or
+     - provide a 'noSuchMethod' implementation.
+  severity: ERROR_LEGACY_WARNING
+  analyzerCode: CONCRETE_CLASS_WITH_ABSTRACT_MEMBER
+  dart2jsCode: "*fatal*"
+  script:
+    - "class C {foo();}"
+
+MissingImplementationCause:
+  template: "'#name' is defined here."
+  severity: CONTEXT
+
 ListLiteralTooManyTypeArguments:
   template: "Too many type arguments on List literal."
   severity: ERROR_LEGACY_WARNING
diff --git a/pkg/front_end/test/fasta/parser/token_stream_rewriter_test.dart b/pkg/front_end/test/fasta/parser/token_stream_rewriter_test.dart
index 6a5ddce..ed8df9c 100644
--- a/pkg/front_end/test/fasta/parser/token_stream_rewriter_test.dart
+++ b/pkg/front_end/test/fasta/parser/token_stream_rewriter_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:front_end/src/fasta/parser/token_stream_rewriter.dart';
+import 'package:front_end/src/fasta/scanner.dart'
+    show ScannerResult, scanString;
 import 'package:front_end/src/fasta/scanner/token.dart';
 import 'package:front_end/src/scanner/token.dart' show Token;
 import 'package:test/test.dart';
@@ -77,6 +79,23 @@
     expect(b.next, same(c));
   }
 
+  void test_moveSynthetic() {
+    ScannerResult scanResult = scanString('Foo(bar; baz=0;');
+    expect(scanResult.hasErrors, isTrue);
+    Token open = scanResult.tokens.next.next;
+    expect(open.lexeme, '(');
+    Token close = open.endGroup;
+    expect(close.isSynthetic, isTrue);
+    expect(close.next.isEof, isTrue);
+    var rewriter = new TokenStreamRewriter();
+
+    Token result = rewriter.moveSynthetic(open.next, close);
+    expect(result, close);
+    expect(open.endGroup, close);
+    expect(open.next.next, close);
+    expect(close.next.isEof, isFalse);
+  }
+
   void test_replaceTokenFollowing_multiple() {
     var a = _makeToken(0, 'a');
     var b = _makeToken(1, 'b');
diff --git a/pkg/front_end/test/fasta/parser/type_info_test.dart b/pkg/front_end/test/fasta/parser/type_info_test.dart
index b02c547..d09b895 100644
--- a/pkg/front_end/test/fasta/parser/type_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/type_info_test.dart
@@ -22,15 +22,15 @@
   void test_noType() {
     final Token start = scanString('before ;').tokens;
 
-    expect(noTypeInfo.couldBeExpression, isFalse);
-    expect(noTypeInfo.skipType(start), start);
+    expect(noType.couldBeExpression, isFalse);
+    expect(noType.skipType(start), start);
   }
 
   void test_noType_ensureTypeNotVoid() {
     final Token start = scanString('before ;').tokens;
     final TypeInfoListener listener = new TypeInfoListener();
 
-    expect(noTypeInfo.ensureTypeNotVoid(start, new Parser(listener)),
+    expect(noType.ensureTypeNotVoid(start, new Parser(listener)),
         new isInstanceOf<SyntheticStringToken>());
     expect(listener.calls, [
       'handleIdentifier  typeReference',
@@ -44,7 +44,7 @@
     final Token start = scanString('before ;').tokens;
     final TypeInfoListener listener = new TypeInfoListener();
 
-    expect(noTypeInfo.ensureTypeOrVoid(start, new Parser(listener)),
+    expect(noType.ensureTypeOrVoid(start, new Parser(listener)),
         new isInstanceOf<SyntheticStringToken>());
     expect(listener.calls, [
       'handleIdentifier  typeReference',
@@ -58,7 +58,7 @@
     final Token start = scanString('before ;').tokens;
     final TypeInfoListener listener = new TypeInfoListener();
 
-    expect(noTypeInfo.parseType(start, new Parser(listener)), start);
+    expect(noType.parseType(start, new Parser(listener)), start);
     expect(listener.calls, ['handleNoType before']);
     expect(listener.errors, isNull);
   }
@@ -67,7 +67,7 @@
     final Token start = scanString('before ;').tokens;
     final TypeInfoListener listener = new TypeInfoListener();
 
-    expect(noTypeInfo.parseTypeNotVoid(start, new Parser(listener)), start);
+    expect(noType.parseTypeNotVoid(start, new Parser(listener)), start);
     expect(listener.calls, ['handleNoType before']);
     expect(listener.errors, isNull);
   }
@@ -75,16 +75,15 @@
   void test_voidType() {
     final Token start = scanString('before void ;').tokens;
 
-    expect(voidTypeInfo.skipType(start), start.next);
-    expect(voidTypeInfo.couldBeExpression, isFalse);
+    expect(voidType.skipType(start), start.next);
+    expect(voidType.couldBeExpression, isFalse);
   }
 
   void test_voidType_ensureTypeNotVoid() {
     final Token start = scanString('before void ;').tokens;
     final TypeInfoListener listener = new TypeInfoListener();
 
-    expect(voidTypeInfo.ensureTypeNotVoid(start, new Parser(listener)),
-        start.next);
+    expect(voidType.ensureTypeNotVoid(start, new Parser(listener)), start.next);
     expect(listener.calls, [
       'handleIdentifier void typeReference',
       'handleNoTypeArguments ;',
@@ -97,7 +96,7 @@
     final Token start = scanString('before void ;').tokens;
     final TypeInfoListener listener = new TypeInfoListener();
 
-    expect(voidTypeInfo.parseType(start, new Parser(listener)), start.next);
+    expect(voidType.parseType(start, new Parser(listener)), start.next);
     expect(listener.calls, ['handleVoidKeyword void']);
     expect(listener.errors, isNull);
   }
@@ -106,7 +105,7 @@
     final Token start = scanString('before void ;').tokens;
     final TypeInfoListener listener = new TypeInfoListener();
 
-    expect(voidTypeInfo.parseType(start, new Parser(listener)), start.next);
+    expect(voidType.parseType(start, new Parser(listener)), start.next);
     expect(listener.calls, ['handleVoidKeyword void']);
     expect(listener.errors, isNull);
   }
@@ -115,8 +114,7 @@
     final Token start = scanString('before void ;').tokens;
     final TypeInfoListener listener = new TypeInfoListener();
 
-    expect(
-        voidTypeInfo.parseTypeNotVoid(start, new Parser(listener)), start.next);
+    expect(voidType.parseTypeNotVoid(start, new Parser(listener)), start.next);
     expect(listener.calls, [
       'handleIdentifier void typeReference',
       'handleNoTypeArguments ;',
@@ -129,8 +127,8 @@
     final Token start = scanString('before C.a ;').tokens;
     final Token expectedEnd = start.next.next.next;
 
-    expect(prefixedTypeInfo.skipType(start), expectedEnd);
-    expect(prefixedTypeInfo.couldBeExpression, isTrue);
+    expect(prefixedType.skipType(start), expectedEnd);
+    expect(prefixedType.couldBeExpression, isTrue);
 
     TypeInfoListener listener;
     assertResult(Token actualEnd) {
@@ -146,27 +144,24 @@
     }
 
     listener = new TypeInfoListener();
-    assertResult(
-        prefixedTypeInfo.ensureTypeNotVoid(start, new Parser(listener)));
+    assertResult(prefixedType.ensureTypeNotVoid(start, new Parser(listener)));
 
     listener = new TypeInfoListener();
-    assertResult(
-        prefixedTypeInfo.ensureTypeOrVoid(start, new Parser(listener)));
+    assertResult(prefixedType.ensureTypeOrVoid(start, new Parser(listener)));
 
     listener = new TypeInfoListener();
-    assertResult(
-        prefixedTypeInfo.parseTypeNotVoid(start, new Parser(listener)));
+    assertResult(prefixedType.parseTypeNotVoid(start, new Parser(listener)));
 
     listener = new TypeInfoListener();
-    assertResult(prefixedTypeInfo.parseType(start, new Parser(listener)));
+    assertResult(prefixedType.parseType(start, new Parser(listener)));
   }
 
   void test_simpleTypeInfo() {
     final Token start = scanString('before C ;').tokens;
     final Token expectedEnd = start.next;
 
-    expect(simpleTypeInfo.skipType(start), expectedEnd);
-    expect(simpleTypeInfo.couldBeExpression, isTrue);
+    expect(simpleType.skipType(start), expectedEnd);
+    expect(simpleType.couldBeExpression, isTrue);
 
     TypeInfoListener listener;
     assertResult(Token actualEnd) {
@@ -180,24 +175,24 @@
     }
 
     listener = new TypeInfoListener();
-    assertResult(simpleTypeInfo.ensureTypeNotVoid(start, new Parser(listener)));
+    assertResult(simpleType.ensureTypeNotVoid(start, new Parser(listener)));
 
     listener = new TypeInfoListener();
-    assertResult(simpleTypeInfo.ensureTypeOrVoid(start, new Parser(listener)));
+    assertResult(simpleType.ensureTypeOrVoid(start, new Parser(listener)));
 
     listener = new TypeInfoListener();
-    assertResult(simpleTypeInfo.parseTypeNotVoid(start, new Parser(listener)));
+    assertResult(simpleType.parseTypeNotVoid(start, new Parser(listener)));
 
     listener = new TypeInfoListener();
-    assertResult(simpleTypeInfo.parseType(start, new Parser(listener)));
+    assertResult(simpleType.parseType(start, new Parser(listener)));
   }
 
   void test_simpleTypeArgumentsInfo() {
     final Token start = scanString('before C<T> ;').tokens;
     final Token expectedEnd = start.next.next.next.next;
 
-    expect(simpleTypeArgumentsInfo.skipType(start), expectedEnd);
-    expect(simpleTypeArgumentsInfo.couldBeExpression, isFalse);
+    expect(simpleTypeWith1Argument.skipType(start), expectedEnd);
+    expect(simpleTypeWith1Argument.couldBeExpression, isFalse);
 
     TypeInfoListener listener;
     assertResult(Token actualEnd) {
@@ -216,32 +211,42 @@
 
     listener = new TypeInfoListener();
     assertResult(
-        simpleTypeArgumentsInfo.ensureTypeNotVoid(start, new Parser(listener)));
+        simpleTypeWith1Argument.ensureTypeNotVoid(start, new Parser(listener)));
 
     listener = new TypeInfoListener();
     assertResult(
-        simpleTypeArgumentsInfo.ensureTypeOrVoid(start, new Parser(listener)));
+        simpleTypeWith1Argument.ensureTypeOrVoid(start, new Parser(listener)));
 
     listener = new TypeInfoListener();
     assertResult(
-        simpleTypeArgumentsInfo.parseTypeNotVoid(start, new Parser(listener)));
+        simpleTypeWith1Argument.parseTypeNotVoid(start, new Parser(listener)));
 
     listener = new TypeInfoListener();
     assertResult(
-        simpleTypeArgumentsInfo.parseType(start, new Parser(listener)));
+        simpleTypeWith1Argument.parseType(start, new Parser(listener)));
   }
 
   void test_computeType_basic() {
-    expectInfo(noTypeInfo, '');
-    expectInfo(noTypeInfo, ';');
-    expectInfo(noTypeInfo, '( foo');
-    expectInfo(noTypeInfo, '< foo');
-    expectInfo(noTypeInfo, '= foo');
-    expectInfo(noTypeInfo, '* foo');
-    expectInfo(noTypeInfo, 'do foo');
-    expectInfo(noTypeInfo, 'get foo');
-    expectInfo(noTypeInfo, 'set foo');
-    expectInfo(noTypeInfo, 'operator *');
+    expectInfo(noType, '');
+    expectInfo(noType, ';');
+    expectInfo(noType, '( foo');
+    expectInfo(noType, '< foo');
+    expectInfo(noType, '= foo');
+    expectInfo(noType, '* foo');
+    expectInfo(noType, 'do foo');
+    expectInfo(noType, 'get foo');
+    expectInfo(noType, 'set foo');
+    expectInfo(noType, 'operator *');
+
+    expectInfo(noType, '.', required: false);
+    expectComplexInfo('.', required: true, expectedErrors: [
+      error(codeExpectedType, 0, 1),
+      error(codeExpectedType, 1, 0)
+    ]);
+
+    expectInfo(noType, '.Foo', required: false);
+    expectComplexInfo('.Foo',
+        required: true, expectedErrors: [error(codeExpectedType, 0, 1)]);
   }
 
   void test_computeType_builtin() {
@@ -330,8 +335,8 @@
       'endFunctionType Function m',
     ]);
 
-    expectInfo(noTypeInfo, 'Function(int x)', required: false);
-    expectInfo(noTypeInfo, 'Function<T>(int x)', required: false);
+    expectInfo(noType, 'Function(int x)', required: false);
+    expectInfo(noType, 'Function<T>(int x)', required: false);
 
     expectComplexInfo('Function(int x)', required: true);
     expectComplexInfo('Function<T>(int x)', required: true);
@@ -346,39 +351,40 @@
   }
 
   void test_computeType_identifier() {
-    expectInfo(noTypeInfo, 'C', required: false);
-    expectInfo(noTypeInfo, 'C;', required: false);
-    expectInfo(noTypeInfo, 'C(', required: false);
-    expectInfo(noTypeInfo, 'C<', required: false);
-    expectInfo(noTypeInfo, 'C.', required: false);
-    expectInfo(noTypeInfo, 'C=', required: false);
-    expectInfo(noTypeInfo, 'C*', required: false);
-    expectInfo(noTypeInfo, 'C do', required: false);
+    expectInfo(noType, 'C', required: false);
+    expectInfo(noType, 'C;', required: false);
+    expectInfo(noType, 'C(', required: false);
+    expectInfo(noType, 'C<', required: false);
+    expectInfo(noType, 'C.', required: false);
+    expectInfo(noType, 'C=', required: false);
+    expectInfo(noType, 'C*', required: false);
+    expectInfo(noType, 'C do', required: false);
 
-    expectInfo(simpleTypeInfo, 'C', required: true);
-    expectInfo(simpleTypeInfo, 'C;', required: true);
-    expectInfo(simpleTypeInfo, 'C(', required: true);
-    expectInfo(simpleTypeInfo, 'C<', required: true);
-    expectInfo(simpleTypeInfo, 'C.', required: true);
-    expectInfo(simpleTypeInfo, 'C=', required: true);
-    expectInfo(simpleTypeInfo, 'C*', required: true);
-    expectInfo(simpleTypeInfo, 'C do', required: true);
+    expectInfo(simpleType, 'C', required: true);
+    expectInfo(simpleType, 'C;', required: true);
+    expectInfo(simpleType, 'C(', required: true);
+    expectInfo(simpleType, 'C<', required: true);
+    expectComplexInfo('C.',
+        required: true, expectedErrors: [error(codeExpectedType, 2, 0)]);
+    expectInfo(simpleType, 'C=', required: true);
+    expectInfo(simpleType, 'C*', required: true);
+    expectInfo(simpleType, 'C do', required: true);
 
-    expectInfo(simpleTypeInfo, 'C foo');
-    expectInfo(simpleTypeInfo, 'C get');
-    expectInfo(simpleTypeInfo, 'C set');
-    expectInfo(simpleTypeInfo, 'C operator');
-    expectInfo(simpleTypeInfo, 'C this');
-    expectInfo(simpleTypeInfo, 'C Function');
+    expectInfo(simpleType, 'C foo');
+    expectInfo(simpleType, 'C get');
+    expectInfo(simpleType, 'C set');
+    expectInfo(simpleType, 'C operator');
+    expectInfo(simpleType, 'C this');
+    expectInfo(simpleType, 'C Function');
   }
 
   void test_computeType_identifierComplex() {
-    expectInfo(simpleTypeInfo, 'C Function()', required: false);
-    expectInfo(simpleTypeInfo, 'C Function<T>()', required: false);
-    expectInfo(simpleTypeInfo, 'C Function(int)', required: false);
-    expectInfo(simpleTypeInfo, 'C Function<T>(int)', required: false);
-    expectInfo(simpleTypeInfo, 'C Function(int x)', required: false);
-    expectInfo(simpleTypeInfo, 'C Function<T>(int x)', required: false);
+    expectInfo(simpleType, 'C Function()', required: false);
+    expectInfo(simpleType, 'C Function<T>()', required: false);
+    expectInfo(simpleType, 'C Function(int)', required: false);
+    expectInfo(simpleType, 'C Function<T>(int)', required: false);
+    expectInfo(simpleType, 'C Function(int x)', required: false);
+    expectInfo(simpleType, 'C Function<T>(int x)', required: false);
 
     expectComplexInfo('C Function()', required: true);
     expectComplexInfo('C Function<T>()', required: true);
@@ -405,16 +411,16 @@
   }
 
   void test_computeType_identifierTypeArg() {
-    expectInfo(noTypeInfo, 'C<T>', required: false);
-    expectInfo(noTypeInfo, 'C<T>;', required: false);
-    expectInfo(noTypeInfo, 'C<T>(', required: false);
-    expectInfo(noTypeInfo, 'C<T> do', required: false);
-    expectInfo(noTypeInfo, 'C<void>', required: false);
+    expectInfo(noType, 'C<T>', required: false);
+    expectInfo(noType, 'C<T>;', required: false);
+    expectInfo(noType, 'C<T>(', required: false);
+    expectInfo(noType, 'C<T> do', required: false);
+    expectInfo(noType, 'C<void>', required: false);
 
-    expectInfo(simpleTypeArgumentsInfo, 'C<T>', required: true);
-    expectInfo(simpleTypeArgumentsInfo, 'C<T>;', required: true);
-    expectInfo(simpleTypeArgumentsInfo, 'C<T>(', required: true);
-    expectInfo(simpleTypeArgumentsInfo, 'C<T> do', required: true);
+    expectInfo(simpleTypeWith1Argument, 'C<T>', required: true);
+    expectInfo(simpleTypeWith1Argument, 'C<T>;', required: true);
+    expectInfo(simpleTypeWith1Argument, 'C<T>(', required: true);
+    expectInfo(simpleTypeWith1Argument, 'C<T> do', required: true);
     expectComplexInfo('C<void>', required: true, expectedCalls: [
       'handleIdentifier C typeReference',
       'beginTypeArguments <',
@@ -423,17 +429,17 @@
       'handleType C ',
     ]);
 
-    expectInfo(simpleTypeArgumentsInfo, 'C<T> foo');
-    expectInfo(simpleTypeArgumentsInfo, 'C<T> get');
-    expectInfo(simpleTypeArgumentsInfo, 'C<T> set');
-    expectInfo(simpleTypeArgumentsInfo, 'C<T> operator');
-    expectInfo(simpleTypeArgumentsInfo, 'C<T> Function');
+    expectInfo(simpleTypeWith1Argument, 'C<T> foo');
+    expectInfo(simpleTypeWith1Argument, 'C<T> get');
+    expectInfo(simpleTypeWith1Argument, 'C<T> set');
+    expectInfo(simpleTypeWith1Argument, 'C<T> operator');
+    expectInfo(simpleTypeWith1Argument, 'C<T> Function');
   }
 
   void test_computeType_identifierTypeArgComplex() {
-    expectInfo(noTypeInfo, 'C<S,T>', required: false);
-    expectInfo(noTypeInfo, 'C<S<T>>', required: false);
-    expectInfo(noTypeInfo, 'C.a<T>', required: false);
+    expectInfo(noType, 'C<S,T>', required: false);
+    expectInfo(noType, 'C<S<T>>', required: false);
+    expectInfo(noType, 'C.a<T>', required: false);
 
     expectComplexInfo('C<S,T>', required: true, expectedCalls: [
       'handleIdentifier C typeReference',
@@ -530,7 +536,7 @@
           error(codeExpectedToken, 6, 6)
         ]);
 
-    expectInfo(noTypeInfo, 'C<>', required: false);
+    expectInfo(noType, 'C<>', required: false);
     expectComplexInfo('C<>', required: true, expectedCalls: [
       'handleIdentifier C typeReference',
       'beginTypeArguments <',
@@ -555,32 +561,32 @@
     ]);
 
     // Statements that should not have a type
-    expectInfo(noTypeInfo, 'C<T ; T>U;', required: false);
-    expectInfo(noTypeInfo, 'C<T && T>U;', required: false);
+    expectInfo(noType, 'C<T ; T>U;', required: false);
+    expectInfo(noType, 'C<T && T>U;', required: false);
   }
 
   void test_computeType_prefixed() {
-    expectInfo(noTypeInfo, 'C.a', required: false);
-    expectInfo(noTypeInfo, 'C.a;', required: false);
-    expectInfo(noTypeInfo, 'C.a(', required: false);
-    expectInfo(noTypeInfo, 'C.a<', required: false);
-    expectInfo(noTypeInfo, 'C.a=', required: false);
-    expectInfo(noTypeInfo, 'C.a*', required: false);
-    expectInfo(noTypeInfo, 'C.a do', required: false);
+    expectInfo(noType, 'C.a', required: false);
+    expectInfo(noType, 'C.a;', required: false);
+    expectInfo(noType, 'C.a(', required: false);
+    expectInfo(noType, 'C.a<', required: false);
+    expectInfo(noType, 'C.a=', required: false);
+    expectInfo(noType, 'C.a*', required: false);
+    expectInfo(noType, 'C.a do', required: false);
 
-    expectInfo(prefixedTypeInfo, 'C.a', required: true);
-    expectInfo(prefixedTypeInfo, 'C.a;', required: true);
-    expectInfo(prefixedTypeInfo, 'C.a(', required: true);
-    expectInfo(prefixedTypeInfo, 'C.a<', required: true);
-    expectInfo(prefixedTypeInfo, 'C.a=', required: true);
-    expectInfo(prefixedTypeInfo, 'C.a*', required: true);
-    expectInfo(prefixedTypeInfo, 'C.a do', required: true);
+    expectInfo(prefixedType, 'C.a', required: true);
+    expectInfo(prefixedType, 'C.a;', required: true);
+    expectInfo(prefixedType, 'C.a(', required: true);
+    expectInfo(prefixedType, 'C.a<', required: true);
+    expectInfo(prefixedType, 'C.a=', required: true);
+    expectInfo(prefixedType, 'C.a*', required: true);
+    expectInfo(prefixedType, 'C.a do', required: true);
 
-    expectInfo(prefixedTypeInfo, 'C.a foo');
-    expectInfo(prefixedTypeInfo, 'C.a get');
-    expectInfo(prefixedTypeInfo, 'C.a set');
-    expectInfo(prefixedTypeInfo, 'C.a operator');
-    expectInfo(prefixedTypeInfo, 'C.a Function');
+    expectInfo(prefixedType, 'C.a foo');
+    expectInfo(prefixedType, 'C.a get');
+    expectInfo(prefixedType, 'C.a set');
+    expectInfo(prefixedType, 'C.a operator');
+    expectInfo(prefixedType, 'C.a Function');
   }
 
   void test_computeType_prefixedGFT() {
@@ -691,19 +697,19 @@
   }
 
   void test_computeType_void() {
-    expectInfo(voidTypeInfo, 'void');
-    expectInfo(voidTypeInfo, 'void;');
-    expectInfo(voidTypeInfo, 'void(');
-    expectInfo(voidTypeInfo, 'void<');
-    expectInfo(voidTypeInfo, 'void=');
-    expectInfo(voidTypeInfo, 'void*');
-    expectInfo(voidTypeInfo, 'void<T>');
-    expectInfo(voidTypeInfo, 'void do');
-    expectInfo(voidTypeInfo, 'void foo');
-    expectInfo(voidTypeInfo, 'void get');
-    expectInfo(voidTypeInfo, 'void set');
-    expectInfo(voidTypeInfo, 'void operator');
-    expectInfo(voidTypeInfo, 'void Function');
+    expectInfo(voidType, 'void');
+    expectInfo(voidType, 'void;');
+    expectInfo(voidType, 'void(');
+    expectInfo(voidType, 'void<');
+    expectInfo(voidType, 'void=');
+    expectInfo(voidType, 'void*');
+    expectInfo(voidType, 'void<T>');
+    expectInfo(voidType, 'void do');
+    expectInfo(voidType, 'void foo');
+    expectInfo(voidType, 'void get');
+    expectInfo(voidType, 'void set');
+    expectInfo(voidType, 'void operator');
+    expectInfo(voidType, 'void Function');
     expectComplexInfo('void Function(', // Scanner inserts synthetic ')'.
         required: true,
         expectedCalls: [
@@ -717,7 +723,7 @@
   }
 
   void test_computeType_voidComplex() {
-    expectInfo(voidTypeInfo, 'void Function()', required: false);
+    expectInfo(voidType, 'void Function()', required: false);
     expectComplexInfo('void Function()', required: true, expectedCalls: [
       'handleNoTypeVariables (',
       'beginFunctionType void',
@@ -727,11 +733,11 @@
       'endFunctionType Function ',
     ]);
 
-    expectInfo(voidTypeInfo, 'void Function<T>()', required: false);
-    expectInfo(voidTypeInfo, 'void Function(int)', required: false);
-    expectInfo(voidTypeInfo, 'void Function<T>(int)', required: false);
-    expectInfo(voidTypeInfo, 'void Function(int x)', required: false);
-    expectInfo(voidTypeInfo, 'void Function<T>(int x)', required: false);
+    expectInfo(voidType, 'void Function<T>()', required: false);
+    expectInfo(voidType, 'void Function(int)', required: false);
+    expectInfo(voidType, 'void Function<T>(int)', required: false);
+    expectInfo(voidType, 'void Function(int x)', required: false);
+    expectInfo(voidType, 'void Function<T>(int x)', required: false);
 
     expectComplexInfo('void Function<T>()', required: true);
     expectComplexInfo('void Function(int)', required: true);
diff --git a/pkg/front_end/test/fasta/super_mixins_test.dart b/pkg/front_end/test/fasta/super_mixins_test.dart
index d0ad9eb..17a4f92 100644
--- a/pkg/front_end/test/fasta/super_mixins_test.dart
+++ b/pkg/front_end/test/fasta/super_mixins_test.dart
@@ -60,6 +60,8 @@
     super.foo(value);
     super.quux();
   }
+
+  void foo(String value) {}
 }
 
 void main() {
diff --git a/pkg/front_end/test/scanner_fasta_test.dart b/pkg/front_end/test/scanner_fasta_test.dart
index 0000f0c..2d01af9 100644
--- a/pkg/front_end/test/scanner_fasta_test.dart
+++ b/pkg/front_end/test/scanner_fasta_test.dart
@@ -727,7 +727,18 @@
 
   @override
   Token scan(String source) {
-    return createScanner(source, includeComments: true).tokenize();
+    final Token first = createScanner(source, includeComments: true).tokenize();
+    Token token = first;
+    while (!token.isEof) {
+      Token next = token.next;
+      expect(token.next, next);
+      expect(next.previous, token);
+      if (next.isSynthetic && [')', ']', '}'].contains(next.lexeme)) {
+        expect(next.beforeSynthetic, token);
+      }
+      token = next;
+    }
+    return first;
   }
 
   void test_linestarts() {
diff --git a/pkg/front_end/test/scanner_replacement_test.dart b/pkg/front_end/test/scanner_replacement_test.dart
index 984c877..c13663a 100644
--- a/pkg/front_end/test/scanner_replacement_test.dart
+++ b/pkg/front_end/test/scanner_replacement_test.dart
@@ -229,9 +229,7 @@
       token = token.next;
     }
     if (!token.previous.isEof) {
-      var head = new analyzer.Token.eof(-1);
-      token.previous = head;
-      head.next = token;
+      new analyzer.Token.eof(-1).setNext(token);
     }
     return token;
   }
diff --git a/pkg/front_end/testcases/inference/future_then.dart b/pkg/front_end/testcases/inference/future_then.dart
index 6b9527f..75782a4 100644
--- a/pkg/front_end/testcases/inference/future_then.dart
+++ b/pkg/front_end/testcases/inference/future_then.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then.dart.direct.expect b/pkg/front_end/testcases/inference/future_then.dart.direct.expect
index 10b7eb2..d9c0e0e 100644
--- a/pkg/front_end/testcases/inference/future_then.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_then.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then.dart.direct.transformed.expect
index 2ea9110..80a20d3 100644
--- a/pkg/front_end/testcases/inference/future_then.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then.dart.outline.expect b/pkg/front_end/testcases/inference/future_then.dart.outline.expect
new file mode 100644
index 0000000..bf89d40
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then.dart.outline.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(self::MyFuture::T x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method test() → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then.dart.strong.expect b/pkg/front_end/testcases/inference/future_then.dart.strong.expect
index 1089564..b7c6c22 100644
--- a/pkg/front_end/testcases/inference/future_then.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then.dart.strong.transformed.expect
index 82803df..5caa1e0 100644
--- a/pkg/front_end/testcases/inference/future_then.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_2.dart b/pkg/front_end/testcases/inference/future_then_2.dart
index b8dc5ff..f5f9def 100644
--- a/pkg/front_end/testcases/inference/future_then_2.dart
+++ b/pkg/front_end/testcases/inference/future_then_2.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_2.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_2.dart.direct.expect
index acb9122..3290595 100644
--- a/pkg/front_end/testcases/inference/future_then_2.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_then_2.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_2.dart.direct.transformed.expect
index 920eb54..93b4078 100644
--- a/pkg/front_end/testcases/inference/future_then_2.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_2.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_2.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_2.dart.outline.expect
new file mode 100644
index 0000000..bf89d40
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_2.dart.outline.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(self::MyFuture::T x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method test() → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then_2.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_2.dart.strong.expect
index 6e10646..264f452 100644
--- a/pkg/front_end/testcases/inference/future_then_2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_2.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_2.dart.strong.transformed.expect
index abf3ad2..8989332 100644
--- a/pkg/front_end/testcases/inference/future_then_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_2.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_3.dart b/pkg/front_end/testcases/inference/future_then_3.dart
index ca18c4f..1b4bfac 100644
--- a/pkg/front_end/testcases/inference/future_then_3.dart
+++ b/pkg/front_end/testcases/inference/future_then_3.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_3.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_3.dart.direct.expect
index 62054d0..fc2ec41 100644
--- a/pkg/front_end/testcases/inference/future_then_3.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_then_3.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_3.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_3.dart.direct.transformed.expect
index 752fb03..a94ad9c 100644
--- a/pkg/front_end/testcases/inference/future_then_3.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_3.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_3.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_3.dart.outline.expect
new file mode 100644
index 0000000..bf89d40
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_3.dart.outline.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(self::MyFuture::T x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method test() → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then_3.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_3.dart.strong.expect
index 66f74c0..496a434 100644
--- a/pkg/front_end/testcases/inference/future_then_3.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_3.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_3.dart.strong.transformed.expect
index 2678694..78a4a61 100644
--- a/pkg/front_end/testcases/inference/future_then_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_3.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_4.dart b/pkg/front_end/testcases/inference/future_then_4.dart
index 25a1a92..afc672d 100644
--- a/pkg/front_end/testcases/inference/future_then_4.dart
+++ b/pkg/front_end/testcases/inference/future_then_4.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_4.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_4.dart.direct.expect
index 6a85bd4..627469a9 100644
--- a/pkg/front_end/testcases/inference/future_then_4.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_then_4.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_4.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_4.dart.direct.transformed.expect
index c1da628..ee00df9 100644
--- a/pkg/front_end/testcases/inference/future_then_4.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_4.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_4.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_4.dart.outline.expect
new file mode 100644
index 0000000..bf89d40
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_4.dart.outline.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(self::MyFuture::T x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method test() → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then_4.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_4.dart.strong.expect
index 077aa15..0e9ab26 100644
--- a/pkg/front_end/testcases/inference/future_then_4.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_4.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_4.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_4.dart.strong.transformed.expect
index 4b747e7..03446f5 100644
--- a/pkg/front_end/testcases/inference/future_then_4.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_4.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_5.dart b/pkg/front_end/testcases/inference/future_then_5.dart
index 84fbc39..2fa4ef8 100644
--- a/pkg/front_end/testcases/inference/future_then_5.dart
+++ b/pkg/front_end/testcases/inference/future_then_5.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_5.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_5.dart.direct.expect
index 49a21d8..cf8341b 100644
--- a/pkg/front_end/testcases/inference/future_then_5.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_then_5.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_5.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_5.dart.direct.transformed.expect
index e7a0114..2c79488 100644
--- a/pkg/front_end/testcases/inference/future_then_5.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_5.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_5.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_5.dart.outline.expect
new file mode 100644
index 0000000..bf89d40
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_5.dart.outline.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(self::MyFuture::T x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method test() → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then_5.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_5.dart.strong.expect
index 248c940..60a45b2 100644
--- a/pkg/front_end/testcases/inference/future_then_5.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_5.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_5.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_5.dart.strong.transformed.expect
index e8a77dc..495a584 100644
--- a/pkg/front_end/testcases/inference/future_then_5.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_5.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_6.dart b/pkg/front_end/testcases/inference/future_then_6.dart
index cd5877d..25cb27f 100644
--- a/pkg/front_end/testcases/inference/future_then_6.dart
+++ b/pkg/front_end/testcases/inference/future_then_6.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_6.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_6.dart.direct.expect
index 784211b..59eca7d 100644
--- a/pkg/front_end/testcases/inference/future_then_6.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_then_6.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_6.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_6.dart.direct.transformed.expect
index c04938b..470f6c1 100644
--- a/pkg/front_end/testcases/inference/future_then_6.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_6.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_6.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_6.dart.outline.expect
new file mode 100644
index 0000000..bf89d40
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_6.dart.outline.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(self::MyFuture::T x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method test() → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then_6.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_6.dart.strong.expect
index 6293827..03a4550 100644
--- a/pkg/front_end/testcases/inference/future_then_6.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_6.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_6.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_6.dart.strong.transformed.expect
index fba912b..01b2db8 100644
--- a/pkg/front_end/testcases/inference/future_then_6.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_6.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<dynamic> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart b/pkg/front_end/testcases/inference/future_then_conditional.dart
index 84451ed..32f7cf2 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.direct.expect
index 2492740..6352e0d 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.direct.transformed.expect
index 61e4088..8b8e2a7 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.outline.expect
new file mode 100644
index 0000000..bf89d40
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.outline.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(self::MyFuture::T x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method test() → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.expect
index b5a4ef4..08ec64a 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect
index d83bae2..ff77eeb 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart b/pkg/front_end/testcases/inference/future_then_conditional_2.dart
index 2dcdf3f..9fb812d 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.direct.expect
index c8a5b9b..4884c6c 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.direct.transformed.expect
index bc86cdc..77323ea 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.outline.expect
new file mode 100644
index 0000000..bf89d40
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.outline.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(self::MyFuture::T x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method test() → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.expect
index 213e538a..13b1486 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect
index 27c0cd2..f272bfc 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart b/pkg/front_end/testcases/inference/future_then_conditional_3.dart
index f06ef6b..6a68194 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.direct.expect
index 6d9b472..477583e 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.direct.transformed.expect
index 88cca73..4fc92fe 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.outline.expect
new file mode 100644
index 0000000..bf89d40
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.outline.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(self::MyFuture::T x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method test() → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.expect
index 95d159a..af297a2 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect
index 008dad4..f2c3a2a 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart b/pkg/front_end/testcases/inference/future_then_conditional_4.dart
index 8049974..f99855b 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.direct.expect
index 1603dff..73ac5c0 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.direct.transformed.expect
index c248a6d3..dc2f85e 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.outline.expect
new file mode 100644
index 0000000..bf89d40
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.outline.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(self::MyFuture::T x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method test() → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.expect
index d84c298..b3e8ccc 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect
index 5db216e..6c4ab09 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart b/pkg/front_end/testcases/inference/future_then_conditional_5.dart
index 4660443..7520121 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.direct.expect
index bd54b84..32dbcf8 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.direct.transformed.expect
index eb4fbef..d7bf2f2 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.outline.expect
new file mode 100644
index 0000000..bf89d40
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.outline.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(self::MyFuture::T x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method test() → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.expect
index d010e60..8425b11 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect
index 4ab3d5f..f1cb720 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart b/pkg/front_end/testcases/inference/future_then_conditional_6.dart
index e843c57..b5d6508 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.direct.expect
index 82773ea..2fb57b2 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.direct.transformed.expect
index ca97197..93c7048 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.outline.expect
new file mode 100644
index 0000000..bf89d40
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.outline.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(self::MyFuture::T x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method test() → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.expect
index eb9edd0..47e72b3 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect
index 14029ba..48d5198 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<core::bool> f;
diff --git a/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.outline.expect
new file mode 100644
index 0000000..8e85697
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.outline.expect
@@ -0,0 +1,7 @@
+library test;
+import self as self;
+
+static method test() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then_explicit_future.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_explicit_future.dart.outline.expect
new file mode 100644
index 0000000..50d546c
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_explicit_future.dart.outline.expect
@@ -0,0 +1,7 @@
+library test;
+import self as self;
+
+static method m1() → dynamic
+  ;
+static method m2() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart b/pkg/front_end/testcases/inference/future_then_ifNull.dart
index f79997e..96695d4 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.direct.expect
index 2104ba8..3f7d35c 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::int> f;
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.direct.transformed.expect
index 98e506f..f0608c1 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::int> f;
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.outline.expect
index abbb36f..bf89d40 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.outline.expect
@@ -8,9 +8,14 @@
     ;
   constructor value(self::MyFuture::T x) → void
     ;
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
     ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void
   ;
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.expect
index 636b65e..0b16167 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::int> f;
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
index c0b8a92..186d1fe 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   self::MyFuture<core::int> f;
diff --git a/pkg/front_end/testcases/inference/future_then_upwards.dart b/pkg/front_end/testcases/inference/future_then_upwards.dart
index 34290072..1a770e9 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards.dart
+++ b/pkg/front_end/testcases/inference/future_then_upwards.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_upwards.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_upwards.dart.direct.expect
index ef2dc93..ad86cf9 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method main() → void {
   dynamic f = self::foo().then((dynamic _) → dynamic => 2.3);
diff --git a/pkg/front_end/testcases/inference/future_then_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_upwards.dart.direct.transformed.expect
index ef2dc93..ad86cf9 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method main() → void {
   dynamic f = self::foo().then((dynamic _) → dynamic => 2.3);
diff --git a/pkg/front_end/testcases/inference/future_then_upwards.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_upwards.dart.outline.expect
new file mode 100644
index 0000000..dd8d84a
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_upwards.dart.outline.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(self::MyFuture::T x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method main() → void
+  ;
+static method foo() → self::MyFuture<dynamic>
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.expect
index 82a1eea..e70813f 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method main() → void {
   self::MyFuture<core::double> f = self::foo().{self::MyFuture::then}<core::double>((dynamic _) → core::double => 2.3);
diff --git a/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.transformed.expect
index d15cb1a..5f33f15 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method main() → void {
   self::MyFuture<core::double> f = self::foo().{self::MyFuture::then}<core::double>((dynamic _) → core::double => 2.3);
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_2.dart b/pkg/front_end/testcases/inference/future_then_upwards_2.dart
index 8db4acd..b9d340e 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_2.dart
+++ b/pkg/front_end/testcases/inference/future_then_upwards_2.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.direct.expect
index d4901ef..a47a67c 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method main() → void {
   dynamic f = self::foo().then((dynamic _) → dynamic => 2.3);
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.direct.transformed.expect
index d4901ef..a47a67c 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method main() → void {
   dynamic f = self::foo().then((dynamic _) → dynamic => 2.3);
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.outline.expect
new file mode 100644
index 0000000..dd8d84a
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.outline.expect
@@ -0,0 +1,23 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(self::MyFuture::T x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method main() → void
+  ;
+static method foo() → self::MyFuture<dynamic>
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.expect
index 93e4a01..7a3e3e5 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method main() → void {
   self::MyFuture<core::double> f = self::foo().{self::MyFuture::then}<core::double>((dynamic _) → core::double => 2.3);
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.transformed.expect
index 3ff32da..c45f7a3 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method main() → void {
   self::MyFuture<core::double> f = self::foo().{self::MyFuture::then}<core::double>((dynamic _) → core::double => 2.3);
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_3.dart b/pkg/front_end/testcases/inference/future_then_upwards_3.dart
index 809f9ce..f57ee71 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_3.dart
+++ b/pkg/front_end/testcases/inference/future_then_upwards_3.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.direct.expect
index 8be59eb..e107ab2 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   dynamic f = self::foo().then((dynamic _) → dynamic => 2.3);
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.direct.transformed.expect
index 8be59eb..e107ab2 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   dynamic f = self::foo().then((dynamic _) → dynamic => 2.3);
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.outline.expect
new file mode 100644
index 0000000..f9939e0
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.outline.expect
@@ -0,0 +1,25 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(self::MyFuture::T x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method test() → void
+  ;
+static method foo() → asy::Future<dynamic>
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.expect
index d31aa187..d0de61c 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<core::double> f = self::foo().{asy::Future::then}<core::double>((dynamic _) → core::double => 2.3);
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.transformed.expect
index 87ba016..7784c77 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(self::MyFuture::T x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method test() → void {
   asy::Future<core::double> f = self::foo().{asy::Future::then}<core::double>((dynamic _) → core::double => 2.3);
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.outline.expect
new file mode 100644
index 0000000..8e85697
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.outline.expect
@@ -0,0 +1,7 @@
+library test;
+import self as self;
+
+static method test() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional.dart b/pkg/front_end/testcases/inference/future_union_async_conditional.dart
index 345ed22..e1f0f8c 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional.dart
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.direct.expect b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.direct.expect
index ee695a6..2f01968 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(dynamic x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method g1(core::bool x) → asy::Future<core::int> async {
   return x ? 42 : asy::Future::value<dynamic>(42);
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.direct.transformed.expect
index 911e233..5fc5f19 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(dynamic x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method g1(core::bool x) → asy::Future<core::int> /* originally async */ {
   final asy::Completer<core::int> :completer = asy::Completer::sync<core::int>();
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.outline.expect b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.outline.expect
new file mode 100644
index 0000000..353c1be
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.outline.expect
@@ -0,0 +1,27 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(dynamic x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method g1(core::bool x) → asy::Future<core::int>
+  ;
+static method g2(core::bool x) → asy::Future<core::int>
+  ;
+static method g3(core::bool x) → asy::Future<core::int>
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.expect b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.expect
index 85ff010..722f2d6 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(dynamic x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method g1(core::bool x) → asy::Future<core::int> async {
   return (x ?{core::Object} 42 : asy::Future::value<core::int>(42)) as{TypeError} asy::FutureOr<core::int>;
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.transformed.expect
index 7c803fd..260e803 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(dynamic x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method g1(core::bool x) → asy::Future<core::int> /* originally async */ {
   final asy::Completer<core::int> :completer = asy::Completer::sync<core::int>();
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart
index 3523226..41e7cb0 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(x) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.direct.expect b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.direct.expect
index 82e5e2a..e4c0c12 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(dynamic x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method g1(core::bool x) → asy::Future<core::int> async {
   return x ? 42 : new self::MyFuture::value<dynamic>(42);
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.direct.transformed.expect
index 00559fd..3010ada 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(dynamic x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method g1(core::bool x) → asy::Future<core::int> /* originally async */ {
   final asy::Completer<core::int> :completer = asy::Completer::sync<core::int>();
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.outline.expect b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.outline.expect
new file mode 100644
index 0000000..353c1be
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.outline.expect
@@ -0,0 +1,27 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value(dynamic x) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static method g1(core::bool x) → asy::Future<core::int>
+  ;
+static method g2(core::bool x) → asy::Future<core::int>
+  ;
+static method g3(core::bool x) → asy::Future<core::int>
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.expect b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.expect
index b235cc7..c539bcd 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(dynamic x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method g1(core::bool x) → asy::Future<core::int> async {
   return (x ?{core::Object} 42 : new self::MyFuture::value<core::int>(42)) as{TypeError} asy::FutureOr<core::int>;
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.transformed.expect
index 10fb0f8..ee81fa3 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value(dynamic x) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static method g1(core::bool x) → asy::Future<core::int> /* originally async */ {
   final asy::Completer<core::int> :completer = asy::Completer::sync<core::int>();
diff --git a/pkg/front_end/testcases/inference/future_union_downwards.dart b/pkg/front_end/testcases/inference/future_union_downwards.dart
index 75043bd..5622782 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards.dart
+++ b/pkg/front_end/testcases/inference/future_union_downwards.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value([x]) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_union_downwards.dart.direct.expect b/pkg/front_end/testcases/inference/future_union_downwards.dart.direct.expect
index 23bf82d..2bdcc03 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value([dynamic x = null]) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static field self::MyFuture<dynamic> f;
 static field asy::Future<core::int> t1 = self::f.then((dynamic _) → dynamic => asy::Future::value<dynamic>("hi"));
diff --git a/pkg/front_end/testcases/inference/future_union_downwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards.dart.direct.transformed.expect
index 859cda9..5db5ef3 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value([dynamic x = null]) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static field self::MyFuture<dynamic> f;
 static field asy::Future<core::int> t1 = self::f.then((dynamic _) → dynamic => asy::Future::value<dynamic>("hi"));
diff --git a/pkg/front_end/testcases/inference/future_union_downwards.dart.outline.expect b/pkg/front_end/testcases/inference/future_union_downwards.dart.outline.expect
new file mode 100644
index 0000000..203722c
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_union_downwards.dart.outline.expect
@@ -0,0 +1,28 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value([dynamic x]) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static field self::MyFuture<dynamic> f;
+static field asy::Future<core::int> t1;
+static field asy::Future<core::List<core::int>> t2;
+static method g2() → asy::Future<core::List<core::int>>
+  ;
+static method g3() → asy::Future<core::List<core::int>>
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.expect b/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.expect
index 68b4bb8..c6c4632 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value([dynamic x = null]) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static field self::MyFuture<dynamic> f;
 static field asy::Future<core::int> t1 = self::f.{self::MyFuture::then}<core::int>((dynamic _) → asy::Future<core::int> => asy::Future::value<core::int>(let final dynamic #t1 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/future_union_downwards.dart:21:44: Error: A value of type 'dart.core::String' can't be assigned to a variable of type 'dart.async::FutureOr<dart.core::int>'.
diff --git a/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.transformed.expect
index 2081070..e8e745e 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value([dynamic x = null]) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static field self::MyFuture<dynamic> f;
 static field asy::Future<core::int> t1 = self::f.{self::MyFuture::then}<core::int>((dynamic _) → asy::Future<core::int> => asy::Future::value<core::int>(let final dynamic #t1 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/future_union_downwards.dart:21:44: Error: A value of type 'dart.core::String' can't be assigned to a variable of type 'dart.async::FutureOr<dart.core::int>'.
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_2.dart b/pkg/front_end/testcases/inference/future_union_downwards_2.dart
index 8f83ae1..7ff20a9 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_2.dart
+++ b/pkg/front_end/testcases/inference/future_union_downwards_2.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value([x]) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.direct.expect b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.direct.expect
index 55196f7..c76f12a 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value([dynamic x = null]) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static field self::MyFuture<dynamic> f;
 static field asy::Future<core::int> t1 = self::f.then((dynamic _) → dynamic => new self::MyFuture::value<dynamic>("hi"));
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.direct.transformed.expect
index 793eefb..87b4be0eb 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value([dynamic x = null]) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static field self::MyFuture<dynamic> f;
 static field asy::Future<core::int> t1 = self::f.then((dynamic _) → dynamic => new self::MyFuture::value<dynamic>("hi"));
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.outline.expect b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.outline.expect
new file mode 100644
index 0000000..203722c
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.outline.expect
@@ -0,0 +1,28 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value([dynamic x]) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static field self::MyFuture<dynamic> f;
+static field asy::Future<core::int> t1;
+static field asy::Future<core::List<core::int>> t2;
+static method g2() → asy::Future<core::List<core::int>>
+  ;
+static method g3() → asy::Future<core::List<core::int>>
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.expect b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.expect
index 7200164..5c9ecaf 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value([dynamic x = null]) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static field self::MyFuture<dynamic> f;
 static field asy::Future<core::int> t1 = self::f.{self::MyFuture::then}<core::int>((dynamic _) → self::MyFuture<core::int> => new self::MyFuture::value<core::int>("hi"));
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.transformed.expect
index d4ffd12..7eae3ec 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value([dynamic x = null]) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static field self::MyFuture<dynamic> f;
 static field asy::Future<core::int> t1 = self::f.{self::MyFuture::then}<core::int>((dynamic _) → self::MyFuture<core::int> => new self::MyFuture::value<core::int>("hi"));
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_3.dart b/pkg/front_end/testcases/inference/future_union_downwards_3.dart
index c00a4b5..3cd6687 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_3.dart
+++ b/pkg/front_end/testcases/inference/future_union_downwards_3.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value([x]) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.direct.expect b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.direct.expect
index b63f083..7e03996 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value([dynamic x = null]) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static field asy::Future<dynamic> f;
 static field asy::Future<core::int> t1 = self::f.then((dynamic _) → dynamic => asy::Future::value<dynamic>("hi"));
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.direct.transformed.expect
index 9d94cef..665f3ee 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value([dynamic x = null]) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static field asy::Future<dynamic> f;
 static field asy::Future<core::int> t1 = self::f.then((dynamic _) → dynamic => asy::Future::value<dynamic>("hi"));
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.outline.expect b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.outline.expect
new file mode 100644
index 0000000..64f58e3
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.outline.expect
@@ -0,0 +1,28 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value([dynamic x]) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static field asy::Future<dynamic> f;
+static field asy::Future<core::int> t1;
+static field asy::Future<core::List<core::int>> t2;
+static method g2() → asy::Future<core::List<core::int>>
+  ;
+static method g3() → asy::Future<core::List<core::int>>
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.expect b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.expect
index 4faa367..a78fef7 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value([dynamic x = null]) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static field asy::Future<dynamic> f;
 static field asy::Future<core::int> t1 = self::f.{asy::Future::then}<core::int>((dynamic _) → asy::Future<core::int> => asy::Future::value<core::int>(let final dynamic #t1 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/future_union_downwards_3.dart:21:44: Error: A value of type 'dart.core::String' can't be assigned to a variable of type 'dart.async::FutureOr<dart.core::int>'.
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.transformed.expect
index 8f591b2..ff49091 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value([dynamic x = null]) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static field asy::Future<dynamic> f;
 static field asy::Future<core::int> t1 = self::f.{asy::Future::then}<core::int>((dynamic _) → asy::Future<core::int> => asy::Future::value<core::int>(let final dynamic #t1 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/future_union_downwards_3.dart:21:44: Error: A value of type 'dart.core::String' can't be assigned to a variable of type 'dart.async::FutureOr<dart.core::int>'.
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_4.dart b/pkg/front_end/testcases/inference/future_union_downwards_4.dart
index 7fa2acf..0bf7b5c 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_4.dart
+++ b/pkg/front_end/testcases/inference/future_union_downwards_4.dart
@@ -10,7 +10,7 @@
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value([x]) {}
-  dynamic noSuchMethod(/*@topType=Invocation*/ invocation);
+  dynamic noSuchMethod(/*@topType=Invocation*/ invocation) => null;
   MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.direct.expect b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.direct.expect
index 6eff123..a80ae91 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.direct.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value([dynamic x = null]) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static field asy::Future<dynamic> f;
 static field asy::Future<core::int> t1 = self::f.then((dynamic _) → dynamic => new self::MyFuture::value<dynamic>("hi"));
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.direct.transformed.expect
index 306af4b..b952431 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.direct.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value([dynamic x = null]) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(dynamic invocation) → dynamic;
+  method noSuchMethod(dynamic invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static field asy::Future<dynamic> f;
 static field asy::Future<core::int> t1 = self::f.then((dynamic _) → dynamic => new self::MyFuture::value<dynamic>("hi"));
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.outline.expect b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.outline.expect
new file mode 100644
index 0000000..64f58e3
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.outline.expect
@@ -0,0 +1,28 @@
+library test;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class MyFuture<T extends core::Object> extends core::Object implements asy::Future<self::MyFuture::T> {
+  constructor •() → void
+    ;
+  constructor value([dynamic x]) → void
+    ;
+  method noSuchMethod(dynamic invocation) → dynamic
+    ;
+  method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError}) → self::MyFuture<self::MyFuture::then::S>
+    ;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {() → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
+}
+static field asy::Future<dynamic> f;
+static field asy::Future<core::int> t1;
+static field asy::Future<core::List<core::int>> t2;
+static method g2() → asy::Future<core::List<core::int>>
+  ;
+static method g3() → asy::Future<core::List<core::int>>
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.expect b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.expect
index 1b9b482..d62bc1b 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value([dynamic x = null]) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static field asy::Future<dynamic> f;
 static field asy::Future<core::int> t1 = self::f.{asy::Future::then}<core::int>((dynamic _) → self::MyFuture<core::int> => new self::MyFuture::value<core::int>("hi"));
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.transformed.expect
index 58bf77e..f3bd417 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.transformed.expect
@@ -8,9 +8,14 @@
     : super core::Object::•() {}
   constructor value([dynamic x = null]) → void
     : super core::Object::•() {}
-  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
   method then<S extends core::Object>((self::MyFuture::T) → asy::FutureOr<self::MyFuture::then::S> f, {core::Function onError = null}) → self::MyFuture<self::MyFuture::then::S>
     return null;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) → core::bool test = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ whenComplete(() → asy::FutureOr<dynamic> action) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl generic-covariant-interface () → asy::FutureOr<self::MyFuture::T> onTimeout = null}) → asy::Future<self::MyFuture::T>;
+  abstract no-such-method-forwarder method /* from org-dartlang-testcase-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::MyFuture::T>;
 }
 static field asy::Future<dynamic> f;
 static field asy::Future<core::int> t1 = self::f.{asy::Future::then}<core::int>((dynamic _) → self::MyFuture<core::int> => new self::MyFuture::value<core::int>("hi"));
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.outline.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.outline.expect
new file mode 100644
index 0000000..5c21b43
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.outline.expect
@@ -0,0 +1,12 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    ;
+}
+static method foo() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.outline.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.outline.expect
new file mode 100644
index 0000000..a323d38
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.outline.expect
@@ -0,0 +1,10 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+static method id<T extends core::Object>(self::id::T x) → self::id::T
+  ;
+static method test() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.outline.expect b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.outline.expect
new file mode 100644
index 0000000..fbafd9f
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.outline.expect
@@ -0,0 +1,18 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    ;
+}
+class B extends self::A {
+  synthetic constructor •() → void
+    ;
+}
+class C extends self::A {
+  synthetic constructor •() → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart
index 1cd1300..185cb96 100644
--- a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart
@@ -7,7 +7,7 @@
 
 abstract class A {
   int get x;
-  void set x(double value);
+  void set x(double value) {}
 }
 
 class B extends A {
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.direct.expect
index ade9351..84b8120b 100644
--- a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.direct.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
   abstract get x() → core::int;
-  abstract set x(core::double value) → void;
+  set x(core::double value) → void {}
 }
 class B extends self::A {
   final field dynamic x;
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.direct.transformed.expect
index ade9351..84b8120b 100644
--- a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.direct.transformed.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
   abstract get x() → core::int;
-  abstract set x(core::double value) → void;
+  set x(core::double value) → void {}
 }
 class B extends self::A {
   final field dynamic x;
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.outline.expect
index 4b932ab..e843722 100644
--- a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.outline.expect
@@ -6,7 +6,8 @@
   synthetic constructor •() → void
     ;
   abstract get x() → core::int;
-  abstract set x(core::double value) → void;
+  set x(core::double value) → void
+    ;
 }
 class B extends self::A {
   final field dynamic x;
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.expect
index e5bc744..f27336bc 100644
--- a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
   abstract get x() → core::int;
-  abstract set x(core::double value) → void;
+  set x(core::double value) → void {}
 }
 class B extends self::A {
   final field core::int x;
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.transformed.expect
index e5bc744..f27336bc 100644
--- a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
   abstract get x() → core::int;
-  abstract set x(core::double value) → void;
+  set x(core::double value) → void {}
 }
 class B extends self::A {
   final field core::int x;
diff --git a/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart
index cf037f2..39ed20b 100644
--- a/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart
+++ b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart
@@ -6,7 +6,7 @@
 library test;
 
 abstract class A {
-  void set x(double value);
+  void set x(double value) {}
 }
 
 class B extends A {
diff --git a/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.direct.expect b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.direct.expect
index eaabbd8..1e77979 100644
--- a/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.direct.expect
+++ b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.direct.expect
@@ -6,7 +6,7 @@
   synthetic constructor •() → void
     : super core::Object::•()
     ;
-  abstract set x(core::double value) → void;
+  set x(core::double value) → void {}
 }
 class B extends self::A {
   final field dynamic x;
diff --git a/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.direct.transformed.expect
index eaabbd8..1e77979 100644
--- a/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.direct.transformed.expect
@@ -6,7 +6,7 @@
   synthetic constructor •() → void
     : super core::Object::•()
     ;
-  abstract set x(core::double value) → void;
+  set x(core::double value) → void {}
 }
 class B extends self::A {
   final field dynamic x;
diff --git a/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.outline.expect b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.outline.expect
index b89d2f3..8c26438 100644
--- a/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.outline.expect
@@ -5,7 +5,8 @@
 abstract class A extends core::Object {
   synthetic constructor •() → void
     ;
-  abstract set x(core::double value) → void;
+  set x(core::double value) → void
+    ;
 }
 class B extends self::A {
   final field dynamic x;
diff --git a/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.strong.expect b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.strong.expect
index e666cdd..9054ebc 100644
--- a/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.strong.expect
@@ -6,7 +6,7 @@
   synthetic constructor •() → void
     : super core::Object::•()
     ;
-  abstract set x(core::double value) → void;
+  set x(core::double value) → void {}
 }
 class B extends self::A {
   final field core::double x;
diff --git a/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.strong.transformed.expect
index e666cdd..9054ebc 100644
--- a/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
   synthetic constructor •() → void
     : super core::Object::•()
     ;
-  abstract set x(core::double value) → void;
+  set x(core::double value) → void {}
 }
 class B extends self::A {
   final field core::double x;
diff --git a/pkg/front_end/testcases/native_as_name.dart b/pkg/front_end/testcases/native_as_name.dart
index 8bd1047..d4b6837 100644
--- a/pkg/front_end/testcases/native_as_name.dart
+++ b/pkg/front_end/testcases/native_as_name.dart
@@ -18,11 +18,11 @@
   String native() => "method";
 }
 
-class Y1 {
+abstract class Y1 {
   String get native;
 }
 
-class Y2 {
+class Y2 extends Y1 {
   @override
   String get native => "getter";
 }
diff --git a/pkg/front_end/testcases/native_as_name.dart.direct.expect b/pkg/front_end/testcases/native_as_name.dart.direct.expect
index 93e5e80..d982aee 100644
--- a/pkg/front_end/testcases/native_as_name.dart.direct.expect
+++ b/pkg/front_end/testcases/native_as_name.dart.direct.expect
@@ -15,15 +15,15 @@
   method native() → core::String
     return "method";
 }
-class Y1 extends core::Object {
+abstract class Y1 extends core::Object {
   synthetic constructor •() → void
     : super core::Object::•()
     ;
   abstract get native() → core::String;
 }
-class Y2 extends core::Object {
+class Y2 extends self::Y1 {
   synthetic constructor •() → void
-    : super core::Object::•()
+    : super self::Y1::•()
     ;
   @core::override
   get native() → core::String
diff --git a/pkg/front_end/testcases/native_as_name.dart.direct.transformed.expect b/pkg/front_end/testcases/native_as_name.dart.direct.transformed.expect
index 93e5e80..d982aee 100644
--- a/pkg/front_end/testcases/native_as_name.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/native_as_name.dart.direct.transformed.expect
@@ -15,15 +15,15 @@
   method native() → core::String
     return "method";
 }
-class Y1 extends core::Object {
+abstract class Y1 extends core::Object {
   synthetic constructor •() → void
     : super core::Object::•()
     ;
   abstract get native() → core::String;
 }
-class Y2 extends core::Object {
+class Y2 extends self::Y1 {
   synthetic constructor •() → void
-    : super core::Object::•()
+    : super self::Y1::•()
     ;
   @core::override
   get native() → core::String
diff --git a/pkg/front_end/testcases/native_as_name.dart.outline.expect b/pkg/front_end/testcases/native_as_name.dart.outline.expect
index 80a1780..0ee8d2d 100644
--- a/pkg/front_end/testcases/native_as_name.dart.outline.expect
+++ b/pkg/front_end/testcases/native_as_name.dart.outline.expect
@@ -13,12 +13,12 @@
   method native() → core::String
     ;
 }
-class Y1 extends core::Object {
+abstract class Y1 extends core::Object {
   synthetic constructor •() → void
     ;
   abstract get native() → core::String;
 }
-class Y2 extends core::Object {
+class Y2 extends self::Y1 {
   synthetic constructor •() → void
     ;
   get native() → core::String
diff --git a/pkg/front_end/testcases/native_as_name.dart.strong.expect b/pkg/front_end/testcases/native_as_name.dart.strong.expect
index 4b3cf16..e667fad 100644
--- a/pkg/front_end/testcases/native_as_name.dart.strong.expect
+++ b/pkg/front_end/testcases/native_as_name.dart.strong.expect
@@ -15,15 +15,15 @@
   method native() → core::String
     return "method";
 }
-class Y1 extends core::Object {
+abstract class Y1 extends core::Object {
   synthetic constructor •() → void
     : super core::Object::•()
     ;
   abstract get native() → core::String;
 }
-class Y2 extends core::Object {
+class Y2 extends self::Y1 {
   synthetic constructor •() → void
-    : super core::Object::•()
+    : super self::Y1::•()
     ;
   @core::override
   get native() → core::String
diff --git a/pkg/front_end/testcases/native_as_name.dart.strong.transformed.expect b/pkg/front_end/testcases/native_as_name.dart.strong.transformed.expect
index 39a0b89..a502052 100644
--- a/pkg/front_end/testcases/native_as_name.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/native_as_name.dart.strong.transformed.expect
@@ -15,15 +15,15 @@
   method native() → core::String
     return "method";
 }
-class Y1 extends core::Object {
+abstract class Y1 extends core::Object {
   synthetic constructor •() → void
     : super core::Object::•()
     ;
   abstract get native() → core::String;
 }
-class Y2 extends core::Object {
+class Y2 extends self::Y1 {
   synthetic constructor •() → void
-    : super core::Object::•()
+    : super self::Y1::•()
     ;
   @core::override
   get native() → core::String
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart
index f461405..8879c0e 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart
@@ -6,7 +6,7 @@
 // non-implemented abstract method has all the references to the type variables
 // in its signature replaced with the appropriate types.
 
-class I<T> {
+abstract class I<T> {
   T foo();
 }
 
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.expect
index ffa2406..bf9c46c 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class I<T extends core::Object> extends core::Object {
+abstract class I<T extends core::Object> extends core::Object {
   synthetic constructor •() → void
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.transformed.expect
index 41aef5e..32ef81f 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class I<T extends core::Object> extends core::Object {
+abstract class I<T extends core::Object> extends core::Object {
   synthetic constructor •() → void
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
index 6a7ca94..969a34b 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class I<T extends core::Object> extends core::Object {
+abstract class I<T extends core::Object> extends core::Object {
   synthetic constructor •() → void
     ;
   abstract method foo() → self::I::T;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect
index ffa2406..bf9c46c 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class I<T extends core::Object> extends core::Object {
+abstract class I<T extends core::Object> extends core::Object {
   synthetic constructor •() → void
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect
index 41aef5e..32ef81f 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class I<T extends core::Object> extends core::Object {
+abstract class I<T extends core::Object> extends core::Object {
   synthetic constructor •() → void
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index 80f615e..ae45e4b 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -74,33 +74,6 @@
 inference/field_refers_to_static_getter: Fail
 inference/field_refers_to_top_level_getter: Fail
 inference/future_or_subtyping: Fail
-inference/future_then: Fail
-inference/future_then_2: Fail
-inference/future_then_3: Fail
-inference/future_then_4: Fail
-inference/future_then_5: Fail
-inference/future_then_6: Fail
-inference/future_then_conditional: Fail
-inference/future_then_conditional_2: Fail
-inference/future_then_conditional_3: Fail
-inference/future_then_conditional_4: Fail
-inference/future_then_conditional_5: Fail
-inference/future_then_conditional_6: Fail
-inference/future_then_downwards_method_target: Fail
-inference/future_then_explicit_future: Fail
-inference/future_then_upwards: Fail
-inference/future_then_upwards_2: Fail
-inference/future_then_upwards_3: Fail
-inference/future_then_upwards_from_block: Fail
-inference/future_union_async_conditional: Fail
-inference/future_union_async_conditional_2: Fail
-inference/future_union_downwards: Fail
-inference/future_union_downwards_2: Fail
-inference/future_union_downwards_3: Fail
-inference/future_union_downwards_4: Fail
-inference/future_union_downwards_generic_method_with_future_return: Fail
-inference/future_union_downwards_generic_method_with_generic_return: Fail
-inference/future_union_upwards_generic_methods: Fail
 inference/generic_functions_return_typedef: Fail
 inference/generic_methods_basic_downward_inference: Fail
 inference/generic_methods_correctly_recognize_generic_upper_bound: Fail
diff --git a/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart b/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart
index eea4d0b..0030a53 100644
--- a/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart
+++ b/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart
@@ -13,7 +13,7 @@
 // This class inherits genericImpl annotations from its superclass, but doesn't
 // have any members marked genericInterface because the inferred types of x and
 // y do not depend on the type parameter T.
-class C<T> implements B<num> {
+abstract class C<T> implements B<num> {
   var /*@covariance=genericImpl*/ x;
   get y;
   set y(/*@covariance=genericImpl*/ value);
@@ -21,7 +21,7 @@
 
 // This class also has members marked genericInterface, since the inferred types
 // of x and y *do* depend on the type parameter T.
-class D<T> implements B<T> {
+abstract class D<T> implements B<T> {
   var /*@covariance=genericInterface, genericImpl*/ x;
   get y;
   set y(/*@covariance=genericInterface, genericImpl*/ value);
diff --git a/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.direct.expect
index a69ba21..2582858 100644
--- a/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.direct.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.direct.expect
@@ -9,7 +9,7 @@
     : super core::Object::•()
     ;
 }
-class C<T extends core::Object> extends core::Object implements self::B<core::num> {
+abstract class C<T extends core::Object> extends core::Object implements self::B<core::num> {
   field dynamic x = null;
   synthetic constructor •() → void
     : super core::Object::•()
@@ -17,7 +17,7 @@
   abstract get y() → dynamic;
   abstract set y(dynamic value) → dynamic;
 }
-class D<T extends core::Object> extends core::Object implements self::B<self::D::T> {
+abstract class D<T extends core::Object> extends core::Object implements self::B<self::D::T> {
   field dynamic x = null;
   synthetic constructor •() → void
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.direct.transformed.expect
index a69ba21..2582858 100644
--- a/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.direct.transformed.expect
@@ -9,7 +9,7 @@
     : super core::Object::•()
     ;
 }
-class C<T extends core::Object> extends core::Object implements self::B<core::num> {
+abstract class C<T extends core::Object> extends core::Object implements self::B<core::num> {
   field dynamic x = null;
   synthetic constructor •() → void
     : super core::Object::•()
@@ -17,7 +17,7 @@
   abstract get y() → dynamic;
   abstract set y(dynamic value) → dynamic;
 }
-class D<T extends core::Object> extends core::Object implements self::B<self::D::T> {
+abstract class D<T extends core::Object> extends core::Object implements self::B<self::D::T> {
   field dynamic x = null;
   synthetic constructor •() → void
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.outline.expect
index 0c10d85..6ae5d4d 100644
--- a/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.outline.expect
@@ -8,14 +8,14 @@
   synthetic constructor •() → void
     ;
 }
-class C<T extends core::Object> extends core::Object implements self::B<core::num> {
+abstract class C<T extends core::Object> extends core::Object implements self::B<core::num> {
   field dynamic x;
   synthetic constructor •() → void
     ;
   abstract get y() → dynamic;
   abstract set y(dynamic value) → dynamic;
 }
-class D<T extends core::Object> extends core::Object implements self::B<self::D::T> {
+abstract class D<T extends core::Object> extends core::Object implements self::B<self::D::T> {
   field dynamic x;
   synthetic constructor •() → void
     ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.strong.expect
index 7a67ecc..d32e1ab 100644
--- a/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.strong.expect
@@ -9,7 +9,7 @@
     : super core::Object::•()
     ;
 }
-class C<T extends core::Object> extends core::Object implements self::B<core::num> {
+abstract class C<T extends core::Object> extends core::Object implements self::B<core::num> {
   generic-covariant-impl field core::num x = null;
   synthetic constructor •() → void
     : super core::Object::•()
@@ -17,7 +17,7 @@
   abstract get y() → core::num;
   abstract set y(generic-covariant-impl core::num value) → void;
 }
-class D<T extends core::Object> extends core::Object implements self::B<self::D::T> {
+abstract class D<T extends core::Object> extends core::Object implements self::B<self::D::T> {
   generic-covariant-impl generic-covariant-interface field self::D::T x = null;
   synthetic constructor •() → void
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.strong.transformed.expect
index 7a67ecc..d32e1ab 100644
--- a/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.strong.transformed.expect
@@ -9,7 +9,7 @@
     : super core::Object::•()
     ;
 }
-class C<T extends core::Object> extends core::Object implements self::B<core::num> {
+abstract class C<T extends core::Object> extends core::Object implements self::B<core::num> {
   generic-covariant-impl field core::num x = null;
   synthetic constructor •() → void
     : super core::Object::•()
@@ -17,7 +17,7 @@
   abstract get y() → core::num;
   abstract set y(generic-covariant-impl core::num value) → void;
 }
-class D<T extends core::Object> extends core::Object implements self::B<self::D::T> {
+abstract class D<T extends core::Object> extends core::Object implements self::B<self::D::T> {
   generic-covariant-impl generic-covariant-interface field self::D::T x = null;
   synthetic constructor •() → void
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart
index b107e62..1da15ad 100644
--- a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart
+++ b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart
@@ -5,7 +5,7 @@
 /*@testedFeatures=error*/
 
 class C {
-  void set x(value);
+  void set x(value) {}
 }
 
 void test(C c) {
diff --git a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.direct.expect b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.direct.expect
index ceea877..8fbca83 100644
--- a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.direct.expect
+++ b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.direct.expect
@@ -6,7 +6,7 @@
   synthetic constructor •() → void
     : super core::Object::•()
     ;
-  abstract set x(dynamic value) → void;
+  set x(dynamic value) → void {}
 }
 static method test(self::C c) → void {
   c.x = 1;
diff --git a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.direct.transformed.expect b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.direct.transformed.expect
index ceea877..8fbca83 100644
--- a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.direct.transformed.expect
@@ -6,7 +6,7 @@
   synthetic constructor •() → void
     : super core::Object::•()
     ;
-  abstract set x(dynamic value) → void;
+  set x(dynamic value) → void {}
 }
 static method test(self::C c) → void {
   c.x = 1;
diff --git a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.outline.expect b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.outline.expect
index af37326..36f9321 100644
--- a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.outline.expect
+++ b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.outline.expect
@@ -5,7 +5,8 @@
 class C extends core::Object {
   synthetic constructor •() → void
     ;
-  abstract set x(dynamic value) → void;
+  set x(dynamic value) → void
+    ;
 }
 static method test(self::C c) → void
   ;
diff --git a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.strong.expect b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.strong.expect
index 639d3c2..052b332 100644
--- a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.strong.expect
+++ b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.strong.expect
@@ -6,7 +6,7 @@
   synthetic constructor •() → void
     : super core::Object::•()
     ;
-  abstract set x(dynamic value) → void;
+  set x(dynamic value) → void {}
 }
 static method test(self::C c) → void {
   c.{self::C::x} = 1;
diff --git a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.strong.transformed.expect b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.strong.transformed.expect
index c1dd51a..bb3271b 100644
--- a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
   synthetic constructor •() → void
     : super core::Object::•()
     ;
-  abstract set x(dynamic value) → void;
+  set x(dynamic value) → void {}
 }
 static method test(self::C c) → void {
   c.{self::C::x} = 1;
diff --git a/pkg/front_end/tool/_fasta/compile_platform.dart b/pkg/front_end/tool/_fasta/compile_platform.dart
index b2bf572..7dcf8b4 100644
--- a/pkg/front_end/tool/_fasta/compile_platform.dart
+++ b/pkg/front_end/tool/_fasta/compile_platform.dart
@@ -10,6 +10,9 @@
 
 import 'package:compiler/src/kernel/dart2js_target.dart' show Dart2jsTarget;
 
+import 'package:vm/bytecode/gen_bytecode.dart'
+    show generateBytecode, kEnableKernelBytecodeForPlatform;
+
 import 'package:vm/target/dart_runner.dart' show DartRunnerTarget;
 
 import 'package:vm/target/flutter_runner.dart' show FlutterRunnerTarget;
@@ -85,6 +88,11 @@
   }
   new File.fromUri(outlineOutput).writeAsBytesSync(result.summary);
   c.options.ticker.logMs("Wrote outline to ${outlineOutput.toFilePath()}");
+
+  if (kEnableKernelBytecodeForPlatform) {
+    generateBytecode(result.component, strongMode: c.options.strongMode);
+  }
+
   await writeComponentToFile(result.component, fullOutput,
       filter: (lib) => !lib.isExternal);
 
diff --git a/pkg/front_end/tool/perf.dart b/pkg/front_end/tool/perf.dart
index 02b9283..b25a5b6 100644
--- a/pkg/front_end/tool/perf.dart
+++ b/pkg/front_end/tool/perf.dart
@@ -20,12 +20,12 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/file_system/file_system.dart' show ResourceUriResolver;
 import 'package:analyzer/file_system/physical_file_system.dart'
     show PhysicalResourceProvider;
 import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk;
+import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index e50b62d..d4983da 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -3650,9 +3650,23 @@
   }
 }
 
-/// Expression of the form `MakeClosure(f, c, t)` where `f` is a name of a
-/// closed top-level function, `c` is a Vector representing closure context, and
-/// `t` is the type of the resulting closure.
+/// Expression of the form `MakeClosure<T>(f, c, t)` where `f` is a name of a
+/// closed top-level function, `c` is a Vector representing closure context, `t`
+/// is the type of the resulting closure and `T` is a vector of type arguments
+/// to be passed to `f`.
+///
+/// Note these restrictions on its usage:
+///
+///   1. `f` must reference a statically-resolved top-level function.
+///
+///   2. The length of `T` must be less than or equal to the number of type
+///      parameters on `f`.
+///
+///   3. It is disallowed to use `MakeClosure` on the same function twice with
+///      different numbers of type arguments.
+///
+///   4. The type arguments `T` must be guaranteed to satisfy the bounds of the
+///      corresponding type parameters on `f`.
 class ClosureCreation extends Expression {
   Reference topLevelFunctionReference;
   Expression contextVector;
@@ -5103,6 +5117,8 @@
   /// Returns a possibly synthesized name for this type parameter, consistent
   /// with the names used across all [toString] calls.
   String toString() => debugQualifiedTypeParameterName(this);
+
+  bool get isFunctionTypeTypeParameter => parent == null;
 }
 
 class Supertype extends Node {
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index ae840c7..6749c74 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -182,7 +182,7 @@
         final DartType valueType = readDartType();
         final int length = readUInt();
         final List<ConstantMapEntry> entries =
-            new List<ConstantMapEntry>(length);
+            new List<ConstantMapEntry>.filled(length, null, growable: true);
         for (int i = 0; i < length; i++) {
           final Constant key = readConstantReference();
           final Constant value = readConstantReference();
@@ -192,7 +192,8 @@
       case ConstantTag.ListConstant:
         final DartType typeArgument = readDartType();
         final int length = readUInt();
-        final List<Constant> entries = new List<Constant>(length);
+        final List<Constant> entries =
+            new List<Constant>.filled(length, null, growable: true);
         for (int i = 0; i < length; i++) {
           entries[i] = readConstantReference();
         }
@@ -201,7 +202,7 @@
         final Reference classReference = readClassReference();
         final int typeArgumentCount = readUInt();
         final List<DartType> typeArguments =
-            new List<DartType>(typeArgumentCount);
+            new List<DartType>.filled(typeArgumentCount, null, growable: true);
         for (int i = 0; i < typeArgumentCount; i++) {
           typeArguments[i] = readDartType();
         }
@@ -242,7 +243,7 @@
 
   List<String> readStringReferenceList() {
     int length = readUInt();
-    List<String> result = new List<String>(length);
+    List<String> result = new List<String>.filled(length, null, growable: true);
     for (int i = 0; i < length; ++i) {
       result[i] = readStringReference();
     }
@@ -268,7 +269,8 @@
   List<Expression> readAnnotationList(TreeNode parent) {
     int length = readUInt();
     if (length == 0) return const <Expression>[];
-    List<Expression> list = new List<Expression>(length);
+    List<Expression> list =
+        new List<Expression>.filled(length, null, growable: true);
     for (int i = 0; i < length; ++i) {
       list[i] = readExpression()..parent = parent;
     }
@@ -699,7 +701,8 @@
 
   List<Combinator> readCombinatorList() {
     int length = readUInt();
-    List<Combinator> result = new List<Combinator>(length);
+    List<Combinator> result =
+        new List<Combinator>.filled(length, null, growable: true);
     for (int i = 0; i < length; ++i) {
       result[i] = readCombinator();
     }
@@ -1164,7 +1167,8 @@
 
   List<Expression> readExpressionList() {
     int length = readUInt();
-    List<Expression> result = new List<Expression>(length);
+    List<Expression> result =
+        new List<Expression>.filled(length, null, growable: true);
     for (int i = 0; i < length; ++i) {
       result[i] = readExpression();
     }
@@ -1418,7 +1422,8 @@
 
   List<MapEntry> readMapEntryList() {
     int length = readUInt();
-    List<MapEntry> result = new List<MapEntry>(length);
+    List<MapEntry> result =
+        new List<MapEntry>.filled(length, null, growable: true);
     for (int i = 0; i < length; ++i) {
       result[i] = readMapEntry();
     }
@@ -1431,8 +1436,8 @@
 
   List<Statement> readStatementList() {
     int length = readUInt();
-    List<Statement> result = <Statement>[];
-    result.length = length;
+    List<Statement> result =
+        new List<Statement>.filled(length, null, growable: true);
     for (int i = 0; i < length; ++i) {
       result[i] = readStatement();
     }
@@ -1514,7 +1519,8 @@
         var offset = readOffset();
         var expression = readExpression();
         int count = readUInt();
-        List<SwitchCase> cases = new List<SwitchCase>(count);
+        List<SwitchCase> cases =
+            new List<SwitchCase>.filled(count, null, growable: true);
         for (int i = 0; i < count; ++i) {
           cases[i] = new SwitchCase.empty();
         }
@@ -1579,7 +1585,7 @@
 
   List<Catch> readCatchList() {
     int length = readUInt();
-    List<Catch> result = new List<Catch>(length);
+    List<Catch> result = new List<Catch>.filled(length, null, growable: true);
     for (int i = 0; i < length; ++i) {
       result[i] = readCatch();
     }
@@ -1623,7 +1629,8 @@
 
   List<Supertype> readSupertypeList() {
     int length = readUInt();
-    List<Supertype> result = new List<Supertype>(length);
+    List<Supertype> result =
+        new List<Supertype>.filled(length, null, growable: true);
     for (int i = 0; i < length; ++i) {
       result[i] = readSupertype();
     }
@@ -1632,7 +1639,8 @@
 
   List<DartType> readDartTypeList() {
     int length = readUInt();
-    List<DartType> result = new List<DartType>(length);
+    List<DartType> result =
+        new List<DartType>.filled(length, null, growable: true);
     for (int i = 0; i < length; ++i) {
       result[i] = readDartType();
     }
@@ -1641,7 +1649,8 @@
 
   List<NamedType> readNamedTypeList() {
     int length = readUInt();
-    List<NamedType> result = new List<NamedType>(length);
+    List<NamedType> result =
+        new List<NamedType>.filled(length, null, growable: true);
     for (int i = 0; i < length; ++i) {
       result[i] = readNamedType();
     }
@@ -1716,7 +1725,7 @@
     int length = readUInt();
     if (length == 0) return list ?? <TypeParameter>[];
     if (list == null) {
-      list = new List<TypeParameter>(length);
+      list = new List<TypeParameter>.filled(length, null, growable: true);
       for (int i = 0; i < length; ++i) {
         list[i] = new TypeParameter(null, null)..parent = parent;
       }
@@ -1752,7 +1761,8 @@
 
   List<NamedExpression> readNamedExpressionList() {
     int length = readUInt();
-    List<NamedExpression> result = new List<NamedExpression>(length);
+    List<NamedExpression> result =
+        new List<NamedExpression>.filled(length, null, growable: true);
     for (int i = 0; i < length; ++i) {
       result[i] = readNamedExpression();
     }
@@ -1765,7 +1775,8 @@
 
   List<VariableDeclaration> readAndPushVariableDeclarationList() {
     int length = readUInt();
-    List<VariableDeclaration> result = new List<VariableDeclaration>(length);
+    List<VariableDeclaration> result =
+        new List<VariableDeclaration>.filled(length, null, growable: true);
     for (int i = 0; i < length; ++i) {
       result[i] = readAndPushVariableDeclaration();
     }
@@ -1860,7 +1871,8 @@
             final nodeOffset = readUint32();
             offsetToReferenceId[nodeOffset] = j;
           }
-          referencedNodes = new List<Node>(referencesLength);
+          referencedNodes =
+              new List<Node>.filled(referencesLength, null, growable: true);
           containsNodeReferences = true;
         }
 
diff --git a/pkg/kernel/lib/transformations/closure/info.dart b/pkg/kernel/lib/transformations/closure/info.dart
index 6d0a288..ffa5fd7 100644
--- a/pkg/kernel/lib/transformations/closure/info.dart
+++ b/pkg/kernel/lib/transformations/closure/info.dart
@@ -233,7 +233,9 @@
   }
 
   visitTypeParameterType(TypeParameterType node) {
-    if (!isOuterMostContext && node.parameter.parent != currentFunction) {
+    if (!isOuterMostContext &&
+        node.parameter.parent != currentFunction &&
+        !node.parameter.isFunctionTypeTypeParameter) {
       typeVariables
           .putIfAbsent(currentFunction, () => new Set<TypeParameter>())
           .add(node.parameter);
diff --git a/pkg/vm/bin/dump_kernel.dart b/pkg/vm/bin/dump_kernel.dart
index 0f95c9ce..2add763 100644
--- a/pkg/vm/bin/dump_kernel.dart
+++ b/pkg/vm/bin/dump_kernel.dart
@@ -8,6 +8,7 @@
 import 'package:kernel/binary/ast_from_binary.dart'
     show BinaryBuilderWithMetadata;
 
+import 'package:vm/metadata/bytecode.dart' show BytecodeMetadataRepository;
 import 'package:vm/metadata/direct_call.dart' show DirectCallMetadataRepository;
 import 'package:vm/metadata/inferred_type.dart'
     show InferredTypeMetadataRepository;
@@ -37,6 +38,7 @@
   component.addMetadataRepository(new InferredTypeMetadataRepository());
   component.addMetadataRepository(new ProcedureAttributesMetadataRepository());
   component.addMetadataRepository(new UnreachableNodeMetadataRepository());
+  component.addMetadataRepository(new BytecodeMetadataRepository());
 
   final List<int> bytes = new File(input).readAsBytesSync();
   new BinaryBuilderWithMetadata(bytes).readComponent(component);
diff --git a/pkg/vm/bin/gen_kernel.dart b/pkg/vm/bin/gen_kernel.dart
index 5c17f8f..d845a2d 100644
--- a/pkg/vm/bin/gen_kernel.dart
+++ b/pkg/vm/bin/gen_kernel.dart
@@ -14,6 +14,7 @@
 import 'package:kernel/target/vm.dart' show VmTarget;
 import 'package:kernel/text/ast_to_text.dart'
     show globalDebuggingNames, NameSystem;
+import 'package:vm/bytecode/gen_bytecode.dart' show kEnableKernelBytecode;
 import 'package:vm/kernel_front_end.dart' show compileToKernel, ErrorDetector;
 
 final ArgParser _argParser = new ArgParser(allowTrailingOptions: true)
@@ -36,7 +37,9 @@
           'Enable global type flow analysis and related transformations in AOT mode.',
       defaultsTo: true)
   ..addMultiOption('entry-points',
-      help: 'Path to JSON file with the list of entry points');
+      help: 'Path to JSON file with the list of entry points')
+  ..addFlag('gen-bytecode',
+      help: 'Generate bytecode', defaultsTo: kEnableKernelBytecode);
 
 final String _usage = '''
 Usage: dart pkg/vm/bin/gen_kernel.dart --platform vm_platform_strong.dill [options] input.dart
@@ -73,6 +76,7 @@
   final bool aot = options['aot'];
   final bool syncAsync = options['sync-async'];
   final bool tfa = options['tfa'];
+  final bool genBytecode = options['gen-bytecode'];
 
   final List<String> entryPoints = options['entry-points'] ?? <String>[];
   if (entryPoints.isEmpty) {
@@ -100,7 +104,10 @@
 
   Component component = await compileToKernel(
       Uri.base.resolveUri(new Uri.file(filename)), compilerOptions,
-      aot: aot, useGlobalTypeFlowAnalysis: tfa, entryPoints: entryPoints);
+      aot: aot,
+      useGlobalTypeFlowAnalysis: tfa,
+      entryPoints: entryPoints,
+      genBytecode: genBytecode);
 
   if (errorDetector.hasCompilationErrors || (component == null)) {
     return _compileTimeErrorExitCode;
diff --git a/pkg/vm/lib/bytecode/assembler.dart b/pkg/vm/lib/bytecode/assembler.dart
new file mode 100644
index 0000000..ac3b157
--- /dev/null
+++ b/pkg/vm/lib/bytecode/assembler.dart
@@ -0,0 +1,921 @@
+// 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.
+
+library vm.bytecode.assembler;
+
+import 'dart:typed_data';
+
+import 'package:vm/bytecode/dbc.dart';
+
+class Label {
+  List<int> _jumps = <int>[];
+  int offset = -1;
+
+  Label();
+
+  bool get isBound => offset >= 0;
+
+  int jumpOperand(int jumpOffset) {
+    if (isBound) {
+      // Jump instruction takes an offset in DBC words.
+      return (offset - jumpOffset) >> BytecodeAssembler.kLog2BytesPerBytecode;
+    }
+    _jumps.add(jumpOffset);
+    return 0;
+  }
+
+  List<int> bind(int offset) {
+    assert(!isBound);
+    this.offset = offset;
+    final jumps = _jumps;
+    _jumps = null;
+    return jumps;
+  }
+}
+
+class BytecodeAssembler {
+  static const int kBitsPerInt = 64;
+  static const int kLog2BytesPerBytecode = 2;
+
+  // TODO(alexmarkov): figure out more efficient storage for generated bytecode.
+  final List<int> bytecode = new List<int>();
+  final Uint32List _encodeBufferIn;
+  final Uint8List _encodeBufferOut;
+
+  BytecodeAssembler._(this._encodeBufferIn, this._encodeBufferOut);
+
+  factory BytecodeAssembler() {
+    final buf = new Uint32List(1);
+    return new BytecodeAssembler._(buf, new Uint8List.view(buf.buffer));
+  }
+
+  int get offset => bytecode.length;
+
+  void bind(Label label) {
+    final List<int> jumps = label.bind(offset);
+    for (int jumpOffset in jumps) {
+      patchJump(jumpOffset, label.jumpOperand(jumpOffset));
+    }
+  }
+
+  void emitWord(int word) {
+    _encodeBufferIn[0] = word; // TODO(alexmarkov): Which endianness to use?
+    bytecode.addAll(_encodeBufferOut);
+  }
+
+  void _setWord(int pos, int word) {
+    _encodeBufferIn[0] = word; // TODO(alexmarkov): Which endianness to use?
+    bytecode.setRange(pos, pos + _encodeBufferOut.length, _encodeBufferOut);
+  }
+
+  int _unsigned(int v, int bits) {
+    assert(bits < kBitsPerInt);
+    final int mask = (1 << bits) - 1;
+    if ((v & mask) != v) {
+      throw 'Value $v is out of unsigned $bits-bit range';
+    }
+    return v;
+  }
+
+  int _signed(int v, int bits) {
+    assert(bits < kBitsPerInt);
+    final int shift = kBitsPerInt - bits;
+    if (((v << shift) >> shift) != v) {
+      throw 'Value $v is out of signed $bits-bit range';
+    }
+    final int mask = (1 << bits) - 1;
+    return v & mask;
+  }
+
+  int _uint8(int v) => _unsigned(v, 8);
+  int _uint16(int v) => _unsigned(v, 16);
+
+  int _int8(int v) => _signed(v, 8);
+  int _int16(int v) => _signed(v, 16);
+  int _int24(int v) => _signed(v, 24);
+
+  int _encode0(Opcode opcode) => _uint8(opcode.index);
+
+  int _encodeA(Opcode opcode, int ra) =>
+      _uint8(opcode.index) | (_uint8(ra) << 8);
+
+  int _encodeAD(Opcode opcode, int ra, int rd) =>
+      _uint8(opcode.index) | (_uint8(ra) << 8) | (_uint16(rd) << 16);
+
+  int _encodeAX(Opcode opcode, int ra, int rx) =>
+      _uint8(opcode.index) | (_uint8(ra) << 8) | (_int16(rx) << 16);
+
+  int _encodeD(Opcode opcode, int rd) =>
+      _uint8(opcode.index) | (_uint16(rd) << 16);
+
+  int _encodeX(Opcode opcode, int rx) =>
+      _uint8(opcode.index) | (_int16(rx) << 16);
+
+  int _encodeABC(Opcode opcode, int ra, int rb, int rc) =>
+      _uint8(opcode.index) |
+      (_uint8(ra) << 8) |
+      (_uint8(rb) << 16) |
+      (_uint8(rc) << 24);
+
+  int _encodeABY(Opcode opcode, int ra, int rb, int ry) =>
+      _uint8(opcode.index) |
+      (_uint8(ra) << 8) |
+      (_uint8(rb) << 16) |
+      (_int8(ry) << 24);
+
+  int _encodeT(Opcode opcode, int rt) =>
+      _uint8(opcode.index) | (_int24(rt) << 8);
+
+  void emitTrap() {
+    emitWord(_encode0(Opcode.kTrap));
+  }
+
+  void emitNop(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kNop, ra, rd));
+  }
+
+  void emitCompile() {
+    emitWord(_encode0(Opcode.kCompile));
+  }
+
+  void emitHotCheck(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kHotCheck, ra, rd));
+  }
+
+  void emitIntrinsic(int ra) {
+    emitWord(_encodeA(Opcode.kIntrinsic, ra));
+  }
+
+  void emitDrop1() {
+    emitWord(_encode0(Opcode.kDrop1));
+  }
+
+  void emitDropR(int ra) {
+    emitWord(_encodeA(Opcode.kDropR, ra));
+  }
+
+  void emitDrop(int ra) {
+    emitWord(_encodeA(Opcode.kDrop, ra));
+  }
+
+  void emitJump(Label label) {
+    emitWord(_encodeT(Opcode.kJump, label.jumpOperand(offset)));
+  }
+
+  void patchJump(int pos, int rt) {
+    _setWord(pos, _encodeT(Opcode.kJump, rt));
+  }
+
+  void emitReturn(int ra) {
+    emitWord(_encodeA(Opcode.kReturn, ra));
+  }
+
+  void emitReturnTOS() {
+    emitWord(_encode0(Opcode.kReturnTOS));
+  }
+
+  void emitMove(int ra, int rx) {
+    emitWord(_encodeAX(Opcode.kMove, ra, rx));
+  }
+
+  void emitSwap(int ra, int rx) {
+    emitWord(_encodeAX(Opcode.kSwap, ra, rx));
+  }
+
+  void emitPush(int rx) {
+    emitWord(_encodeX(Opcode.kPush, rx));
+  }
+
+  void emitLoadConstant(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kLoadConstant, ra, rd));
+  }
+
+  void emitLoadClassId(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kLoadClassId, ra, rd));
+  }
+
+  void emitLoadClassIdTOS() {
+    emitWord(_encode0(Opcode.kLoadClassIdTOS));
+  }
+
+  void emitPushConstant(int rd) {
+    emitWord(_encodeD(Opcode.kPushConstant, rd));
+  }
+
+  void emitStoreLocal(int rx) {
+    emitWord(_encodeX(Opcode.kStoreLocal, rx));
+  }
+
+  void emitPopLocal(int rx) {
+    emitWord(_encodeX(Opcode.kPopLocal, rx));
+  }
+
+  void emitIndirectStaticCall(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIndirectStaticCall, ra, rd));
+  }
+
+  void emitStaticCall(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kStaticCall, ra, rd));
+  }
+
+  void emitInstanceCall1(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kInstanceCall1, ra, rd));
+  }
+
+  void emitInstanceCall2(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kInstanceCall2, ra, rd));
+  }
+
+  void emitInstanceCall1Opt(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kInstanceCall1Opt, ra, rd));
+  }
+
+  void emitInstanceCall2Opt(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kInstanceCall2Opt, ra, rd));
+  }
+
+  void emitPushPolymorphicInstanceCall(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kPushPolymorphicInstanceCall, ra, rd));
+  }
+
+  void emitPushPolymorphicInstanceCallByRange(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kPushPolymorphicInstanceCallByRange, ra, rd));
+  }
+
+  void emitNativeCall(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kNativeCall, ra, rb, rc));
+  }
+
+  void emitOneByteStringFromCharCode(int ra, int rx) {
+    emitWord(_encodeAX(Opcode.kOneByteStringFromCharCode, ra, rx));
+  }
+
+  void emitStringToCharCode(int ra, int rx) {
+    emitWord(_encodeAX(Opcode.kStringToCharCode, ra, rx));
+  }
+
+  void emitAddTOS() {
+    emitWord(_encode0(Opcode.kAddTOS));
+  }
+
+  void emitSubTOS() {
+    emitWord(_encode0(Opcode.kSubTOS));
+  }
+
+  void emitMulTOS() {
+    emitWord(_encode0(Opcode.kMulTOS));
+  }
+
+  void emitBitOrTOS() {
+    emitWord(_encode0(Opcode.kBitOrTOS));
+  }
+
+  void emitBitAndTOS() {
+    emitWord(_encode0(Opcode.kBitAndTOS));
+  }
+
+  void emitEqualTOS() {
+    emitWord(_encode0(Opcode.kEqualTOS));
+  }
+
+  void emitLessThanTOS() {
+    emitWord(_encode0(Opcode.kLessThanTOS));
+  }
+
+  void emitGreaterThanTOS() {
+    emitWord(_encode0(Opcode.kGreaterThanTOS));
+  }
+
+  void emitSmiAddTOS() {
+    emitWord(_encode0(Opcode.kSmiAddTOS));
+  }
+
+  void emitSmiSubTOS() {
+    emitWord(_encode0(Opcode.kSmiSubTOS));
+  }
+
+  void emitSmiMulTOS() {
+    emitWord(_encode0(Opcode.kSmiMulTOS));
+  }
+
+  void emitSmiBitAndTOS() {
+    emitWord(_encode0(Opcode.kSmiBitAndTOS));
+  }
+
+  void emitAdd(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kAdd, ra, rb, rc));
+  }
+
+  void emitSub(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kSub, ra, rb, rc));
+  }
+
+  void emitMul(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kMul, ra, rb, rc));
+  }
+
+  void emitDiv(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kDiv, ra, rb, rc));
+  }
+
+  void emitMod(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kMod, ra, rb, rc));
+  }
+
+  void emitShl(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kShl, ra, rb, rc));
+  }
+
+  void emitShr(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kShr, ra, rb, rc));
+  }
+
+  void emitShlImm(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kShlImm, ra, rb, rc));
+  }
+
+  void emitNeg(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kNeg, ra, rd));
+  }
+
+  void emitBitOr(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kBitOr, ra, rb, rc));
+  }
+
+  void emitBitAnd(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kBitAnd, ra, rb, rc));
+  }
+
+  void emitBitXor(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kBitXor, ra, rb, rc));
+  }
+
+  void emitBitNot(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kBitNot, ra, rd));
+  }
+
+  void emitMin(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kMin, ra, rb, rc));
+  }
+
+  void emitMax(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kMax, ra, rb, rc));
+  }
+
+  void emitWriteIntoDouble(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kWriteIntoDouble, ra, rd));
+  }
+
+  void emitUnboxDouble(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kUnboxDouble, ra, rd));
+  }
+
+  void emitCheckedUnboxDouble(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kCheckedUnboxDouble, ra, rd));
+  }
+
+  void emitUnboxInt32(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kUnboxInt32, ra, rb, rc));
+  }
+
+  void emitBoxInt32(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kBoxInt32, ra, rd));
+  }
+
+  void emitBoxUint32(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kBoxUint32, ra, rd));
+  }
+
+  void emitSmiToDouble(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kSmiToDouble, ra, rd));
+  }
+
+  void emitDoubleToSmi(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kDoubleToSmi, ra, rd));
+  }
+
+  void emitDAdd(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kDAdd, ra, rb, rc));
+  }
+
+  void emitDSub(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kDSub, ra, rb, rc));
+  }
+
+  void emitDMul(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kDMul, ra, rb, rc));
+  }
+
+  void emitDDiv(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kDDiv, ra, rb, rc));
+  }
+
+  void emitDNeg(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kDNeg, ra, rd));
+  }
+
+  void emitDSqrt(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kDSqrt, ra, rd));
+  }
+
+  void emitDMin(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kDMin, ra, rb, rc));
+  }
+
+  void emitDMax(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kDMax, ra, rb, rc));
+  }
+
+  void emitDCos(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kDCos, ra, rd));
+  }
+
+  void emitDSin(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kDSin, ra, rd));
+  }
+
+  void emitDPow(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kDPow, ra, rb, rc));
+  }
+
+  void emitDMod(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kDMod, ra, rb, rc));
+  }
+
+  void emitDTruncate(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kDTruncate, ra, rd));
+  }
+
+  void emitDFloor(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kDFloor, ra, rd));
+  }
+
+  void emitDCeil(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kDCeil, ra, rd));
+  }
+
+  void emitDoubleToFloat(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kDoubleToFloat, ra, rd));
+  }
+
+  void emitFloatToDouble(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kFloatToDouble, ra, rd));
+  }
+
+  void emitDoubleIsNaN(int ra) {
+    emitWord(_encodeA(Opcode.kDoubleIsNaN, ra));
+  }
+
+  void emitDoubleIsInfinite(int ra) {
+    emitWord(_encodeA(Opcode.kDoubleIsInfinite, ra));
+  }
+
+  void emitStoreStaticTOS(int rd) {
+    emitWord(_encodeD(Opcode.kStoreStaticTOS, rd));
+  }
+
+  void emitPushStatic(int rd) {
+    emitWord(_encodeD(Opcode.kPushStatic, rd));
+  }
+
+  void emitInitStaticTOS() {
+    emitWord(_encode0(Opcode.kInitStaticTOS));
+  }
+
+  void emitIfNeStrictTOS() {
+    emitWord(_encode0(Opcode.kIfNeStrictTOS));
+  }
+
+  void emitIfEqStrictTOS() {
+    emitWord(_encode0(Opcode.kIfEqStrictTOS));
+  }
+
+  void emitIfNeStrictNumTOS() {
+    emitWord(_encode0(Opcode.kIfNeStrictNumTOS));
+  }
+
+  void emitIfEqStrictNumTOS() {
+    emitWord(_encode0(Opcode.kIfEqStrictNumTOS));
+  }
+
+  void emitIfSmiLtTOS() {
+    emitWord(_encode0(Opcode.kIfSmiLtTOS));
+  }
+
+  void emitIfSmiLeTOS() {
+    emitWord(_encode0(Opcode.kIfSmiLeTOS));
+  }
+
+  void emitIfSmiGeTOS() {
+    emitWord(_encode0(Opcode.kIfSmiGeTOS));
+  }
+
+  void emitIfSmiGtTOS() {
+    emitWord(_encode0(Opcode.kIfSmiGtTOS));
+  }
+
+  void emitIfNeStrict(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfNeStrict, ra, rd));
+  }
+
+  void emitIfEqStrict(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfEqStrict, ra, rd));
+  }
+
+  void emitIfLe(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfLe, ra, rd));
+  }
+
+  void emitIfLt(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfLt, ra, rd));
+  }
+
+  void emitIfGe(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfGe, ra, rd));
+  }
+
+  void emitIfGt(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfGt, ra, rd));
+  }
+
+  void emitIfULe(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfULe, ra, rd));
+  }
+
+  void emitIfULt(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfULt, ra, rd));
+  }
+
+  void emitIfUGe(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfUGe, ra, rd));
+  }
+
+  void emitIfUGt(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfUGt, ra, rd));
+  }
+
+  void emitIfDNe(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfDNe, ra, rd));
+  }
+
+  void emitIfDEq(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfDEq, ra, rd));
+  }
+
+  void emitIfDLe(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfDLe, ra, rd));
+  }
+
+  void emitIfDLt(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfDLt, ra, rd));
+  }
+
+  void emitIfDGe(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfDGe, ra, rd));
+  }
+
+  void emitIfDGt(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfDGt, ra, rd));
+  }
+
+  void emitIfNeStrictNum(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfNeStrictNum, ra, rd));
+  }
+
+  void emitIfEqStrictNum(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kIfEqStrictNum, ra, rd));
+  }
+
+  void emitIfEqNull(int ra) {
+    emitWord(_encodeA(Opcode.kIfEqNull, ra));
+  }
+
+  void emitIfNeNull(int ra) {
+    emitWord(_encodeA(Opcode.kIfNeNull, ra));
+  }
+
+  void emitCreateArrayTOS() {
+    emitWord(_encode0(Opcode.kCreateArrayTOS));
+  }
+
+  void emitCreateArrayOpt(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kCreateArrayOpt, ra, rb, rc));
+  }
+
+  void emitAllocate(int rd) {
+    emitWord(_encodeD(Opcode.kAllocate, rd));
+  }
+
+  void emitAllocateT() {
+    emitWord(_encode0(Opcode.kAllocateT));
+  }
+
+  void emitAllocateOpt(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kAllocateOpt, ra, rd));
+  }
+
+  void emitAllocateTOpt(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kAllocateTOpt, ra, rd));
+  }
+
+  void emitStoreIndexedTOS() {
+    emitWord(_encode0(Opcode.kStoreIndexedTOS));
+  }
+
+  void emitStoreIndexed(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kStoreIndexed, ra, rb, rc));
+  }
+
+  void emitStoreIndexedUint8(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kStoreIndexedUint8, ra, rb, rc));
+  }
+
+  void emitStoreIndexedExternalUint8(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kStoreIndexedExternalUint8, ra, rb, rc));
+  }
+
+  void emitStoreIndexedOneByteString(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kStoreIndexedOneByteString, ra, rb, rc));
+  }
+
+  void emitStoreIndexedUint32(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kStoreIndexedUint32, ra, rb, rc));
+  }
+
+  void emitStoreIndexedFloat32(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kStoreIndexedFloat32, ra, rb, rc));
+  }
+
+  void emitStoreIndexed4Float32(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kStoreIndexed4Float32, ra, rb, rc));
+  }
+
+  void emitStoreIndexedFloat64(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kStoreIndexedFloat64, ra, rb, rc));
+  }
+
+  void emitStoreIndexed8Float64(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kStoreIndexed8Float64, ra, rb, rc));
+  }
+
+  void emitNoSuchMethod() {
+    emitWord(_encode0(Opcode.kNoSuchMethod));
+  }
+
+  void emitTailCall() {
+    emitWord(_encode0(Opcode.kTailCall));
+  }
+
+  void emitTailCallOpt(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kTailCallOpt, ra, rd));
+  }
+
+  void emitLoadArgDescriptor() {
+    emitWord(_encode0(Opcode.kLoadArgDescriptor));
+  }
+
+  void emitLoadArgDescriptorOpt(int ra) {
+    emitWord(_encodeA(Opcode.kLoadArgDescriptorOpt, ra));
+  }
+
+  void emitLoadFpRelativeSlot(int rx) {
+    emitWord(_encodeX(Opcode.kLoadFpRelativeSlot, rx));
+  }
+
+  void emitLoadFpRelativeSlotOpt(int ra, int rb, int ry) {
+    emitWord(_encodeABY(Opcode.kLoadFpRelativeSlotOpt, ra, rb, ry));
+  }
+
+  void emitStoreFpRelativeSlot(int rx) {
+    emitWord(_encodeX(Opcode.kStoreFpRelativeSlot, rx));
+  }
+
+  void emitStoreFpRelativeSlotOpt(int ra, int rb, int ry) {
+    emitWord(_encodeABY(Opcode.kStoreFpRelativeSlotOpt, ra, rb, ry));
+  }
+
+  void emitLoadIndexedTOS() {
+    emitWord(_encode0(Opcode.kLoadIndexedTOS));
+  }
+
+  void emitLoadIndexed(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kLoadIndexed, ra, rb, rc));
+  }
+
+  void emitLoadIndexedUint8(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kLoadIndexedUint8, ra, rb, rc));
+  }
+
+  void emitLoadIndexedInt8(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kLoadIndexedInt8, ra, rb, rc));
+  }
+
+  void emitLoadIndexedInt32(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kLoadIndexedInt32, ra, rb, rc));
+  }
+
+  void emitLoadIndexedUint32(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kLoadIndexedUint32, ra, rb, rc));
+  }
+
+  void emitLoadIndexedExternalUint8(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kLoadIndexedExternalUint8, ra, rb, rc));
+  }
+
+  void emitLoadIndexedExternalInt8(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kLoadIndexedExternalInt8, ra, rb, rc));
+  }
+
+  void emitLoadIndexedFloat32(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kLoadIndexedFloat32, ra, rb, rc));
+  }
+
+  void emitLoadIndexed4Float32(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kLoadIndexed4Float32, ra, rb, rc));
+  }
+
+  void emitLoadIndexedFloat64(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kLoadIndexedFloat64, ra, rb, rc));
+  }
+
+  void emitLoadIndexed8Float64(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kLoadIndexed8Float64, ra, rb, rc));
+  }
+
+  void emitLoadIndexedOneByteString(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kLoadIndexedOneByteString, ra, rb, rc));
+  }
+
+  void emitLoadIndexedTwoByteString(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kLoadIndexedTwoByteString, ra, rb, rc));
+  }
+
+  void emitStoreField(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kStoreField, ra, rb, rc));
+  }
+
+  void emitStoreFieldExt(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kStoreFieldExt, ra, rd));
+  }
+
+  void emitStoreFieldTOS(int rd) {
+    emitWord(_encodeD(Opcode.kStoreFieldTOS, rd));
+  }
+
+  void emitLoadField(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kLoadField, ra, rb, rc));
+  }
+
+  void emitLoadFieldExt(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kLoadFieldExt, ra, rd));
+  }
+
+  void emitLoadUntagged(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kLoadUntagged, ra, rb, rc));
+  }
+
+  void emitLoadFieldTOS(int rd) {
+    emitWord(_encodeD(Opcode.kLoadFieldTOS, rd));
+  }
+
+  void emitBooleanNegateTOS() {
+    emitWord(_encode0(Opcode.kBooleanNegateTOS));
+  }
+
+  void emitBooleanNegate(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kBooleanNegate, ra, rd));
+  }
+
+  void emitThrow(int ra) {
+    emitWord(_encodeA(Opcode.kThrow, ra));
+  }
+
+  void emitEntry(int rd) {
+    emitWord(_encodeD(Opcode.kEntry, rd));
+  }
+
+  void emitEntryOptimized(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kEntryOptimized, ra, rd));
+  }
+
+  void emitFrame(int rd) {
+    emitWord(_encodeD(Opcode.kFrame, rd));
+  }
+
+  void emitSetFrame(int ra) {
+    emitWord(_encodeA(Opcode.kSetFrame, ra));
+  }
+
+  void emitAllocateContext(int rd) {
+    emitWord(_encodeD(Opcode.kAllocateContext, rd));
+  }
+
+  void emitAllocateUninitializedContext(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kAllocateUninitializedContext, ra, rd));
+  }
+
+  void emitCloneContext() {
+    emitWord(_encode0(Opcode.kCloneContext));
+  }
+
+  void emitMoveSpecial(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kMoveSpecial, ra, rd));
+  }
+
+  void emitInstantiateType(int rd) {
+    emitWord(_encodeD(Opcode.kInstantiateType, rd));
+  }
+
+  void emitInstantiateTypeArgumentsTOS(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kInstantiateTypeArgumentsTOS, ra, rd));
+  }
+
+  void emitInstanceOf() {
+    emitWord(_encode0(Opcode.kInstanceOf));
+  }
+
+  void emitBadTypeError() {
+    emitWord(_encode0(Opcode.kBadTypeError));
+  }
+
+  void emitAssertAssignable(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kAssertAssignable, ra, rd));
+  }
+
+  void emitAssertSubtype() {
+    emitWord(_encode0(Opcode.kAssertSubtype));
+  }
+
+  void emitAssertBoolean(int ra) {
+    emitWord(_encodeA(Opcode.kAssertBoolean, ra));
+  }
+
+  void emitTestSmi(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kTestSmi, ra, rd));
+  }
+
+  void emitTestCids(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kTestCids, ra, rd));
+  }
+
+  void emitCheckSmi(int ra) {
+    emitWord(_encodeA(Opcode.kCheckSmi, ra));
+  }
+
+  void emitCheckEitherNonSmi(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kCheckEitherNonSmi, ra, rd));
+  }
+
+  void emitCheckClassId(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kCheckClassId, ra, rd));
+  }
+
+  void emitCheckClassIdRange(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kCheckClassIdRange, ra, rd));
+  }
+
+  void emitCheckBitTest(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kCheckBitTest, ra, rd));
+  }
+
+  void emitCheckCids(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kCheckCids, ra, rb, rc));
+  }
+
+  void emitCheckCidsByRange(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kCheckCidsByRange, ra, rb, rc));
+  }
+
+  void emitCheckStack() {
+    emitWord(_encode0(Opcode.kCheckStack));
+  }
+
+  void emitCheckStackAlwaysExit() {
+    emitWord(_encode0(Opcode.kCheckStackAlwaysExit));
+  }
+
+  void emitCheckFunctionTypeArgs(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kCheckFunctionTypeArgs, ra, rd));
+  }
+
+  void emitDebugStep() {
+    emitWord(_encode0(Opcode.kDebugStep));
+  }
+
+  void emitDebugBreak(int ra) {
+    emitWord(_encodeA(Opcode.kDebugBreak, ra));
+  }
+
+  void emitDeopt(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kDeopt, ra, rd));
+  }
+
+  void emitDeoptRewind() {
+    emitWord(_encode0(Opcode.kDeoptRewind));
+  }
+
+  void emitEntryOptional(int ra, int rb, int rc) {
+    emitWord(_encodeABC(Opcode.kEntryOptional, ra, rb, rc));
+  }
+}
diff --git a/pkg/vm/lib/bytecode/constant_pool.dart b/pkg/vm/lib/bytecode/constant_pool.dart
new file mode 100644
index 0000000..770ff55
--- /dev/null
+++ b/pkg/vm/lib/bytecode/constant_pool.dart
@@ -0,0 +1,840 @@
+// 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.
+
+library vm.bytecode.constant_pool;
+
+import 'dart:typed_data';
+
+import 'package:kernel/ast.dart' hide MapEntry;
+
+/*
+
+In kernel binary, constant pool is encoded in the following way
+(using notation from pkg/kernel/binary.md):
+
+type ConstantPool {
+  List<ConstantPoolEntry>
+}
+
+abstract type ConstantPoolEntry {
+  Byte tag;
+}
+
+type ConstantNull extends ConstantPoolEntry {
+  Byte tag = 1;
+}
+
+type ConstantString extends ConstantPoolEntry {
+  Byte tag = 2;
+  StringReference value;
+}
+
+type ConstantInt extends ConstantPoolEntry {
+  Byte tag = 3;
+  UInt32 low;
+  UInt32 high;
+}
+
+type ConstantDouble extends ConstantPoolEntry {
+  Byte tag = 4;
+  UInt32 low;
+  UInt32 high;
+}
+
+type ConstantBool extends ConstantPoolEntry {
+  Byte tag = 5;
+  UInt flag;
+}
+
+type ConstantArgDesc extends ConstantPoolEntry {
+  Byte tag = 6;
+  UInt numArguments;
+  UInt numTypeArgs;
+  List<StringReference> names;
+}
+
+type ConstantICData extends ConstantPoolEntry {
+  Byte tag = 7;
+  StringReference targetName;
+  UInt argDescConstantIndex;
+}
+
+type ConstantStaticICData extends ConstantPoolEntry {
+  Byte tag = 8;
+  CanonicalNameReference target;
+  UInt argDescConstantIndex;
+}
+
+type ConstantField extends ConstantPoolEntry {
+  Byte tag = 9;
+  CanonicalNameReference field;
+}
+
+type ConstantFieldOffset extends ConstantPoolEntry {
+  Byte tag = 10;
+  CanonicalNameReference field;
+}
+
+type ConstantClass extends ConstantPoolEntry {
+  Byte tag = 11;
+  CanonicalNameReference class;
+}
+
+type ConstantTypeArgumentsFieldOffset extends ConstantPoolEntry {
+  Byte tag = 12;
+  CanonicalNameReference class;
+}
+
+type ConstantTearOff extends ConstantPoolEntry {
+  Byte tag = 13;
+  CanonicalNameReference target;
+}
+
+type ConstantType extends ConstantPoolEntry {
+  Byte tag = 14;
+  NodeReference type;
+}
+
+type ConstantTypeArguments extends ConstantPoolEntry {
+  Byte tag = 15;
+  List<NodeReference> types;
+}
+
+type ConstantList extends ConstantPoolEntry {
+  Byte tag = 16;
+  NodeReference typeArg;
+  List<UInt> entries;
+}
+
+type ConstantInstance extends ConstantPoolEntry {
+  Byte tag = 17;
+  CanonicalNameReference class;
+  UInt typeArgumentsConstantIndex;
+  List<Pair<CanonicalNameReference, UInt>> fieldValues;
+}
+
+type ConstantSymbol extends ConstantPoolEntry {
+  Byte tag = 18;
+  StringReference value;
+}
+
+*/
+
+enum ConstantTag {
+  kInvalid,
+  kNull,
+  kString,
+  kInt,
+  kDouble,
+  kBool,
+  kArgDesc,
+  kICData,
+  kStaticICData,
+  kField,
+  kFieldOffset,
+  kClass,
+  kTypeArgumentsFieldOffset,
+  kTearOff,
+  kType,
+  kTypeArguments,
+  kList,
+  kInstance,
+  kSymbol,
+}
+
+abstract class ConstantPoolEntry {
+  const ConstantPoolEntry();
+
+  ConstantTag get tag;
+
+  void writeToBinary(BinarySink sink) {
+    sink.writeUInt30(tag.index);
+    writeValueToBinary(sink);
+  }
+
+  void writeValueToBinary(BinarySink sink);
+
+  factory ConstantPoolEntry.readFromBinary(BinarySource source) {
+    ConstantTag tag = ConstantTag.values[source.readUInt()];
+    switch (tag) {
+      case ConstantTag.kInvalid:
+        break;
+      case ConstantTag.kNull:
+        return new ConstantNull.readFromBinary(source);
+      case ConstantTag.kString:
+        return new ConstantString.readFromBinary(source);
+      case ConstantTag.kInt:
+        return new ConstantInt.readFromBinary(source);
+      case ConstantTag.kDouble:
+        return new ConstantDouble.readFromBinary(source);
+      case ConstantTag.kBool:
+        return new ConstantBool.readFromBinary(source);
+      case ConstantTag.kICData:
+        return new ConstantICData.readFromBinary(source);
+      case ConstantTag.kStaticICData:
+        return new ConstantStaticICData.readFromBinary(source);
+      case ConstantTag.kArgDesc:
+        return new ConstantArgDesc.readFromBinary(source);
+      case ConstantTag.kField:
+        return new ConstantField.readFromBinary(source);
+      case ConstantTag.kFieldOffset:
+        return new ConstantFieldOffset.readFromBinary(source);
+      case ConstantTag.kClass:
+        return new ConstantClass.readFromBinary(source);
+      case ConstantTag.kTypeArgumentsFieldOffset:
+        return new ConstantTypeArgumentsFieldOffset.readFromBinary(source);
+      case ConstantTag.kTearOff:
+        return new ConstantTearOff.readFromBinary(source);
+      case ConstantTag.kType:
+        return new ConstantType.readFromBinary(source);
+      case ConstantTag.kTypeArguments:
+        return new ConstantTypeArguments.readFromBinary(source);
+      case ConstantTag.kList:
+        return new ConstantList.readFromBinary(source);
+      case ConstantTag.kInstance:
+        return new ConstantInstance.readFromBinary(source);
+      case ConstantTag.kSymbol:
+        return new ConstantSymbol.readFromBinary(source);
+    }
+    throw 'Unexpected constant tag $tag';
+  }
+}
+
+class ConstantNull extends ConstantPoolEntry {
+  const ConstantNull();
+
+  @override
+  ConstantTag get tag => ConstantTag.kNull;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {}
+
+  ConstantNull.readFromBinary(BinarySource source);
+
+  @override
+  String toString() => 'Null';
+
+  @override
+  int get hashCode => 1961;
+
+  @override
+  bool operator ==(other) => other is ConstantNull;
+}
+
+class ConstantString extends ConstantPoolEntry {
+  final String value;
+
+  ConstantString(this.value);
+  ConstantString.fromLiteral(StringLiteral literal) : this(literal.value);
+
+  @override
+  ConstantTag get tag => ConstantTag.kString;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    sink.writeStringReference(value);
+  }
+
+  ConstantString.readFromBinary(BinarySource source)
+      : value = source.readStringReference();
+
+  @override
+  String toString() => 'String \'$value\'';
+
+  @override
+  int get hashCode => value.hashCode;
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantString && this.value == other.value;
+}
+
+class ConstantInt extends ConstantPoolEntry {
+  final int value;
+
+  ConstantInt(this.value);
+  ConstantInt.fromLiteral(IntLiteral literal) : this(literal.value);
+
+  @override
+  ConstantTag get tag => ConstantTag.kInt;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    // TODO(alexmarkov): more efficient encoding
+    sink.writeUInt32(value & 0xffffffff);
+    sink.writeUInt32((value >> 32) & 0xffffffff);
+  }
+
+  ConstantInt.readFromBinary(BinarySource source)
+      : value = source.readUint32() | (source.readUint32() << 32);
+
+  @override
+  String toString() => 'Int $value';
+
+  @override
+  int get hashCode => value;
+
+  @override
+  bool operator ==(other) => other is ConstantInt && this.value == other.value;
+}
+
+class ConstantDouble extends ConstantPoolEntry {
+  final double value;
+
+  ConstantDouble(this.value);
+  ConstantDouble.fromLiteral(DoubleLiteral literal) : this(literal.value);
+
+  @override
+  ConstantTag get tag => ConstantTag.kDouble;
+
+  static int doubleToIntBits(double value) {
+    final buf = new ByteData(8);
+    buf.setFloat64(0, value, Endian.host);
+    return buf.getInt64(0, Endian.host);
+  }
+
+  static double intBitsToDouble(int bits) {
+    final buf = new ByteData(8);
+    buf.setInt64(0, bits, Endian.host);
+    return buf.getFloat64(0, Endian.host);
+  }
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    // TODO(alexmarkov): more efficient encoding
+    int bits = doubleToIntBits(value);
+    sink.writeUInt32(bits & 0xffffffff);
+    sink.writeUInt32((bits >> 32) & 0xffffffff);
+  }
+
+  ConstantDouble.readFromBinary(BinarySource source)
+      : value =
+            intBitsToDouble(source.readUint32() | (source.readUint32() << 32));
+
+  @override
+  String toString() => 'Double $value';
+
+  @override
+  int get hashCode => value.hashCode;
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantDouble && value.compareTo(other.value) == 0;
+}
+
+class ConstantBool extends ConstantPoolEntry {
+  final bool value;
+
+  ConstantBool(this.value);
+  ConstantBool.fromLiteral(BoolLiteral literal) : this(literal.value);
+
+  @override
+  ConstantTag get tag => ConstantTag.kBool;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    sink.writeUInt30(value ? 1 : 0);
+  }
+
+  ConstantBool.readFromBinary(BinarySource source)
+      : value = source.readUInt() != 0;
+
+  @override
+  String toString() => 'Bool $value';
+
+  @override
+  int get hashCode => value.hashCode;
+
+  @override
+  bool operator ==(other) => other is ConstantBool && this.value == other.value;
+}
+
+class ConstantArgDesc extends ConstantPoolEntry {
+  final int numArguments;
+  final int numTypeArgs;
+  final List<String> argNames;
+
+  ConstantArgDesc(this.numArguments,
+      {this.numTypeArgs = 0, this.argNames = const <String>[]});
+
+  ConstantArgDesc.fromArguments(Arguments args, {bool hasReceiver: false})
+      : this(args.positional.length + args.named.length + (hasReceiver ? 1 : 0),
+            numTypeArgs: args.types.length,
+            argNames: new List<String>.from(args.named.map((ne) => ne.name)));
+
+  @override
+  ConstantTag get tag => ConstantTag.kArgDesc;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    sink.writeUInt30(numArguments);
+    sink.writeUInt30(numTypeArgs);
+    sink.writeUInt30(argNames.length);
+    argNames.forEach(sink.writeStringReference);
+  }
+
+  ConstantArgDesc.readFromBinary(BinarySource source)
+      : numArguments = source.readUInt(),
+        numTypeArgs = source.readUInt(),
+        argNames = new List<String>.generate(
+            source.readUInt(), (_) => source.readStringReference());
+
+  @override
+  String toString() =>
+      'ArgDesc num-args $numArguments, num-type-args $numTypeArgs, names $argNames';
+
+  @override
+  int get hashCode =>
+      (numArguments * 31 + numTypeArgs) * 31 + listHashCode(argNames);
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantArgDesc &&
+      this.numArguments == other.numArguments &&
+      this.numTypeArgs == other.numTypeArgs &&
+      listEquals(this.argNames, other.argNames);
+}
+
+class ConstantICData extends ConstantPoolEntry {
+  final String targetName;
+  final int argDescConstantIndex;
+
+  ConstantICData(this.targetName, this.argDescConstantIndex);
+
+  @override
+  ConstantTag get tag => ConstantTag.kICData;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    sink.writeStringReference(targetName);
+    sink.writeUInt30(argDescConstantIndex);
+  }
+
+  ConstantICData.readFromBinary(BinarySource source)
+      : targetName = source.readStringReference(),
+        argDescConstantIndex = source.readUInt();
+
+  @override
+  String toString() =>
+      'ICData target-name \'$targetName\', arg-desc CP#$argDescConstantIndex';
+
+  // ConstantICData entries are created per call site and should not be merged,
+  // so ConstantICData class uses identity [hashCode] and [operator ==].
+
+  @override
+  int get hashCode => identityHashCode(this);
+
+  @override
+  bool operator ==(other) => identical(this, other);
+}
+
+class ConstantStaticICData extends ConstantPoolEntry {
+  final Reference _reference;
+  final int argDescConstantIndex;
+
+  ConstantStaticICData(Member member, int argDescConstantIndex)
+      : this.byReference(member.reference, argDescConstantIndex);
+  ConstantStaticICData.byReference(this._reference, this.argDescConstantIndex);
+
+  Member get target => _reference.asMember;
+
+  @override
+  ConstantTag get tag => ConstantTag.kStaticICData;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    sink.writeCanonicalNameReference(getCanonicalNameOfMember(target));
+    sink.writeUInt30(argDescConstantIndex);
+  }
+
+  ConstantStaticICData.readFromBinary(BinarySource source)
+      : _reference = source.readCanonicalNameReference().getReference(),
+        argDescConstantIndex = source.readUInt();
+
+  @override
+  String toString() =>
+      'StaticICData target \'$target\', arg-desc CP#$argDescConstantIndex';
+
+  // ConstantStaticICData entries are created per call site and should not be
+  // merged, so ConstantStaticICData class uses identity [hashCode] and
+  // [operator ==].
+
+  @override
+  int get hashCode => identityHashCode(this);
+
+  @override
+  bool operator ==(other) => identical(this, other);
+}
+
+class ConstantField extends ConstantPoolEntry {
+  final Reference _reference;
+
+  Field get field => _reference.asField;
+
+  ConstantField(Field field) : this.byReference(field.reference);
+  ConstantField.byReference(this._reference);
+
+  @override
+  ConstantTag get tag => ConstantTag.kField;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    sink.writeCanonicalNameReference(getCanonicalNameOfMember(field));
+  }
+
+  ConstantField.readFromBinary(BinarySource source)
+      : _reference = source.readCanonicalNameReference().getReference();
+
+  @override
+  String toString() => 'Field $field';
+
+  @override
+  int get hashCode => field.hashCode;
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantField && this.field == other.field;
+}
+
+class ConstantFieldOffset extends ConstantPoolEntry {
+  final Reference _reference;
+
+  Field get field => _reference.asField;
+
+  ConstantFieldOffset(Field field) : this.byReference(field.reference);
+  ConstantFieldOffset.byReference(this._reference);
+
+  @override
+  ConstantTag get tag => ConstantTag.kFieldOffset;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    sink.writeCanonicalNameReference(getCanonicalNameOfMember(field));
+  }
+
+  ConstantFieldOffset.readFromBinary(BinarySource source)
+      : _reference = source.readCanonicalNameReference().getReference();
+
+  @override
+  String toString() => 'FieldOffset $field';
+
+  @override
+  int get hashCode => field.hashCode;
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantFieldOffset && this.field == other.field;
+}
+
+class ConstantClass extends ConstantPoolEntry {
+  final Reference _reference;
+
+  Class get classNode => _reference.asClass;
+
+  ConstantClass(Class class_) : this.byReference(class_.reference);
+  ConstantClass.byReference(this._reference);
+
+  @override
+  ConstantTag get tag => ConstantTag.kClass;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    sink.writeCanonicalNameReference(getCanonicalNameOfClass(classNode));
+  }
+
+  ConstantClass.readFromBinary(BinarySource source)
+      : _reference = source.readCanonicalNameReference().getReference();
+
+  @override
+  String toString() => 'Class $classNode';
+
+  @override
+  int get hashCode => classNode.hashCode;
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantClass && this.classNode == other.classNode;
+}
+
+class ConstantTypeArgumentsFieldOffset extends ConstantPoolEntry {
+  final Reference _reference;
+
+  Class get classNode => _reference.asClass;
+
+  ConstantTypeArgumentsFieldOffset(Class class_)
+      : this.byReference(class_.reference);
+  ConstantTypeArgumentsFieldOffset.byReference(this._reference);
+
+  @override
+  ConstantTag get tag => ConstantTag.kTypeArgumentsFieldOffset;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    sink.writeCanonicalNameReference(getCanonicalNameOfClass(classNode));
+  }
+
+  ConstantTypeArgumentsFieldOffset.readFromBinary(BinarySource source)
+      : _reference = source.readCanonicalNameReference().getReference();
+
+  @override
+  String toString() => 'TypeArgumentsFieldOffset $classNode';
+
+  @override
+  int get hashCode => classNode.hashCode;
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantTypeArgumentsFieldOffset &&
+      this.classNode == other.classNode;
+}
+
+class ConstantTearOff extends ConstantPoolEntry {
+  final Reference _reference;
+
+  Procedure get procedure => _reference.asProcedure;
+
+  ConstantTearOff(Procedure procedure) : this.byReference(procedure.reference);
+  ConstantTearOff.byReference(this._reference);
+
+  @override
+  ConstantTag get tag => ConstantTag.kTearOff;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    sink.writeCanonicalNameReference(getCanonicalNameOfMember(procedure));
+  }
+
+  ConstantTearOff.readFromBinary(BinarySource source)
+      : _reference = source.readCanonicalNameReference().getReference();
+
+  @override
+  String toString() => 'TearOff $procedure';
+
+  @override
+  int get hashCode => procedure.hashCode;
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantTearOff && this.procedure == other.procedure;
+}
+
+class ConstantType extends ConstantPoolEntry {
+  final DartType type;
+
+  ConstantType(this.type);
+
+  @override
+  ConstantTag get tag => ConstantTag.kType;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    sink.writeNodeReference(type);
+  }
+
+  ConstantType.readFromBinary(BinarySource source)
+      : type = source.readNodeReference() as DartType;
+
+  @override
+  String toString() => 'Type $type';
+
+  @override
+  int get hashCode => type.hashCode;
+
+  @override
+  bool operator ==(other) => other is ConstantType && this.type == other.type;
+}
+
+class ConstantTypeArguments extends ConstantPoolEntry {
+  final List<DartType> typeArgs;
+
+  ConstantTypeArguments(this.typeArgs);
+
+  @override
+  ConstantTag get tag => ConstantTag.kTypeArguments;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    sink.writeUInt30(typeArgs.length);
+    typeArgs.forEach(sink.writeNodeReference);
+  }
+
+  ConstantTypeArguments.readFromBinary(BinarySource source)
+      : typeArgs = new List<DartType>.generate(
+            source.readUInt(), (_) => source.readNodeReference() as DartType);
+
+  @override
+  String toString() => 'TypeArgs $typeArgs';
+
+  @override
+  int get hashCode => listHashCode(typeArgs);
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantTypeArguments &&
+      listEquals(this.typeArgs, other.typeArgs);
+}
+
+class ConstantList extends ConstantPoolEntry {
+  final DartType typeArg;
+  final List<int> entries;
+
+  ConstantList(this.typeArg, this.entries);
+
+  @override
+  ConstantTag get tag => ConstantTag.kList;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    sink.writeNodeReference(typeArg);
+    sink.writeUInt30(entries.length);
+    entries.forEach(sink.writeUInt30);
+  }
+
+  ConstantList.readFromBinary(BinarySource source)
+      : typeArg = source.readNodeReference() as DartType,
+        entries =
+            new List<int>.generate(source.readUInt(), (_) => source.readUInt());
+
+  @override
+  String toString() => 'List type-arg $typeArg, entries CP# $entries';
+
+  @override
+  int get hashCode => typeArg.hashCode ^ listHashCode(entries);
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantList &&
+      this.typeArg == other.typeArg &&
+      listEquals(this.entries, other.entries);
+}
+
+class ConstantInstance extends ConstantPoolEntry {
+  final Reference _classReference;
+  final int _typeArgumentsConstantIndex;
+  final Map<Reference, int> _fieldValues;
+
+  ConstantInstance(Class class_, int typeArgumentsConstantIndex,
+      Map<Reference, int> fieldValues)
+      : this.byReference(
+            class_.reference, typeArgumentsConstantIndex, fieldValues);
+
+  ConstantInstance.byReference(this._classReference,
+      this._typeArgumentsConstantIndex, this._fieldValues);
+
+  @override
+  ConstantTag get tag => ConstantTag.kInstance;
+
+  Class get classNode => _classReference.asClass;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    sink.writeCanonicalNameReference(getCanonicalNameOfClass(classNode));
+    sink.writeUInt30(_typeArgumentsConstantIndex);
+    sink.writeUInt30(_fieldValues.length);
+    _fieldValues.forEach((Reference fieldRef, int valueIndex) {
+      sink.writeCanonicalNameReference(
+          getCanonicalNameOfMember(fieldRef.asField));
+      sink.writeUInt30(valueIndex);
+    });
+  }
+
+  ConstantInstance.readFromBinary(BinarySource source)
+      : _classReference = source.readCanonicalNameReference().getReference(),
+        _typeArgumentsConstantIndex = source.readUInt(),
+        _fieldValues = new Map<Reference, int>() {
+    final fieldValuesLen = source.readUInt();
+    for (int i = 0; i < fieldValuesLen; i++) {
+      final fieldRef = source.readCanonicalNameReference().getReference();
+      final valueIndex = source.readUInt();
+      _fieldValues[fieldRef] = valueIndex;
+    }
+  }
+
+  @override
+  String toString() =>
+      'Instance $classNode type-args CP#$_typeArgumentsConstantIndex'
+      ' ${_fieldValues.map<String, int>((Reference fieldRef, int valueIndex) =>
+              new MapEntry(fieldRef.asField.name.name, valueIndex))}';
+
+  @override
+  int get hashCode =>
+      (classNode.hashCode * 31 + _typeArgumentsConstantIndex) * 31 +
+      mapHashCode(_fieldValues);
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantInstance &&
+      this.classNode == other.classNode &&
+      this._typeArgumentsConstantIndex == other._typeArgumentsConstantIndex &&
+      mapEquals(this._fieldValues, other._fieldValues);
+}
+
+class ConstantSymbol extends ConstantPoolEntry {
+  final String value;
+
+  ConstantSymbol(this.value);
+  ConstantSymbol.fromLiteral(SymbolLiteral literal) : this(literal.value);
+
+  @override
+  ConstantTag get tag => ConstantTag.kSymbol;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    sink.writeStringReference(value);
+  }
+
+  ConstantSymbol.readFromBinary(BinarySource source)
+      : value = source.readStringReference();
+
+  @override
+  String toString() => 'Symbol \'$value\'';
+
+  @override
+  int get hashCode => value.hashCode;
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantSymbol && this.value == other.value;
+}
+
+class ConstantPool {
+  final List<ConstantPoolEntry> entries = <ConstantPoolEntry>[];
+  final Map<ConstantPoolEntry, int> _canonicalizationCache =
+      <ConstantPoolEntry, int>{};
+
+  ConstantPool();
+
+  int add(ConstantPoolEntry entry) {
+    return _canonicalizationCache.putIfAbsent(entry, () {
+      int index = entries.length;
+      entries.add(entry);
+      return index;
+    });
+  }
+
+  void writeToBinary(BinarySink sink) {
+    sink.writeUInt30(entries.length);
+    entries.forEach((e) {
+      e.writeToBinary(sink);
+    });
+  }
+
+  ConstantPool.readFromBinary(BinarySource source) {
+    int len = source.readUInt();
+    for (int i = 0; i < len; i++) {
+      entries.add(new ConstantPoolEntry.readFromBinary(source));
+    }
+  }
+
+  @override
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.writeln('ConstantPool {');
+    for (int i = 0; i < entries.length; i++) {
+      sb.writeln('  [$i] = ${entries[i]}');
+    }
+    sb.writeln('}');
+    return sb.toString();
+  }
+}
diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart
new file mode 100644
index 0000000..17c68c3
--- /dev/null
+++ b/pkg/vm/lib/bytecode/dbc.dart
@@ -0,0 +1,651 @@
+// 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.
+
+library vm.bytecode.dbc;
+
+// List of changes from original DBC (described in runtime/vm/constants_dbc.h):
+//
+// 1. StoreFieldTOS, LoadFieldTOS instructions:
+//    D = index of constant pool entry with FieldOffset or
+//    TypeArgumentsFieldOffset tags (instead of field offset in words).
+//
+// 2. EntryOptional instruction is revived in order to re-shuffle optional
+//    parameters. This DBC instruction was removed at
+//    https://github.com/dart-lang/sdk/commit/cf1de7d46cd88e204380e8f96a993439be56b24c
+//
+
+enum Opcode {
+  kTrap,
+  kNop,
+  kCompile,
+  kHotCheck,
+  kIntrinsic,
+  kDrop1,
+  kDropR,
+  kDrop,
+  kJump,
+  kReturn,
+  kReturnTOS,
+  kMove,
+  kSwap,
+  kPush,
+  kLoadConstant,
+  kLoadClassId,
+  kLoadClassIdTOS,
+  kPushConstant,
+  kStoreLocal,
+  kPopLocal,
+  kIndirectStaticCall,
+  kStaticCall,
+  kInstanceCall1,
+  kInstanceCall2,
+  kInstanceCall1Opt,
+  kInstanceCall2Opt,
+  kPushPolymorphicInstanceCall,
+  kPushPolymorphicInstanceCallByRange,
+  kNativeCall,
+  kOneByteStringFromCharCode,
+  kStringToCharCode,
+  kAddTOS,
+  kSubTOS,
+  kMulTOS,
+  kBitOrTOS,
+  kBitAndTOS,
+  kEqualTOS,
+  kLessThanTOS,
+  kGreaterThanTOS,
+  kSmiAddTOS,
+  kSmiSubTOS,
+  kSmiMulTOS,
+  kSmiBitAndTOS,
+  kAdd,
+  kSub,
+  kMul,
+  kDiv,
+  kMod,
+  kShl,
+  kShr,
+  kShlImm,
+  kNeg,
+  kBitOr,
+  kBitAnd,
+  kBitXor,
+  kBitNot,
+  kMin,
+  kMax,
+  kWriteIntoDouble,
+  kUnboxDouble,
+  kCheckedUnboxDouble,
+  kUnboxInt32,
+  kBoxInt32,
+  kBoxUint32,
+  kSmiToDouble,
+  kDoubleToSmi,
+  kDAdd,
+  kDSub,
+  kDMul,
+  kDDiv,
+  kDNeg,
+  kDSqrt,
+  kDMin,
+  kDMax,
+  kDCos,
+  kDSin,
+  kDPow,
+  kDMod,
+  kDTruncate,
+  kDFloor,
+  kDCeil,
+  kDoubleToFloat,
+  kFloatToDouble,
+  kDoubleIsNaN,
+  kDoubleIsInfinite,
+  kStoreStaticTOS,
+  kPushStatic,
+  kInitStaticTOS,
+  kIfNeStrictTOS,
+  kIfEqStrictTOS,
+  kIfNeStrictNumTOS,
+  kIfEqStrictNumTOS,
+  kIfSmiLtTOS,
+  kIfSmiLeTOS,
+  kIfSmiGeTOS,
+  kIfSmiGtTOS,
+  kIfNeStrict,
+  kIfEqStrict,
+  kIfLe,
+  kIfLt,
+  kIfGe,
+  kIfGt,
+  kIfULe,
+  kIfULt,
+  kIfUGe,
+  kIfUGt,
+  kIfDNe,
+  kIfDEq,
+  kIfDLe,
+  kIfDLt,
+  kIfDGe,
+  kIfDGt,
+  kIfNeStrictNum,
+  kIfEqStrictNum,
+  kIfEqNull,
+  kIfNeNull,
+  kCreateArrayTOS,
+  kCreateArrayOpt,
+  kAllocate,
+  kAllocateT,
+  kAllocateOpt,
+  kAllocateTOpt,
+  kStoreIndexedTOS,
+  kStoreIndexed,
+  kStoreIndexedUint8,
+  kStoreIndexedExternalUint8,
+  kStoreIndexedOneByteString,
+  kStoreIndexedUint32,
+  kStoreIndexedFloat32,
+  kStoreIndexed4Float32,
+  kStoreIndexedFloat64,
+  kStoreIndexed8Float64,
+  kNoSuchMethod,
+  kTailCall,
+  kTailCallOpt,
+  kLoadArgDescriptor,
+  kLoadArgDescriptorOpt,
+  kLoadFpRelativeSlot,
+  kLoadFpRelativeSlotOpt,
+  kStoreFpRelativeSlot,
+  kStoreFpRelativeSlotOpt,
+  kLoadIndexedTOS,
+  kLoadIndexed,
+  kLoadIndexedUint8,
+  kLoadIndexedInt8,
+  kLoadIndexedInt32,
+  kLoadIndexedUint32,
+  kLoadIndexedExternalUint8,
+  kLoadIndexedExternalInt8,
+  kLoadIndexedFloat32,
+  kLoadIndexed4Float32,
+  kLoadIndexedFloat64,
+  kLoadIndexed8Float64,
+  kLoadIndexedOneByteString,
+  kLoadIndexedTwoByteString,
+  kStoreField,
+  kStoreFieldExt,
+  kStoreFieldTOS,
+  kLoadField,
+  kLoadFieldExt,
+  kLoadUntagged,
+  kLoadFieldTOS,
+  kBooleanNegateTOS,
+  kBooleanNegate,
+  kThrow,
+  kEntry,
+  kEntryOptimized,
+  kFrame,
+  kSetFrame,
+  kAllocateContext,
+  kAllocateUninitializedContext,
+  kCloneContext,
+  kMoveSpecial,
+  kInstantiateType,
+  kInstantiateTypeArgumentsTOS,
+  kInstanceOf,
+  kBadTypeError,
+  kAssertAssignable,
+  kAssertSubtype,
+  kAssertBoolean,
+  kTestSmi,
+  kTestCids,
+  kCheckSmi,
+  kCheckEitherNonSmi,
+  kCheckClassId,
+  kCheckClassIdRange,
+  kCheckBitTest,
+  kCheckCids,
+  kCheckCidsByRange,
+  kCheckStack,
+  kCheckStackAlwaysExit,
+  kCheckFunctionTypeArgs,
+  kDebugStep,
+  kDebugBreak,
+  kDeopt,
+  kDeoptRewind,
+  kEntryOptional,
+}
+
+enum Encoding {
+  k0,
+  kA,
+  kAD,
+  kAX,
+  kD,
+  kX,
+  kABC,
+  kABY,
+  kT,
+}
+
+enum Operand {
+  none, // ignored / non-existent operand
+  imm, // immediate operand
+  lit, // constant literal from object pool
+  reg, // register (unsigned FP relative local)
+  xeg, // x-register (signed FP relative local)
+  tgt, // jump target relative to the PC of the current instruction
+}
+
+class Format {
+  final Encoding encoding;
+  final List<Operand> operands;
+  const Format(this.encoding, this.operands);
+}
+
+const Map<Opcode, Format> BytecodeFormats = const {
+  Opcode.kTrap: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kNop: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
+  Opcode.kCompile: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kHotCheck: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
+  Opcode.kIntrinsic: const Format(
+      Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
+  Opcode.kDrop1: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kDropR: const Format(
+      Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
+  Opcode.kDrop: const Format(
+      Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
+  Opcode.kJump: const Format(
+      Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
+  Opcode.kReturn: const Format(
+      Encoding.kA, const [Operand.reg, Operand.none, Operand.none]),
+  Opcode.kReturnTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kMove: const Format(
+      Encoding.kAX, const [Operand.reg, Operand.xeg, Operand.none]),
+  Opcode.kSwap: const Format(
+      Encoding.kAX, const [Operand.reg, Operand.xeg, Operand.none]),
+  Opcode.kPush: const Format(
+      Encoding.kX, const [Operand.xeg, Operand.none, Operand.none]),
+  Opcode.kLoadConstant: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.lit, Operand.none]),
+  Opcode.kLoadClassId: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kLoadClassIdTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kPushConstant: const Format(
+      Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
+  Opcode.kStoreLocal: const Format(
+      Encoding.kX, const [Operand.xeg, Operand.none, Operand.none]),
+  Opcode.kPopLocal: const Format(
+      Encoding.kX, const [Operand.xeg, Operand.none, Operand.none]),
+  Opcode.kIndirectStaticCall: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
+  Opcode.kStaticCall: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
+  Opcode.kInstanceCall1: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
+  Opcode.kInstanceCall2: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
+  Opcode.kInstanceCall1Opt: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
+  Opcode.kInstanceCall2Opt: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
+  Opcode.kPushPolymorphicInstanceCall: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
+  Opcode.kPushPolymorphicInstanceCallByRange: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
+  Opcode.kNativeCall: const Format(
+      Encoding.kABC, const [Operand.imm, Operand.imm, Operand.imm]),
+  Opcode.kOneByteStringFromCharCode: const Format(
+      Encoding.kAX, const [Operand.reg, Operand.xeg, Operand.none]),
+  Opcode.kStringToCharCode: const Format(
+      Encoding.kAX, const [Operand.reg, Operand.xeg, Operand.none]),
+  Opcode.kAddTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kSubTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kMulTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kBitOrTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kBitAndTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kEqualTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kLessThanTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kGreaterThanTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kSmiAddTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kSmiSubTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kSmiMulTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kSmiBitAndTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kAdd: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kSub: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kMul: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kDiv: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kMod: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kShl: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kShr: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kShlImm: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.imm]),
+  Opcode.kNeg: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kBitOr: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kBitAnd: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kBitXor: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kBitNot: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kMin: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kMax: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kWriteIntoDouble: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kUnboxDouble: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kCheckedUnboxDouble: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kUnboxInt32: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.imm]),
+  Opcode.kBoxInt32: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kBoxUint32: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kSmiToDouble: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kDoubleToSmi: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kDAdd: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kDSub: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kDMul: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kDDiv: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kDNeg: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kDSqrt: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kDMin: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kDMax: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kDCos: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kDSin: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kDPow: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kDMod: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kDTruncate: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kDFloor: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kDCeil: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kDoubleToFloat: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kFloatToDouble: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kDoubleIsNaN: const Format(
+      Encoding.kA, const [Operand.reg, Operand.none, Operand.none]),
+  Opcode.kDoubleIsInfinite: const Format(
+      Encoding.kA, const [Operand.reg, Operand.none, Operand.none]),
+  Opcode.kStoreStaticTOS: const Format(
+      Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
+  Opcode.kPushStatic: const Format(
+      Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
+  Opcode.kInitStaticTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kIfNeStrictTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kIfEqStrictTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kIfNeStrictNumTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kIfEqStrictNumTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kIfSmiLtTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kIfSmiLeTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kIfSmiGeTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kIfSmiGtTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kIfNeStrict: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfEqStrict: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfLe: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfLt: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfGe: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfGt: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfULe: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfULt: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfUGe: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfUGt: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfDNe: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfDEq: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfDLe: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfDLt: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfDGe: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfDGt: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfNeStrictNum: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfEqStrictNum: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kIfEqNull: const Format(
+      Encoding.kA, const [Operand.reg, Operand.none, Operand.none]),
+  Opcode.kIfNeNull: const Format(
+      Encoding.kA, const [Operand.reg, Operand.none, Operand.none]),
+  Opcode.kCreateArrayTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kCreateArrayOpt: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kAllocate: const Format(
+      Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
+  Opcode.kAllocateT: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kAllocateOpt: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.lit, Operand.none]),
+  Opcode.kAllocateTOpt: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.lit, Operand.none]),
+  Opcode.kStoreIndexedTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kStoreIndexed: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kStoreIndexedUint8: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kStoreIndexedExternalUint8: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kStoreIndexedOneByteString: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kStoreIndexedUint32: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kStoreIndexedFloat32: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kStoreIndexed4Float32: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kStoreIndexedFloat64: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kStoreIndexed8Float64: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kNoSuchMethod: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kTailCall: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kTailCallOpt: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kLoadArgDescriptor: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kLoadArgDescriptorOpt: const Format(
+      Encoding.kA, const [Operand.reg, Operand.none, Operand.none]),
+  Opcode.kLoadFpRelativeSlot: const Format(
+      Encoding.kX, const [Operand.reg, Operand.none, Operand.none]),
+  Opcode.kLoadFpRelativeSlotOpt: const Format(
+      Encoding.kABY, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kStoreFpRelativeSlot: const Format(
+      Encoding.kX, const [Operand.reg, Operand.none, Operand.none]),
+  Opcode.kStoreFpRelativeSlotOpt: const Format(
+      Encoding.kABY, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kLoadIndexedTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kLoadIndexed: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kLoadIndexedUint8: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kLoadIndexedInt8: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kLoadIndexedInt32: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kLoadIndexedUint32: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kLoadIndexedExternalUint8: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kLoadIndexedExternalInt8: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kLoadIndexedFloat32: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kLoadIndexed4Float32: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kLoadIndexedFloat64: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kLoadIndexed8Float64: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kLoadIndexedOneByteString: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kLoadIndexedTwoByteString: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]),
+  Opcode.kStoreField: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.imm, Operand.reg]),
+  Opcode.kStoreFieldExt: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kStoreFieldTOS: const Format(
+      Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
+  Opcode.kLoadField: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.imm]),
+  Opcode.kLoadFieldExt: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kLoadUntagged: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.reg, Operand.imm]),
+  Opcode.kLoadFieldTOS: const Format(
+      Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
+  Opcode.kBooleanNegateTOS: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kBooleanNegate: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kThrow: const Format(
+      Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
+  Opcode.kEntry: const Format(
+      Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
+  Opcode.kEntryOptimized: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
+  Opcode.kFrame: const Format(
+      Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
+  Opcode.kSetFrame: const Format(
+      Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
+  Opcode.kAllocateContext: const Format(
+      Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
+  Opcode.kAllocateUninitializedContext: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.imm, Operand.none]),
+  Opcode.kCloneContext: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kMoveSpecial: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.imm, Operand.none]),
+  Opcode.kInstantiateType: const Format(
+      Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
+  Opcode.kInstantiateTypeArgumentsTOS: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
+  Opcode.kInstanceOf: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kBadTypeError: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kAssertAssignable: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
+  Opcode.kAssertSubtype: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kAssertBoolean: const Format(
+      Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
+  Opcode.kTestSmi: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kTestCids: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.imm, Operand.none]),
+  Opcode.kCheckSmi: const Format(
+      Encoding.kA, const [Operand.reg, Operand.none, Operand.none]),
+  Opcode.kCheckEitherNonSmi: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]),
+  Opcode.kCheckClassId: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.imm, Operand.none]),
+  Opcode.kCheckClassIdRange: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.imm, Operand.none]),
+  Opcode.kCheckBitTest: const Format(
+      Encoding.kAD, const [Operand.reg, Operand.imm, Operand.none]),
+  Opcode.kCheckCids: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.imm, Operand.imm]),
+  Opcode.kCheckCidsByRange: const Format(
+      Encoding.kABC, const [Operand.reg, Operand.imm, Operand.imm]),
+  Opcode.kCheckStack: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kCheckStackAlwaysExit: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kCheckFunctionTypeArgs: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
+  Opcode.kDebugStep: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kDebugBreak: const Format(
+      Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
+  Opcode.kDeopt: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
+  Opcode.kDeoptRewind: const Format(
+      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kEntryOptional: const Format(
+      Encoding.kABC, const [Operand.imm, Operand.imm, Operand.imm]),
+};
+
+// Should match constant in runtime/vm/stack_frame_dbc.h.
+const int kParamEndSlotFromFp = 4;
+
+// Prefix used to distinguish getters in ICData target names.
+// Should match constant in runtime/vm/object.cc.
+const String kGetterPrefix = 'get:';
+
+// Prefix used to distinguish setters in ICData target names.
+// Should match constant in runtime/vm/object.cc.
+const String kSetterPrefix = 'set:';
diff --git a/pkg/vm/lib/bytecode/disassembler.dart b/pkg/vm/lib/bytecode/disassembler.dart
new file mode 100644
index 0000000..9230268
--- /dev/null
+++ b/pkg/vm/lib/bytecode/disassembler.dart
@@ -0,0 +1,165 @@
+// 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.
+
+library vm.bytecode.disassembler;
+
+import 'dart:typed_data';
+
+import 'package:vm/bytecode/dbc.dart';
+
+class _Instruction {
+  final Opcode opcode;
+  final List<int> operands;
+  _Instruction(this.opcode, this.operands);
+}
+
+class BytecodeDisassembler {
+  static const int kOpcodeMask = 0xFF;
+  static const int kBitsPerInt = 64;
+
+  List<_Instruction> _instructions;
+  int _labelCount;
+  Map<int, int> _labels;
+
+  String disassemble(List<int> bytecode) {
+    _init(bytecode);
+    _scanForJumpTargets();
+    return _disasm();
+  }
+
+  void _init(List<int> bytecode) {
+    final uint8list = new Uint8List.fromList(bytecode);
+    // TODO(alexmarkov): endianness?
+    Uint32List words = uint8list.buffer.asUint32List();
+
+    _instructions = new List<_Instruction>(words.length);
+    for (int i = 0; i < words.length; i++) {
+      _instructions[i] = _decodeInstruction(words[i]);
+    }
+
+    _labelCount = 0;
+    _labels = <int, int>{};
+  }
+
+  _Instruction _decodeInstruction(int word) {
+    final opcode = Opcode.values[word & kOpcodeMask];
+    final format = BytecodeFormats[opcode];
+    return new _Instruction(opcode, _decodeOperands(format, word));
+  }
+
+  List<int> _decodeOperands(Format format, int word) {
+    switch (format.encoding) {
+      case Encoding.k0:
+        return const [];
+      case Encoding.kA:
+        return [_unsigned(word, 8, 8)];
+      case Encoding.kAD:
+        return [_unsigned(word, 8, 8), _unsigned(word, 16, 16)];
+      case Encoding.kAX:
+        return [_unsigned(word, 8, 8), _signed(word, 16, 16)];
+      case Encoding.kD:
+        return [_unsigned(word, 16, 16)];
+      case Encoding.kX:
+        return [_signed(word, 16, 16)];
+      case Encoding.kABC:
+        return [
+          _unsigned(word, 8, 8),
+          _unsigned(word, 16, 8),
+          _unsigned(word, 24, 8)
+        ];
+      case Encoding.kABY:
+        return [
+          _unsigned(word, 8, 8),
+          _unsigned(word, 16, 8),
+          _signed(word, 24, 8)
+        ];
+      case Encoding.kT:
+        return [_signed(word, 8, 24)];
+    }
+    throw 'Unexpected format $format';
+  }
+
+  int _unsigned(int word, int pos, int bits) =>
+      (word >> pos) & ((1 << bits) - 1);
+
+  int _signed(int word, int pos, int bits) =>
+      _unsigned(word, pos, bits) <<
+      (kBitsPerInt - bits) >>
+      (kBitsPerInt - bits);
+
+  void _scanForJumpTargets() {
+    for (int i = 0; i < _instructions.length; i++) {
+      final instr = _instructions[i];
+      if (instr.opcode == Opcode.kJump) {
+        final target = i + instr.operands[0];
+        assert(0 <= target && target < _instructions.length);
+        _labels[target] ??= (++_labelCount);
+      }
+    }
+  }
+
+  String _disasm() {
+    StringBuffer out = new StringBuffer();
+    for (int i = 0; i < _instructions.length; i++) {
+      int label = _labels[i];
+      if (label != null) {
+        out.writeln('L$label:');
+      }
+      _writeInstruction(out, i, _instructions[i]);
+    }
+    return out.toString();
+  }
+
+  void _writeInstruction(StringBuffer out, int bci, _Instruction instr) {
+    final format = BytecodeFormats[instr.opcode];
+    assert(format != null);
+
+    out.write('  ');
+
+    const int kOpcodeWidth = 20;
+    const String kOpcodePrefix = 'Opcode.k';
+
+    String opcode = instr.opcode.toString();
+    assert(opcode.startsWith(kOpcodePrefix));
+    opcode = opcode.substring(kOpcodePrefix.length);
+
+    if (instr.operands.isEmpty) {
+      out.writeln(opcode);
+      return;
+    }
+
+    out.write(opcode.padRight(kOpcodeWidth));
+
+    for (int i = 0; i < instr.operands.length; i++) {
+      if (i == 0) {
+        out.write(' ');
+      } else {
+        out.write(', ');
+      }
+      final operand =
+          _formatOperand(bci, format.operands[i], instr.operands[i]);
+      out.write(operand);
+    }
+
+    out.writeln();
+  }
+
+  String _formatOperand(int bci, Operand fmt, int value) {
+    switch (fmt) {
+      case Operand.none:
+        break;
+      case Operand.imm:
+        return '$value';
+      case Operand.lit:
+        return 'CP#$value';
+      case Operand.reg:
+        return 'r$value';
+      case Operand.xeg:
+        return (value < 0) ? 'FP[$value]' : 'r$value';
+      case Operand.tgt:
+        return 'L${_labels[bci + value] ?? (throw 'Label not found')}';
+    }
+    throw 'Unexpected operand format $fmt';
+  }
+}
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
new file mode 100644
index 0000000..1fd4ebe
--- /dev/null
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -0,0 +1,1332 @@
+// 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.
+
+library vm.bytecode.gen_bytecode;
+
+import 'package:kernel/ast.dart' hide MapEntry;
+import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
+import 'package:kernel/core_types.dart' show CoreTypes;
+import 'package:kernel/library_index.dart' show LibraryIndex;
+import 'package:kernel/transformations/constants.dart'
+    show ConstantEvaluator, ConstantsBackend, EvaluationEnvironment;
+import 'package:kernel/type_algebra.dart' show Substitution;
+import 'package:kernel/type_environment.dart' show TypeEnvironment;
+import 'package:kernel/vm/constants_native_effects.dart'
+    show VmConstantsBackend;
+import 'package:vm/bytecode/assembler.dart';
+import 'package:vm/bytecode/constant_pool.dart';
+import 'package:vm/bytecode/dbc.dart';
+import 'package:vm/bytecode/local_vars.dart' show LocalVariables;
+import 'package:vm/metadata/bytecode.dart';
+
+/// Flag to toggle generation of bytecode in kernel files.
+const bool kEnableKernelBytecode = false;
+
+/// Flag to toggle generation of bytecode in platform kernel files.
+const bool kEnableKernelBytecodeForPlatform = kEnableKernelBytecode;
+
+const bool kTrace = false;
+
+void generateBytecode(Component component, {bool strongMode: true}) {
+  final coreTypes = new CoreTypes(component);
+  void ignoreAmbiguousSupertypes(Class cls, Supertype a, Supertype b) {}
+  final hierarchy = new ClassHierarchy(component,
+      onAmbiguousSupertypes: ignoreAmbiguousSupertypes);
+  final typeEnvironment =
+      new TypeEnvironment(coreTypes, hierarchy, strongMode: strongMode);
+  final constantsBackend = new VmConstantsBackend(null, coreTypes);
+  new BytecodeGenerator(component, coreTypes, hierarchy, typeEnvironment,
+          constantsBackend, strongMode)
+      .visitComponent(component);
+}
+
+class BytecodeGenerator extends RecursiveVisitor<Null> {
+  final Component component;
+  final CoreTypes coreTypes;
+  final ClassHierarchy hierarchy;
+  final TypeEnvironment typeEnvironment;
+  final ConstantsBackend constantsBackend;
+  final bool strongMode;
+  final BytecodeMetadataRepository metadata = new BytecodeMetadataRepository();
+
+  Class enclosingClass;
+  Member enclosingMember;
+  BytecodeAssembler asm;
+  ConstantPool cp;
+  LocalVariables locals;
+  ConstantEmitter constantEmitter;
+  ConstantEvaluator constantEvaluator;
+  Map<LabeledStatement, Label> labeledStatements;
+  Map<SwitchCase, Label> switchCases;
+
+  BytecodeGenerator(this.component, this.coreTypes, this.hierarchy,
+      this.typeEnvironment, this.constantsBackend, this.strongMode) {
+    component.addMetadataRepository(metadata);
+  }
+
+  @override
+  visitComponent(Component node) => node.visitChildren(this);
+
+  @override
+  visitLibrary(Library node) {
+    if (node.isExternal) {
+      return;
+    }
+    visitList(node.classes, this);
+    visitList(node.procedures, this);
+    visitList(node.fields, this);
+  }
+
+  @override
+  visitClass(Class node) {
+    visitList(node.constructors, this);
+    visitList(node.procedures, this);
+    visitList(node.fields, this);
+  }
+
+  @override
+  defaultMember(Member node) {
+    if (node.isAbstract) {
+      return;
+    }
+    try {
+      if (node is Field) {
+        if (node.isStatic && node.initializer != null) {
+          start(node);
+          if (node.isConst) {
+            _genPushConstExpr(node.initializer);
+          } else {
+            node.initializer.accept(this);
+          }
+          _genReturnTOS();
+          end(node);
+        }
+      } else if ((node is Procedure && !node.isRedirectingFactoryConstructor) ||
+          (node is Constructor)) {
+        start(node);
+        if (node is Constructor) {
+          _genConstructorInitializers(node);
+        }
+        node.function?.body?.accept(this);
+        // TODO(alexmarkov): figure out when 'return null' should be generated.
+        _genPushNull();
+        _genReturnTOS();
+        end(node);
+      }
+    } on UnsupportedOperationError catch (e) {
+      if (kTrace) {
+        print('Unable to generate bytecode for $node: $e');
+      }
+    }
+  }
+
+  LibraryIndex _libraryIndex;
+  LibraryIndex get libraryIndex =>
+      _libraryIndex ??= new LibraryIndex.coreLibraries(component);
+
+  Procedure _listFromLiteral;
+  Procedure get listFromLiteral => _listFromLiteral ??=
+      libraryIndex.getMember('dart:core', 'List', '_fromLiteral');
+
+  Procedure _mapFromLiteral;
+  Procedure get mapFromLiteral => _mapFromLiteral ??=
+      libraryIndex.getMember('dart:core', 'Map', '_fromLiteral');
+
+  Procedure _interpolateSingle;
+  Procedure get interpolateSingle => _interpolateSingle ??=
+      libraryIndex.getMember('dart:core', '_StringBase', '_interpolateSingle');
+
+  Procedure _interpolate;
+  Procedure get interpolate => _interpolate ??=
+      libraryIndex.getMember('dart:core', '_StringBase', '_interpolate');
+
+  void _genConstructorInitializers(Constructor node) {
+    bool isRedirecting =
+        node.initializers.any((init) => init is RedirectingInitializer);
+    if (!isRedirecting) {
+      for (var field in node.enclosingClass.fields) {
+        if (!field.isStatic &&
+            field.initializer != null &&
+            !node.initializers.any(
+                (init) => init is FieldInitializer && init.field == field)) {
+          _genFieldInitializer(field, field.initializer);
+        }
+      }
+    }
+    visitList(node.initializers, this);
+  }
+
+  void _genFieldInitializer(Field field, Expression initializer) {
+    if (initializer is NullLiteral) {
+      return;
+    }
+
+    asm.emitPush(locals.thisVarIndex);
+    initializer.accept(this);
+
+    // TODO(alexmarkov): field guards?
+    // TODO(alexmarkov): assignability check
+
+    final int cpIndex = cp.add(new ConstantFieldOffset(field));
+    asm.emitStoreFieldTOS(cpIndex);
+  }
+
+  void _genArguments(Expression receiver, Arguments arguments) {
+    if (arguments.types.isNotEmpty) {
+      _genTypeArguments(arguments.types);
+    }
+    receiver?.accept(this);
+    visitList(arguments.positional, this);
+    arguments.named.forEach((NamedExpression ne) => ne.value.accept(this));
+  }
+
+  void _genPushNull() {
+    final cpIndex = cp.add(const ConstantNull());
+    asm.emitPushConstant(cpIndex);
+  }
+
+  void _genPushInt(int value) {
+    int cpIndex = cp.add(new ConstantInt(value));
+    asm.emitPushConstant(cpIndex);
+  }
+
+  void _genPushConstExpr(Expression expr) {
+    final constant = constantEvaluator.evaluate(expr);
+    asm.emitPushConstant(constant.accept(constantEmitter));
+  }
+
+  void _genReturnTOS() {
+    asm.emitReturnTOS();
+  }
+
+  void _genStaticCall(
+      Member target, ConstantArgDesc argDesc, int totalArgCount) {
+    final argDescIndex = cp.add(argDesc);
+    final icdataIndex = cp.add(new ConstantStaticICData(target, argDescIndex));
+
+    asm.emitPushConstant(icdataIndex);
+    asm.emitIndirectStaticCall(totalArgCount, argDescIndex);
+  }
+
+  void _genStaticCallWithArgs(Member target, Arguments args,
+      {bool hasReceiver: false, bool alwaysPassTypeArgs: false}) {
+    final ConstantArgDesc argDesc =
+        new ConstantArgDesc.fromArguments(args, hasReceiver: hasReceiver);
+
+    int totalArgCount = args.positional.length + args.named.length;
+    if (hasReceiver) {
+      totalArgCount++;
+    }
+    if (args.types.isNotEmpty || alwaysPassTypeArgs) {
+      totalArgCount++;
+    }
+
+    _genStaticCall(target, argDesc, totalArgCount);
+  }
+
+  bool hasTypeParameters(List<DartType> typeArgs) {
+    final findTypeParams = new FindTypeParametersVisitor();
+    return typeArgs.any((t) => t.accept(findTypeParams));
+  }
+
+  bool hasInstantiatorTypeArguments(Class c) {
+    return c.typeParameters.isNotEmpty ||
+        (c.superclass != null && hasInstantiatorTypeArguments(c.superclass));
+  }
+
+  bool isGenericFunction(Member member) {
+    final function = member.function;
+    return function != null && function.typeParameters.isNotEmpty;
+  }
+
+  void _genTypeArguments(List<DartType> typeArgs) {
+    final int typeArgsCPIndex = cp.add(new ConstantTypeArguments(typeArgs));
+    if (typeArgs.isEmpty || !hasTypeParameters(typeArgs)) {
+      asm.emitPushConstant(typeArgsCPIndex);
+    } else {
+      // TODO(alexmarkov): try to reuse instantiator type arguments
+      // TODO(alexmarkov): do not load instantiator type arguments / function type
+      // arguments if they are not needed for these particular [typeArgs].
+      _genPushInstantiatorTypeArguments();
+      _genPushFunctionTypeArguments();
+      asm.emitInstantiateTypeArgumentsTOS(1, typeArgsCPIndex);
+    }
+  }
+
+  void _genPushInstantiatorTypeArguments() {
+    // TODO(alexmarkov): access from closures to up-level type arguments.
+    if ((enclosingMember.isInstanceMember || enclosingMember is Constructor) &&
+        hasInstantiatorTypeArguments(enclosingClass)) {
+      asm.emitPush(locals.thisVarIndex);
+      final int cpIndex =
+          cp.add(new ConstantTypeArgumentsFieldOffset(enclosingClass));
+      asm.emitLoadFieldTOS(cpIndex);
+    } else {
+      _genPushNull();
+    }
+  }
+
+  void _genPushFunctionTypeArguments() {
+    // TODO(alexmarkov): closures
+    if (isGenericFunction(enclosingMember)) {
+      asm.emitPush(locals.functionTypeArgsVarIndex);
+    } else {
+      _genPushNull();
+    }
+  }
+
+  List<DartType> _flattenTypeArgumentsForInstantiation(
+      Class instantiatedClass, List<DartType> typeArgs) {
+    assert(typeArgs.length == instantiatedClass.typeParameters.length);
+
+    List<DartType> flatTypeArgs;
+    final supertype = instantiatedClass.supertype;
+    if (supertype == null) {
+      flatTypeArgs = <DartType>[];
+    } else {
+      final substitution =
+          Substitution.fromPairs(instantiatedClass.typeParameters, typeArgs);
+      flatTypeArgs = _flattenTypeArgumentsForInstantiation(supertype.classNode,
+          substitution.substituteSupertype(supertype).typeArguments);
+    }
+    flatTypeArgs.addAll(typeArgs);
+    return flatTypeArgs;
+  }
+
+  /// Generates bool condition. Returns `true` if condition is negated.
+  bool _genCondition(Node condition) {
+    bool negated = false;
+    if (condition is Not) {
+      condition = (condition as Not).operand;
+      negated = true;
+    }
+    condition.accept(this);
+    // TODO(alexmarkov): bool check
+    return negated;
+  }
+
+  void _genJumpIfFalse(bool negated, Label dest) {
+    asm.emitPushConstant(cp.add(new ConstantBool(true)));
+    if (negated) {
+      asm.emitIfEqStrictTOS(); // if ((!condition) == true) ...
+    } else {
+      asm.emitIfNeStrictTOS(); // if (condition != true) ...
+    }
+    asm.emitJump(dest); // ... then jump dest
+  }
+
+  // Duplicates value on top of the stack using temporary variable
+  // corresponding to [node].
+  void _genDupTOS(TreeNode node) {
+    // TODO(alexmarkov): Consider introducing Dup bytecode or keeping track of
+    // expression stack depth.
+    final int temp = locals.tempIndex(node);
+    asm.emitStoreLocal(temp);
+    asm.emitPush(temp);
+  }
+
+  void start(Member node) {
+    enclosingMember = node;
+    enclosingClass = node.enclosingClass;
+    asm = new BytecodeAssembler();
+    cp = new ConstantPool();
+    locals = new LocalVariables();
+    constantEmitter = new ConstantEmitter(cp);
+    // TODO(alexmarkov): improve caching in ConstantEvaluator and reuse it
+    constantEvaluator = new ConstantEvaluator(constantsBackend, typeEnvironment,
+        coreTypes, strongMode, /* enableAsserts = */ true)
+      ..env = new EvaluationEnvironment();
+    labeledStatements = <LabeledStatement, Label>{};
+    switchCases = <SwitchCase, Label>{};
+
+    node.accept(locals);
+
+    if (locals.hasOptionalParameters) {
+      final function = node.function;
+      final int numOptionalPositional = function.positionalParameters.length -
+          function.requiredParameterCount;
+      final int numOptionalNamed = function.namedParameters.length;
+      final int numFixed =
+          locals.numParameters - (numOptionalPositional + numOptionalNamed);
+
+      asm.emitEntryOptional(numFixed, numOptionalPositional, numOptionalNamed);
+
+      if (numOptionalPositional != 0) {
+        assert(numOptionalNamed == 0);
+        for (int i = 0; i < numOptionalPositional; i++) {
+          final param = function
+              .positionalParameters[function.requiredParameterCount + i];
+          asm.emitLoadConstant(numFixed + i, _getDefaultParamConstIndex(param));
+        }
+      } else {
+        assert(numOptionalNamed != 0);
+        for (int i = 0; i < numOptionalNamed; i++) {
+          final param = function.namedParameters[i];
+          asm.emitLoadConstant(
+              numFixed + i, cp.add(new ConstantString(param.name)));
+          asm.emitLoadConstant(numFixed + i, _getDefaultParamConstIndex(param));
+        }
+      }
+
+      asm.emitFrame(locals.frameSize - locals.numParameters);
+    } else {
+      asm.emitEntry(locals.frameSize);
+    }
+    asm.emitCheckStack();
+
+    // TODO(alexmarkov): add type checks for parameters
+  }
+
+  int _getDefaultParamConstIndex(VariableDeclaration param) {
+    if (param.initializer == null) {
+      return cp.add(const ConstantNull());
+    }
+    final constant = constantEvaluator.evaluate(param.initializer);
+    return constant.accept(constantEmitter);
+  }
+
+  void _genJumpIfTrue(bool negated, Label dest) {
+    _genJumpIfFalse(!negated, dest);
+  }
+
+  void end(Member node) {
+    enclosingMember = null;
+    enclosingClass = null;
+    metadata.mapping[node] = new BytecodeMetadata(asm.bytecode, cp);
+    if (kTrace) {
+      print('Generated bytecode for $node');
+    }
+  }
+
+  @override
+  defaultTreeNode(Node node) => throw new UnsupportedOperationError(
+      'Unsupported node ${node.runtimeType}');
+
+  @override
+  visitAsExpression(AsExpression node) {
+    node.operand.accept(this);
+
+    if (node.type == const DynamicType()) {
+      return;
+    }
+    if (node.isTypeError) {
+      // TODO(alexmarkov): type checks
+      return;
+    }
+    if (hasTypeParameters([node.type])) {
+      // TODO(alexmarkov): do not load instantiator type arguments / function
+      // type arguments if they are not needed for this particular type.
+      _genPushInstantiatorTypeArguments();
+      _genPushFunctionTypeArguments();
+    } else {
+      _genPushNull(); // Instantiator type arguments.
+      _genPushNull(); // Function type arguments.
+    }
+    final typeIndex = cp.add(new ConstantType(node.type));
+    asm.emitPushConstant(typeIndex);
+    final argDescIndex = cp.add(new ConstantArgDesc(4));
+    final icdataIndex = cp.add(new ConstantICData('_as', argDescIndex));
+    asm.emitInstanceCall1(4, icdataIndex);
+  }
+
+  @override
+  visitBoolLiteral(BoolLiteral node) {
+    final cpIndex = cp.add(new ConstantBool.fromLiteral(node));
+    asm.emitPushConstant(cpIndex);
+  }
+
+  @override
+  visitIntLiteral(IntLiteral node) {
+    final cpIndex = cp.add(new ConstantInt.fromLiteral(node));
+    asm.emitPushConstant(cpIndex);
+  }
+
+  @override
+  visitDoubleLiteral(DoubleLiteral node) {
+    final cpIndex = cp.add(new ConstantDouble.fromLiteral(node));
+    asm.emitPushConstant(cpIndex);
+  }
+
+  @override
+  visitConditionalExpression(ConditionalExpression node) {
+    final Label otherwisePart = new Label();
+    final Label done = new Label();
+    final int temp = locals.tempIndex(node);
+
+    final bool negated = _genCondition(node.condition);
+    _genJumpIfFalse(negated, otherwisePart);
+
+    node.then.accept(this);
+    asm.emitPopLocal(temp);
+    asm.emitJump(done);
+
+    asm.bind(otherwisePart);
+    node.otherwise.accept(this);
+    asm.emitPopLocal(temp);
+
+    asm.bind(done);
+    asm.emitPush(temp);
+  }
+
+  @override
+  visitConstructorInvocation(ConstructorInvocation node) {
+    if (node.isConst) {
+      _genPushConstExpr(node);
+      return;
+    }
+
+    final constructedClass = node.constructedType.classNode;
+    final classIndex = cp.add(new ConstantClass(constructedClass));
+
+    if (hasInstantiatorTypeArguments(constructedClass)) {
+      List<DartType> flatTypeArgs = _flattenTypeArgumentsForInstantiation(
+          constructedClass, node.arguments.types);
+      _genTypeArguments(flatTypeArgs);
+      asm.emitPushConstant(cp.add(new ConstantClass(constructedClass)));
+      asm.emitAllocateT();
+    } else {
+      assert(node.arguments.types.isEmpty);
+      asm.emitAllocate(classIndex);
+    }
+
+    _genDupTOS(node);
+
+    // Remove type arguments as they are only passed to instance allocation,
+    // and not passed to a constructor.
+    final args =
+        new Arguments(node.arguments.positional, named: node.arguments.named);
+    _genArguments(null, args);
+    _genStaticCallWithArgs(node.target, args, hasReceiver: true);
+    asm.emitDrop1();
+  }
+
+//  @override
+//  visitDirectMethodInvocation(DirectMethodInvocation node) {
+//  }
+
+  @override
+  visitDirectPropertyGet(DirectPropertyGet node) {
+    node.receiver.accept(this);
+    final target = node.target;
+    if (target is Field || (target is Procedure && target.isGetter)) {
+      _genStaticCall(target, new ConstantArgDesc(1), 1);
+    } else {
+      throw new UnsupportedOperationError(
+          'Unsupported DirectPropertyGet with ${target.runtimeType} $target');
+    }
+  }
+
+//  @override
+//  visitDirectPropertySet(DirectPropertySet node) {
+//  }
+//
+//  @override
+//  visitFunctionExpression(FunctionExpression node) {
+//  }
+//
+//  @override
+//  visitInstantiation(Instantiation node) {
+//  }
+//
+//  @override
+//  visitInvalidExpression(InvalidExpression node) {
+//  }
+
+  @override
+  visitIsExpression(IsExpression node) {
+    node.operand.accept(this);
+
+    // TODO(alexmarkov): generate _simpleInstanceOf if possible
+
+    if (hasTypeParameters([node.type])) {
+      // TODO(alexmarkov): do not load instantiator type arguments / function type
+      // arguments if they are not needed for this particular type.
+      _genPushInstantiatorTypeArguments();
+      _genPushFunctionTypeArguments();
+    } else {
+      _genPushNull(); // Instantiator type arguments.
+      _genPushNull(); // Function type arguments.
+    }
+    final typeIndex = cp.add(new ConstantType(node.type));
+    asm.emitPushConstant(typeIndex);
+    final argDescIndex = cp.add(new ConstantArgDesc(4));
+    final icdataIndex = cp.add(new ConstantICData('_instanceOf', argDescIndex));
+    asm.emitInstanceCall1(4, icdataIndex);
+  }
+
+  @override
+  visitLet(Let node) {
+    node.variable.accept(this);
+    node.body.accept(this);
+  }
+
+  @override
+  visitListLiteral(ListLiteral node) {
+    if (node.isConst) {
+      _genPushConstExpr(node);
+      return;
+    }
+
+    _genTypeArguments([node.typeArgument]);
+
+    _genDupTOS(node);
+
+    // TODO(alexmarkov): gen more efficient code for empty array
+    _genPushInt(node.expressions.length);
+    asm.emitCreateArrayTOS();
+    final int temp = locals.tempIndex(node);
+    asm.emitStoreLocal(temp);
+
+    for (int i = 0; i < node.expressions.length; i++) {
+      asm.emitPush(temp);
+      _genPushInt(i);
+      node.expressions[i].accept(this);
+      // TODO(alexmarkov): assignable check
+      asm.emitStoreIndexedTOS();
+    }
+
+    _genStaticCall(listFromLiteral, new ConstantArgDesc(1, numTypeArgs: 1), 2);
+  }
+
+  @override
+  visitLogicalExpression(LogicalExpression node) {
+    assert(node.operator == '||' || node.operator == '&&');
+
+    final Label shortCircuit = new Label();
+    final Label done = new Label();
+    final int temp = locals.tempIndex(node);
+    final isOR = (node.operator == '||');
+
+    bool negated = _genCondition(node.left);
+    asm.emitPushConstant(cp.add(new ConstantBool(true)));
+    if (negated != isOR) {
+      // OR: if (condition == true)
+      // AND: if ((!condition) == true)
+      asm.emitIfEqStrictTOS();
+    } else {
+      // OR: if ((!condition) != true)
+      // AND: if (condition != true)
+      asm.emitIfNeStrictTOS();
+    }
+    asm.emitJump(shortCircuit);
+
+    negated = _genCondition(node.right);
+    if (negated) {
+      asm.emitBooleanNegateTOS();
+    }
+    asm.emitPopLocal(temp);
+    asm.emitJump(done);
+
+    asm.bind(shortCircuit);
+    asm.emitPushConstant(cp.add(new ConstantBool(isOR)));
+    asm.emitPopLocal(temp);
+
+    asm.bind(done);
+    asm.emitPush(temp);
+  }
+
+  @override
+  visitMapLiteral(MapLiteral node) {
+    if (node.isConst) {
+      _genPushConstExpr(node);
+      return;
+    }
+
+    _genTypeArguments([node.keyType, node.valueType]);
+
+    if (node.entries.isEmpty) {
+      asm.emitPushConstant(
+          cp.add(new ConstantList(const DynamicType(), const [])));
+    } else {
+      _genTypeArguments([const DynamicType()]);
+      _genPushInt(node.entries.length * 2);
+      asm.emitCreateArrayTOS();
+
+      final int temp = locals.tempIndex(node);
+      asm.emitStoreLocal(temp);
+
+      for (int i = 0; i < node.entries.length; i++) {
+        // key
+        asm.emitPush(temp);
+        _genPushInt(i * 2);
+        node.entries[i].key.accept(this);
+        asm.emitStoreIndexedTOS();
+        // value
+        asm.emitPush(temp);
+        _genPushInt(i * 2 + 1);
+        node.entries[i].value.accept(this);
+        asm.emitStoreIndexedTOS();
+      }
+    }
+
+    _genStaticCall(mapFromLiteral, new ConstantArgDesc(1, numTypeArgs: 1), 2);
+  }
+
+  @override
+  visitMethodInvocation(MethodInvocation node) {
+    final args = node.arguments;
+    _genArguments(node.receiver, args);
+    // TODO(alexmarkov): fast path smi ops
+    final argDescIndex =
+        cp.add(new ConstantArgDesc.fromArguments(args, hasReceiver: true));
+    final icdataIndex =
+        cp.add(new ConstantICData(node.name.name, argDescIndex));
+    // TODO(alexmarkov): figure out when generate InstanceCall2 (2 checked arguments).
+    asm.emitInstanceCall1(
+        args.positional.length + args.named.length + 1, icdataIndex);
+  }
+
+  @override
+  visitPropertyGet(PropertyGet node) {
+    node.receiver.accept(this);
+    final argDescIndex = cp.add(new ConstantArgDesc(1));
+    final icdataIndex = cp.add(
+        new ConstantICData('$kGetterPrefix${node.name.name}', argDescIndex));
+    asm.emitInstanceCall1(1, icdataIndex);
+  }
+
+  @override
+  visitPropertySet(PropertySet node) {
+    final int temp = locals.tempIndex(node);
+    node.receiver.accept(this);
+    node.value.accept(this);
+    asm.emitStoreLocal(temp);
+    final argDescIndex = cp.add(new ConstantArgDesc(2));
+    final icdataIndex = cp.add(
+        new ConstantICData('$kSetterPrefix${node.name.name}', argDescIndex));
+    asm.emitInstanceCall1(2, icdataIndex);
+    asm.emitDrop1();
+    asm.emitPush(temp);
+  }
+
+  @override
+  visitSuperMethodInvocation(SuperMethodInvocation node) {
+    final args = node.arguments;
+    _genArguments(new ThisExpression(), args);
+    Member target =
+        hierarchy.getDispatchTarget(enclosingClass.superclass, node.name);
+    if (target == null) {
+      throw new UnsupportedOperationError(
+          'Unsupported SuperMethodInvocation without target');
+    }
+    if (target is Procedure && !target.isGetter) {
+      _genStaticCallWithArgs(target, args);
+    } else {
+      throw new UnsupportedOperationError(
+          'Unsupported SuperMethodInvocation with target ${target.runtimeType} $target');
+    }
+  }
+
+  @override
+  visitSuperPropertyGet(SuperPropertyGet node) {
+    asm.emitPush(locals.thisVarIndex);
+    Member target =
+        hierarchy.getDispatchTarget(enclosingClass.superclass, node.name);
+    if (target == null) {
+      throw new UnsupportedOperationError(
+          'Unsupported SuperPropertyGet without target');
+    }
+    if (target is Field || (target is Procedure && target.isGetter)) {
+      _genStaticCall(target, new ConstantArgDesc(1), 1);
+    } else {
+      throw new UnsupportedOperationError(
+          'Unsupported SuperPropertyGet with target ${target.runtimeType} $target');
+    }
+  }
+
+//  @override
+//  visitSuperPropertySet(SuperPropertySet node) {
+//  }
+
+  @override
+  visitNot(Not node) {
+    bool negated = _genCondition(node.operand);
+    if (!negated) {
+      asm.emitBooleanNegateTOS();
+    }
+  }
+
+  @override
+  visitNullLiteral(NullLiteral node) {
+    final cpIndex = cp.add(const ConstantNull());
+    asm.emitPushConstant(cpIndex);
+  }
+
+//  @override
+//  visitRethrow(Rethrow node) {
+//  }
+
+  bool _hasTrivialInitializer(Field field) =>
+      (field.initializer == null) ||
+      (field.initializer is StringLiteral) ||
+      (field.initializer is BoolLiteral) ||
+      (field.initializer is IntLiteral) ||
+      (field.initializer is NullLiteral);
+
+  @override
+  visitStaticGet(StaticGet node) {
+    final target = node.target;
+    if (target is Field) {
+      if (target.isConst) {
+        _genPushConstExpr(target.initializer);
+      } else if (_hasTrivialInitializer(target)) {
+        final fieldIndex = cp.add(new ConstantField(target));
+        asm.emitPushConstant(
+            fieldIndex); // TODO(alexmarkov): do we really need this?
+        asm.emitPushStatic(fieldIndex);
+      } else {
+        _genStaticCall(target, new ConstantArgDesc(0), 0);
+      }
+    } else if (target is Procedure) {
+      if (target.isGetter) {
+        _genStaticCall(target, new ConstantArgDesc(0), 0);
+      } else {
+        final tearOffIndex = cp.add(new ConstantTearOff(target));
+        asm.emitPushConstant(tearOffIndex);
+      }
+    } else {
+      throw 'Unexpected target for StaticGet: ${target.runtimeType} $target';
+    }
+  }
+
+  @override
+  visitStaticInvocation(StaticInvocation node) {
+    final args = node.arguments;
+    bool alwaysPassTypeArgs = false;
+    if (node.target.isFactory && args.types.isEmpty) {
+      // VM needs type arguments for every invocation of a factory constructor.
+      // TODO(alexmarkov): Why? Clean this up.
+      _genPushNull();
+      alwaysPassTypeArgs = true;
+    }
+    _genArguments(null, args);
+    _genStaticCallWithArgs(node.target, args,
+        alwaysPassTypeArgs: alwaysPassTypeArgs);
+  }
+
+  @override
+  visitStaticSet(StaticSet node) {
+    node.value.accept(this);
+    final target = node.target;
+    if (target is Field) {
+      // TODO(alexmarkov): assignable check
+      int cpIndex = cp.add(new ConstantField(target));
+      asm.emitStoreStaticTOS(cpIndex);
+    } else {
+      _genStaticCall(target, new ConstantArgDesc(1), 1);
+    }
+  }
+
+  @override
+  visitStringConcatenation(StringConcatenation node) {
+    if (node.expressions.length == 1) {
+      node.expressions.single.accept(this);
+      _genStaticCall(interpolateSingle, new ConstantArgDesc(1), 1);
+    } else {
+      _genPushNull();
+      _genPushInt(node.expressions.length);
+      asm.emitCreateArrayTOS();
+
+      final int temp = locals.tempIndex(node);
+      asm.emitStoreLocal(temp);
+
+      for (int i = 0; i < node.expressions.length; i++) {
+        asm.emitPush(temp);
+        _genPushInt(i);
+        node.expressions[i].accept(this);
+        asm.emitStoreIndexedTOS();
+      }
+
+      _genStaticCall(interpolate, new ConstantArgDesc(1), 1);
+    }
+  }
+
+  @override
+  visitStringLiteral(StringLiteral node) {
+    final cpIndex = cp.add(new ConstantString.fromLiteral(node));
+    asm.emitPushConstant(cpIndex);
+  }
+
+  @override
+  visitSymbolLiteral(SymbolLiteral node) {
+    final cpIndex = cp.add(new ConstantSymbol.fromLiteral(node));
+    asm.emitPushConstant(cpIndex);
+  }
+
+  @override
+  visitThisExpression(ThisExpression node) {
+    // TODO(alexmarkov): access to captured this from closures.
+    asm.emitPush(locals.thisVarIndex);
+  }
+
+  @override
+  visitThrow(Throw node) {
+    node.expression.accept(this);
+    asm.emitThrow(0);
+  }
+
+  @override
+  visitTypeLiteral(TypeLiteral node) {
+    final DartType type = node.type;
+    final int typeCPIndex = cp.add(new ConstantType(type));
+    if (!hasTypeParameters([type])) {
+      asm.emitPushConstant(typeCPIndex);
+    } else {
+      // TODO(alexmarkov): do not load instantiator type arguments / function type
+      // arguments if they are not needed for this particular [type].
+      _genPushInstantiatorTypeArguments();
+      _genPushFunctionTypeArguments();
+      asm.emitInstantiateType(typeCPIndex);
+    }
+  }
+
+  @override
+  visitVariableGet(VariableGet node) {
+    if (node.variable.isConst) {
+      _genPushConstExpr(node.variable.initializer);
+    } else {
+      // TODO(alexmarkov): access to captured variables.
+      asm.emitPush(locals.varIndex(node.variable));
+    }
+  }
+
+  @override
+  visitVariableSet(VariableSet node) {
+    node.value.accept(this);
+    // TODO(alexmarkov): access to captured variables.
+    asm.emitStoreLocal(locals.varIndex(node.variable));
+  }
+
+//  @override
+//  visitLoadLibrary(LoadLibrary node) {
+//  }
+//
+//  @override
+//  visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) {
+//  }
+//
+//  @override
+//  visitVectorCreation(VectorCreation node) {
+//  }
+//
+//  @override
+//  visitVectorGet(VectorGet node) {
+//  }
+//
+//  @override
+//  visitVectorSet(VectorSet node) {
+//  }
+//
+//  @override
+//  visitVectorCopy(VectorCopy node) {
+//  }
+//
+//  @override
+//  visitClosureCreation(ClosureCreation node) {
+//  }
+
+  @override
+  visitAssertStatement(AssertStatement node) {
+    // TODO(alexmarkov): support asserts
+  }
+
+  @override
+  visitBlock(Block node) {
+    visitList(node.statements, this);
+  }
+
+  @override
+  visitAssertBlock(AssertBlock node) {
+    // TODO(alexmarkov): support asserts
+  }
+
+  @override
+  visitBreakStatement(BreakStatement node) {
+    // TODO(alexmarkov): execute all finally blocks on the way out.
+    final label = labeledStatements[node.target] ??
+        (throw 'Target label ${node.target} was not registered for break $node');
+    asm.emitJump(label);
+  }
+
+  @override
+  visitContinueSwitchStatement(ContinueSwitchStatement node) {
+    // TODO(alexmarkov): execute all finally blocks on the way out.
+    final label = switchCases[node.target] ??
+        (throw 'Target label ${node.target} was not registered for continue-switch $node');
+    asm.emitJump(label);
+  }
+
+  @override
+  visitDoStatement(DoStatement node) {
+    final Label join = new Label();
+    asm.bind(join);
+
+    asm.emitCheckStack();
+
+    node.body.accept(this);
+
+    // TODO(alexmarkov): do we need to break this critical edge in CFG?
+    bool negated = _genCondition(node.condition);
+    _genJumpIfTrue(negated, join);
+  }
+
+  @override
+  visitEmptyStatement(EmptyStatement node) {
+    // no-op
+  }
+
+  @override
+  visitExpressionStatement(ExpressionStatement node) {
+    node.expression.accept(this);
+    asm.emitDrop1();
+  }
+
+  @override
+  visitForInStatement(ForInStatement node) {
+    node.iterable.accept(this);
+
+    const kIterator = 'iterator'; // Iterable.iterator
+    const kMoveNext = 'moveNext'; // Iterator.moveNext
+    const kCurrent = 'current'; // Iterator.current
+
+    asm.emitInstanceCall1(
+        1,
+        cp.add(new ConstantICData(
+            '$kGetterPrefix$kIterator', cp.add(new ConstantArgDesc(1)))));
+
+    final iteratorTemp = locals.tempIndex(node);
+    asm.emitPopLocal(iteratorTemp);
+
+    final Label done = new Label();
+    final Label join = new Label();
+    asm.bind(join);
+
+    asm.emitCheckStack();
+
+    asm.emitPush(iteratorTemp);
+    asm.emitInstanceCall1(1,
+        cp.add(new ConstantICData(kMoveNext, cp.add(new ConstantArgDesc(1)))));
+    _genJumpIfFalse(/* negated = */ false, done);
+
+    asm.emitPush(iteratorTemp);
+    asm.emitInstanceCall1(1,
+        cp.add(new ConstantICData(kCurrent, cp.add(new ConstantArgDesc(1)))));
+    asm.emitPopLocal(locals.varIndex(node.variable));
+
+    node.body.accept(this);
+
+    asm.emitJump(join);
+
+    asm.bind(done);
+  }
+
+  @override
+  visitForStatement(ForStatement node) {
+    visitList(node.variables, this);
+
+    final Label done = new Label();
+    final Label join = new Label();
+    asm.bind(join);
+
+    asm.emitCheckStack();
+
+    if (node.condition != null) {
+      bool negated = _genCondition(node.condition);
+      _genJumpIfFalse(negated, done);
+    }
+
+    node.body.accept(this);
+
+    for (var update in node.updates) {
+      update.accept(this);
+      asm.emitDrop1();
+    }
+
+    asm.emitJump(join);
+
+    asm.bind(done);
+  }
+
+//  @override
+//  visitFunctionDeclaration(FunctionDeclaration node) {
+//  }
+
+  @override
+  visitIfStatement(IfStatement node) {
+    final Label otherwisePart = new Label();
+
+    final bool negated = _genCondition(node.condition);
+    _genJumpIfFalse(negated, otherwisePart);
+
+    node.then.accept(this);
+
+    if (node.otherwise != null) {
+      final Label done = new Label();
+      asm.emitJump(done);
+      asm.bind(otherwisePart);
+      node.otherwise.accept(this);
+      asm.bind(done);
+    } else {
+      asm.bind(otherwisePart);
+    }
+  }
+
+  @override
+  visitLabeledStatement(LabeledStatement node) {
+    final label = new Label();
+    labeledStatements[node] = label;
+    node.body.accept(this);
+    asm.bind(label);
+    labeledStatements[node] = null;
+  }
+
+  @override
+  visitReturnStatement(ReturnStatement node) {
+    if (node.expression != null) {
+      node.expression.accept(this);
+    } else {
+      _genPushNull();
+    }
+    asm.emitReturnTOS();
+  }
+
+  @override
+  visitSwitchStatement(SwitchStatement node) {
+    node.expression.accept(this);
+
+    final int temp = locals.tempIndex(node);
+    asm.emitPopLocal(temp);
+
+    final Label done = new Label();
+    final List<Label> caseLabels =
+        new List<Label>.generate(node.cases.length, (_) => new Label());
+    final equalsArgDesc = cp.add(new ConstantArgDesc(2));
+
+    Label defaultLabel = done;
+    for (int i = 0; i < node.cases.length; i++) {
+      final SwitchCase switchCase = node.cases[i];
+      final Label caseLabel = caseLabels[i];
+      switchCases[switchCase] = caseLabel;
+
+      if (switchCase.isDefault) {
+        defaultLabel = caseLabel;
+      } else {
+        for (var expr in switchCase.expressions) {
+          asm.emitPush(temp);
+          _genPushConstExpr(expr);
+          asm.emitInstanceCall2(
+              2, cp.add(new ConstantICData('==', equalsArgDesc)));
+          _genJumpIfTrue(/* negated = */ false, caseLabel);
+        }
+      }
+    }
+
+    asm.emitJump(defaultLabel);
+
+    for (int i = 0; i < node.cases.length; i++) {
+      final SwitchCase switchCase = node.cases[i];
+      final Label caseLabel = caseLabels[i];
+
+      asm.bind(caseLabel);
+      switchCase.body.accept(this);
+
+      // Front-end issues a compile-time error if there is a fallthrough
+      // between cases. Also, default case should be the last one.
+    }
+
+    asm.bind(done);
+    node.cases.forEach(switchCases.remove);
+  }
+
+//  @override
+//  visitTryCatch(TryCatch node) {
+//  }
+//
+//  @override
+//  visitTryFinally(TryFinally node) {
+//  }
+
+  @override
+  visitVariableDeclaration(VariableDeclaration node) {
+    if (node.isConst) {
+      final Constant constant = constantEvaluator.evaluate(node.initializer);
+      constantEvaluator.env.addVariableValue(node, constant);
+    } else {
+      if (node.initializer != null) {
+        node.initializer.accept(this);
+      } else {
+        _genPushNull();
+      }
+      asm.emitPopLocal(locals.varIndex(node));
+    }
+  }
+
+  @override
+  visitWhileStatement(WhileStatement node) {
+    final Label done = new Label();
+    final Label join = new Label();
+    asm.bind(join);
+
+    asm.emitCheckStack();
+
+    bool negated = _genCondition(node.condition);
+    _genJumpIfFalse(negated, done);
+
+    node.body.accept(this);
+
+    asm.emitJump(join);
+
+    asm.bind(done);
+  }
+
+//  @override
+//  visitYieldStatement(YieldStatement node) {
+//  }
+
+  @override
+  visitFieldInitializer(FieldInitializer node) {
+    _genFieldInitializer(node.field, node.value);
+  }
+
+  @override
+  visitRedirectingInitializer(RedirectingInitializer node) {
+    final args = node.arguments;
+    assert(args.types.isEmpty);
+    _genArguments(new ThisExpression(), args);
+    _genStaticCallWithArgs(node.target, args, hasReceiver: true);
+    asm.emitDrop1();
+  }
+
+  @override
+  visitSuperInitializer(SuperInitializer node) {
+    final args = node.arguments;
+    assert(args.types.isEmpty);
+    _genArguments(new ThisExpression(), args);
+    // Re-resolve target due to partial mixin resolution.
+    Member target;
+    for (var replacement in enclosingClass.superclass.constructors) {
+      if (node.target.name == replacement.name) {
+        target = replacement;
+        break;
+      }
+    }
+    assert(target != null);
+    _genStaticCallWithArgs(target, args, hasReceiver: true);
+    asm.emitDrop1();
+  }
+
+//  @override
+//  visitLocalInitializer(LocalInitializer node) {
+//  }
+//
+//  @override
+//  visitAssertInitializer(AssertInitializer node) {
+//  }
+//
+//  @override
+//  visitInvalidInitializer(InvalidInitializer node) {}
+
+  @override
+  visitConstantExpression(ConstantExpression node) {
+    int cpIndex = node.constant.accept(constantEmitter);
+    asm.emitPushConstant(cpIndex);
+  }
+}
+
+class ConstantEmitter extends ConstantVisitor<int> {
+  final ConstantPool cp;
+
+  ConstantEmitter(this.cp);
+
+  @override
+  int defaultConstant(Constant node) => throw new UnsupportedOperationError(
+      'Unsupported constant node ${node.runtimeType}');
+
+  @override
+  int visitNullConstant(NullConstant node) => cp.add(const ConstantNull());
+
+  @override
+  int visitBoolConstant(BoolConstant node) =>
+      cp.add(new ConstantBool(node.value));
+
+  @override
+  int visitIntConstant(IntConstant node) => cp.add(new ConstantInt(node.value));
+
+  @override
+  int visitDoubleConstant(DoubleConstant node) =>
+      cp.add(new ConstantDouble(node.value));
+
+  @override
+  int visitStringConstant(StringConstant node) =>
+      cp.add(new ConstantString(node.value));
+
+  @override
+  int visitListConstant(ListConstant node) => cp.add(new ConstantList(
+      node.typeArgument,
+      new List<int>.from(node.entries.map((Constant c) => c.accept(this)))));
+
+  @override
+  int visitInstanceConstant(InstanceConstant node) =>
+      cp.add(new ConstantInstance(
+          node.klass,
+          cp.add(new ConstantTypeArguments(node.typeArguments)),
+          node.fieldValues.map<Reference, int>(
+              (Reference fieldRef, Constant value) =>
+                  new MapEntry(fieldRef, value.accept(this)))));
+
+  @override
+  int visitTearOffConstant(TearOffConstant node) =>
+      cp.add(new ConstantTearOff(node.procedure));
+
+//  @override
+//  int visitTypeLiteralConstant(TypeLiteralConstant node) => defaultConstant(node);
+}
+
+class UnsupportedOperationError {
+  final String message;
+  UnsupportedOperationError(this.message);
+
+  @override
+  String toString() => message;
+}
+
+class FindTypeParametersVisitor extends DartTypeVisitor<bool> {
+  bool visit(DartType type) => type.accept(this);
+
+  @override
+  bool defaultDartType(DartType node) =>
+      throw 'Unexpected type ${node.runtimeType} $node';
+
+  @override
+  bool visitInvalidType(InvalidType node) => false;
+
+  @override
+  bool visitDynamicType(DynamicType node) => false;
+
+  @override
+  bool visitVoidType(VoidType node) => false;
+
+  @override
+  bool visitBottomType(BottomType node) => false;
+
+  @override
+  bool visitVectorType(VectorType node) => false;
+
+  @override
+  bool visitTypeParameterType(TypeParameterType node) => true;
+
+  @override
+  bool visitInterfaceType(InterfaceType node) =>
+      node.typeArguments.any((t) => t.accept(this));
+
+  @override
+  bool visitTypedefType(TypedefType node) =>
+      node.typeArguments.any((t) => t.accept(this));
+
+  @override
+  bool visitFunctionType(FunctionType node) =>
+      node.typeParameters.isNotEmpty ||
+      node.positionalParameters.any((t) => t.accept(this)) ||
+      node.namedParameters.any((p) => p.type.accept(this));
+}
diff --git a/pkg/vm/lib/bytecode/local_vars.dart b/pkg/vm/lib/bytecode/local_vars.dart
new file mode 100644
index 0000000..578cbc6
--- /dev/null
+++ b/pkg/vm/lib/bytecode/local_vars.dart
@@ -0,0 +1,238 @@
+// 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.
+
+library vm.bytecode.local_vars;
+
+import 'dart:math' show max;
+
+import 'package:kernel/ast.dart';
+import 'package:vm/bytecode/dbc.dart';
+
+class LocalVariables extends RecursiveVisitor<Null> {
+  final Map<VariableDeclaration, int> _vars = <VariableDeclaration, int>{};
+  final Map<TreeNode, int> _temps = <TreeNode, int>{};
+  final List<int> _scopes = <int>[];
+  int _localVars = 0;
+  int _frameSize = 0;
+  int _numParameters = 0;
+  bool _hasOptionalParameters = false;
+  int _thisVarIndex;
+  int _functionTypeArgsVarIndex;
+
+  int get thisVarIndex =>
+      _thisVarIndex ?? (throw '\'this\' variable is not allocated');
+
+  int get functionTypeArgsVarIndex =>
+      _functionTypeArgsVarIndex ??
+      (throw '\'functionTypeArgs\' variable is not allocated');
+
+  int get frameSize => _frameSize;
+
+  int get numParameters => _numParameters;
+
+  bool get hasOptionalParameters => _hasOptionalParameters;
+
+  int varIndex(VariableDeclaration variable) =>
+      _vars[variable] ?? (throw '\'$variable\' variable is not allocated');
+
+  int tempIndex(TreeNode node) =>
+      _temps[node] ??
+      (throw 'Temp is not allocated for node ${node.runtimeType} $node');
+
+  int _allocateVar(VariableDeclaration node, {int index}) {
+    if (index == null) {
+      index = _localVars++;
+    } else {
+      // Should be a parameter.
+      assert(index < 0 || (_hasOptionalParameters && index < _numParameters));
+    }
+    _frameSize = max(_frameSize, _localVars);
+    if (node != null) {
+      assert(_vars[node] == null);
+      _vars[node] = index;
+    }
+    return index;
+  }
+
+  // TODO(alexmarkov): allocate temporaries more efficiently.
+  void _allocateTemp(TreeNode node) {
+    _temps[node] = _allocateVar(null);
+  }
+
+  int _allocateParameter(VariableDeclaration node, int i) {
+    assert(0 <= i && i < _numParameters);
+    int paramSlotIndex =
+        _hasOptionalParameters ? i : -kParamEndSlotFromFp - _numParameters + i;
+    return _allocateVar(node, index: paramSlotIndex);
+  }
+
+  void _enterScope() {
+    _scopes.add(_localVars);
+  }
+
+  void _leaveScope() {
+    final int enclosingScopeLocalVars = _scopes.removeLast();
+    assert(_localVars >= enclosingScopeLocalVars);
+    _localVars = enclosingScopeLocalVars;
+  }
+
+  @override
+  visitField(Field node) {
+    if (node.initializer != null) {
+      assert(_vars.isEmpty);
+      assert(_localVars == 0);
+
+      _enterScope();
+      node.initializer.accept(this);
+      _leaveScope();
+
+      assert(_scopes.isEmpty);
+    }
+  }
+
+  @override
+  defaultMember(Member node) {
+    assert(_vars.isEmpty);
+    assert(_localVars == 0);
+
+    final function = node.function;
+    final bool hasTypeArgs = function.typeParameters.isNotEmpty;
+    final bool hasReceiver =
+        node is Constructor || ((node is Procedure) && !node.isStatic);
+    _numParameters = function.positionalParameters.length +
+        function.namedParameters.length +
+        (hasTypeArgs ? 1 : 0) +
+        (hasReceiver ? 1 : 0);
+    _hasOptionalParameters = function.requiredParameterCount <
+            function.positionalParameters.length ||
+        function.namedParameters.isNotEmpty;
+    int count = 0;
+
+    if (hasTypeArgs) {
+      _functionTypeArgsVarIndex = _allocateParameter(null, count++);
+    }
+
+    if (hasReceiver) {
+      _thisVarIndex = _allocateParameter(null, count++);
+    }
+
+    for (var param in function.positionalParameters) {
+      _allocateParameter(param, count++);
+    }
+
+    List<VariableDeclaration> namedParams = function.namedParameters;
+    namedParams.sort((VariableDeclaration a, VariableDeclaration b) =>
+        a.name.compareTo(b.name));
+    for (var param in namedParams) {
+      _allocateParameter(param, count++);
+    }
+
+    if (_hasOptionalParameters) {
+      _localVars = _numParameters;
+      _frameSize = _numParameters;
+    }
+
+    _enterScope();
+    if (node is Constructor) {
+      _enterScope();
+      for (var field in node.enclosingClass.fields) {
+        if (!field.isStatic && field.initializer != null) {
+          field.initializer.accept(this);
+        }
+      }
+      visitList(node.initializers, this);
+      _leaveScope();
+    }
+    function.body?.accept(this);
+    _leaveScope();
+
+    assert(_scopes.isEmpty);
+  }
+
+  @override
+  visitBlock(Block node) {
+    _enterScope();
+    node.visitChildren(this);
+    _leaveScope();
+  }
+
+  @override
+  visitVariableDeclaration(VariableDeclaration node) {
+    _allocateVar(node);
+    node.visitChildren(this);
+  }
+
+  @override
+  visitLet(Let node) {
+    _enterScope();
+    node.variable.accept(this);
+    node.body.accept(this);
+    _leaveScope();
+  }
+
+  // -------------- Allocation of temporaries --------------
+
+  @override
+  visitConstructorInvocation(ConstructorInvocation node) {
+    if (node.isConst) {
+      return;
+    }
+    _allocateTemp(node);
+    super.visitConstructorInvocation(node);
+  }
+
+  @override
+  visitListLiteral(ListLiteral node) {
+    if (node.isConst) {
+      return;
+    }
+    _allocateTemp(node);
+    super.visitListLiteral(node);
+  }
+
+  @override
+  visitMapLiteral(MapLiteral node) {
+    if (node.isConst) {
+      return;
+    }
+    _allocateTemp(node);
+    super.visitMapLiteral(node);
+  }
+
+  @override
+  visitStringConcatenation(StringConcatenation node) {
+    _allocateTemp(node);
+    super.visitStringConcatenation(node);
+  }
+
+  @override
+  visitConditionalExpression(ConditionalExpression node) {
+    _allocateTemp(node);
+    super.visitConditionalExpression(node);
+  }
+
+  @override
+  visitLogicalExpression(LogicalExpression node) {
+    _allocateTemp(node);
+    super.visitLogicalExpression(node);
+  }
+
+  @override
+  visitPropertySet(PropertySet node) {
+    _allocateTemp(node);
+    super.visitPropertySet(node);
+  }
+
+  @override
+  visitForInStatement(ForInStatement node) {
+    _allocateTemp(node);
+    super.visitForInStatement(node);
+  }
+
+  @override
+  visitSwitchStatement(SwitchStatement node) {
+    _allocateTemp(node);
+    super.visitSwitchStatement(node);
+  }
+}
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 026a99e..8bf56e0 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -16,6 +16,7 @@
 import 'package:front_end/src/fasta/severity.dart' show Severity;
 import 'package:kernel/ast.dart' show Component, StaticGet, Field;
 import 'package:kernel/core_types.dart' show CoreTypes;
+import 'package:vm/bytecode/gen_bytecode.dart' show generateBytecode;
 
 import 'transformations/devirtualization.dart' as devirtualization
     show transformComponent;
@@ -34,7 +35,8 @@
 Future<Component> compileToKernel(Uri source, CompilerOptions options,
     {bool aot: false,
     bool useGlobalTypeFlowAnalysis: false,
-    List<String> entryPoints}) async {
+    List<String> entryPoints,
+    bool genBytecode: false}) async {
   // Replace error handler to detect if there are compilation errors.
   final errorDetector =
       new ErrorDetector(previousErrorHandler: options.onError);
@@ -51,6 +53,10 @@
         component, options.strongMode, useGlobalTypeFlowAnalysis, entryPoints);
   }
 
+  if (genBytecode && component != null) {
+    generateBytecode(component, strongMode: options.strongMode);
+  }
+
   return component;
 }
 
diff --git a/pkg/vm/lib/metadata/bytecode.dart b/pkg/vm/lib/metadata/bytecode.dart
new file mode 100644
index 0000000..1c28c0e
--- /dev/null
+++ b/pkg/vm/lib/metadata/bytecode.dart
@@ -0,0 +1,44 @@
+// 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.
+
+library vm.metadata.bytecode;
+
+import 'package:kernel/ast.dart';
+import 'package:vm/bytecode/constant_pool.dart' show ConstantPool;
+import 'package:vm/bytecode/disassembler.dart' show BytecodeDisassembler;
+
+/// Metadata containing bytecode.
+class BytecodeMetadata {
+  final List<int> bytecodes;
+  final ConstantPool constantPool;
+
+  BytecodeMetadata(this.bytecodes, this.constantPool);
+
+  @override
+  String toString() =>
+      "\nBytecode {\n${new BytecodeDisassembler().disassemble(bytecodes)}}\n$constantPool";
+}
+
+/// Repository for [BytecodeMetadata].
+class BytecodeMetadataRepository extends MetadataRepository<BytecodeMetadata> {
+  @override
+  final String tag = 'vm.bytecode';
+
+  @override
+  final Map<TreeNode, BytecodeMetadata> mapping =
+      <TreeNode, BytecodeMetadata>{};
+
+  @override
+  void writeToBinary(BytecodeMetadata metadata, BinarySink sink) {
+    sink.writeByteList(metadata.bytecodes);
+    metadata.constantPool.writeToBinary(sink);
+  }
+
+  @override
+  BytecodeMetadata readFromBinary(BinarySource source) {
+    final List<int> bytecodes = source.readByteList();
+    final ConstantPool constantPool = new ConstantPool.readFromBinary(source);
+    return new BytecodeMetadata(bytecodes, constantPool);
+  }
+}
diff --git a/pkg/vm/lib/transformations/type_flow/entry_points_extra.json b/pkg/vm/lib/transformations/type_flow/entry_points_extra.json
index 4d4ce33..0ff8ba4 100644
--- a/pkg/vm/lib/transformations/type_flow/entry_points_extra.json
+++ b/pkg/vm/lib/transformations/type_flow/entry_points_extra.json
@@ -95,6 +95,12 @@
     {
       "library": "dart:core",
       "class": "_Closure",
+      "name": "_delayed_type_arguments",
+      "action": "get"
+    },
+    {
+      "library": "dart:core",
+      "class": "_Closure",
       "name": "_function",
       "action": "get"
     },
diff --git a/pkg/vm/test/bytecode/gen_bytecode_test.dart b/pkg/vm/test/bytecode/gen_bytecode_test.dart
new file mode 100644
index 0000000..3ee9d45
--- /dev/null
+++ b/pkg/vm/test/bytecode/gen_bytecode_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/kernel.dart';
+import 'package:test/test.dart';
+import 'package:vm/bytecode/gen_bytecode.dart' show generateBytecode;
+
+import '../common_test_utils.dart';
+
+final String pkgVmDir = Platform.script.resolve('../..').toFilePath();
+
+runTestCase(Uri source) async {
+  Component component = await compileTestCaseToKernelProgram(source);
+
+  generateBytecode(component, strongMode: true);
+
+  final actual = kernelLibraryToString(component.mainMethod.enclosingLibrary);
+  compareResultWithExpectationsFile(source, actual);
+}
+
+main() {
+  group('gen-bytecode', () {
+    final testCasesDir = new Directory(pkgVmDir + '/testcases/bytecode');
+
+    for (var entry
+        in testCasesDir.listSync(recursive: true, followLinks: false)) {
+      if (entry.path.endsWith(".dart")) {
+        test(entry.path, () => runTestCase(entry.uri));
+      }
+    }
+  });
+}
diff --git a/pkg/vm/test/transformations/type_flow/common_test_utils.dart b/pkg/vm/test/common_test_utils.dart
similarity index 74%
rename from pkg/vm/test/transformations/type_flow/common_test_utils.dart
rename to pkg/vm/test/common_test_utils.dart
index cdac3b9..20b0126 100644
--- a/pkg/vm/test/transformations/type_flow/common_test_utils.dart
+++ b/pkg/vm/test/common_test_utils.dart
@@ -9,6 +9,7 @@
 import 'package:front_end/src/compute_platform_binaries_location.dart'
     show computePlatformBinariesLocation;
 import 'package:kernel/ast.dart';
+import 'package:kernel/text/ast_to_text.dart' show Printer;
 import 'package:kernel/target/targets.dart';
 import 'package:kernel/target/vm.dart';
 import 'package:test/test.dart';
@@ -26,7 +27,21 @@
     ..onError = (CompilationMessage error) {
       fail("Compilation error: ${error}");
     };
-  return kernelForProgram(sourceUri, options);
+
+  final Component component = await kernelForProgram(sourceUri, options);
+
+  // Make sure the library name is the same and does not depend on the order
+  // of test cases.
+  component.mainMethod.enclosingLibrary.name = '#lib';
+
+  return component;
+}
+
+String kernelLibraryToString(Library library) {
+  final StringBuffer buffer = new StringBuffer();
+  new Printer(buffer, showExternal: false, showMetadata: true)
+      .writeLibraryFile(library);
+  return buffer.toString();
 }
 
 void compareResultWithExpectationsFile(Uri source, String actual) {
diff --git a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
index 9d4499b..369c421 100644
--- a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
+++ b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
@@ -12,7 +12,7 @@
 import 'package:vm/transformations/type_flow/native_code.dart';
 import 'package:vm/transformations/type_flow/summary_collector.dart';
 
-import 'common_test_utils.dart';
+import '../../common_test_utils.dart';
 
 final String pkgVmDir = Platform.script.resolve('../../..').toFilePath();
 
@@ -43,10 +43,6 @@
   final Component component = await compileTestCaseToKernelProgram(source);
   final Library library = component.mainMethod.enclosingLibrary;
 
-  // Make sure the library name is the same and does not depend on the order
-  // of test cases.
-  library.name = '#lib';
-
   final typeEnvironment = new TypeEnvironment(
       new CoreTypes(component), new ClassHierarchy(component));
 
diff --git a/pkg/vm/test/transformations/type_flow/transformer_test.dart b/pkg/vm/test/transformations/type_flow/transformer_test.dart
index 45a1855..07dcb37 100644
--- a/pkg/vm/test/transformations/type_flow/transformer_test.dart
+++ b/pkg/vm/test/transformations/type_flow/transformer_test.dart
@@ -7,22 +7,17 @@
 import 'package:kernel/ast.dart';
 import 'package:kernel/core_types.dart';
 import 'package:kernel/kernel.dart';
-import 'package:kernel/text/ast_to_text.dart';
 import 'package:test/test.dart';
 import 'package:vm/transformations/type_flow/transformer.dart'
     show transformComponent;
 
-import 'common_test_utils.dart';
+import '../../common_test_utils.dart';
 
 final String pkgVmDir = Platform.script.resolve('../../..').toFilePath();
 
 runTestCase(Uri source) async {
   Component component = await compileTestCaseToKernelProgram(source);
 
-  // Make sure the library name is the same and does not depend on the order
-  // of test cases.
-  component.mainMethod.enclosingLibrary.name = '#lib';
-
   final coreTypes = new CoreTypes(component);
 
   final entryPoints = [
@@ -32,10 +27,7 @@
 
   component = transformComponent(coreTypes, component, entryPoints);
 
-  final StringBuffer buffer = new StringBuffer();
-  new Printer(buffer, showExternal: false, showMetadata: true)
-      .writeLibraryFile(component.mainMethod.enclosingLibrary);
-  final actual = buffer.toString();
+  final actual = kernelLibraryToString(component.mainMethod.enclosingLibrary);
 
   compareResultWithExpectationsFile(source, actual);
 }
diff --git a/pkg/vm/testcases/bytecode/boostrapping.dart b/pkg/vm/testcases/bytecode/boostrapping.dart
new file mode 100644
index 0000000..8f79be8
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/boostrapping.dart
@@ -0,0 +1,142 @@
+// 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.
+
+// Selection of methods used during bootstrapping.
+
+// ignore_for_file: native_function_body_in_non_sdk_code
+// ignore_for_file: unused_element, unused_field
+
+// -----------------------------------------------------------------
+
+void _printString(String s) native "Builtin_PrintString";
+
+void _print(arg) {
+  _printString(arg.toString());
+}
+
+_getPrintClosure() => _print;
+
+// -----------------------------------------------------------------
+
+typedef void _ScheduleImmediateClosure(void callback());
+
+class _ScheduleImmediate {
+  static _ScheduleImmediateClosure _closure;
+}
+
+void _setScheduleImmediateClosure(_ScheduleImmediateClosure closure) {
+  _ScheduleImmediate._closure = closure;
+}
+
+// -----------------------------------------------------------------
+
+class _NamespaceImpl implements _Namespace {
+  _NamespaceImpl._();
+
+  static _NamespaceImpl _create(_NamespaceImpl namespace, var n)
+      native "Namespace_Create";
+  static int _getPointer(_NamespaceImpl namespace)
+      native "Namespace_GetPointer";
+  static int _getDefault() native "Namespace_GetDefault";
+
+  // If the platform supports "namespaces", this method is called by the
+  // embedder with the platform-specific namespace information.
+  static _NamespaceImpl _cachedNamespace = null;
+  static void _setupNamespace(var namespace) {
+    _cachedNamespace = _create(new _NamespaceImpl._(), namespace);
+  }
+
+  static _NamespaceImpl get _namespace {
+    if (_cachedNamespace == null) {
+      // The embedder has not supplied a namespace before one is needed, so
+      // instead use a safe-ish default value.
+      _cachedNamespace = _create(new _NamespaceImpl._(), _getDefault());
+    }
+    return _cachedNamespace;
+  }
+
+  static int get _namespacePointer => _getPointer(_namespace);
+}
+
+class _Namespace {
+  static void _setupNamespace(var namespace) {
+    _NamespaceImpl._setupNamespace(namespace);
+  }
+
+  static _Namespace get _namespace => _NamespaceImpl._namespace;
+
+  static int get _namespacePointer => _NamespaceImpl._namespacePointer;
+}
+
+// -----------------------------------------------------------------
+
+// These may be set to different values by the embedder by calling
+// _setStdioFDs when initializing dart:io.
+int _stdinFD = 0;
+int _stdoutFD = 1;
+int _stderrFD = 2;
+
+// This is an embedder entrypoint.
+void _setStdioFDs(int stdin, int stdout, int stderr) {
+  _stdinFD = stdin;
+  _stdoutFD = stdout;
+  _stderrFD = stderr;
+}
+
+// -----------------------------------------------------------------
+
+class VMLibraryHooks {
+  // Example: "dart:isolate _Timer._factory"
+  static var timerFactory;
+
+  // Example: "dart:io _EventHandler._sendData"
+  static var eventHandlerSendData;
+
+  // A nullary closure that answers the current clock value in milliseconds.
+  // Example: "dart:io _EventHandler._timerMillisecondClock"
+  static var timerMillisecondClock;
+
+  // Implementation of Resource.readAsBytes.
+  static var resourceReadAsBytes;
+
+  // Implementation of package root/map provision.
+  static var packageRootString;
+  static var packageConfigString;
+  static var packageRootUriFuture;
+  static var packageConfigUriFuture;
+  static var resolvePackageUriFuture;
+
+  static var _computeScriptUri;
+  static var _cachedScript;
+  static set platformScript(var f) {
+    _computeScriptUri = f;
+    _cachedScript = null;
+  }
+
+  static get platformScript {
+    if (_cachedScript == null && _computeScriptUri != null) {
+      _cachedScript = _computeScriptUri();
+    }
+    return _cachedScript;
+  }
+}
+
+String _rawScript;
+Uri _scriptUri() {
+  if (_rawScript.startsWith('http:') ||
+      _rawScript.startsWith('https:') ||
+      _rawScript.startsWith('file:')) {
+    return Uri.parse(_rawScript);
+  } else {
+    return Uri.base.resolveUri(new Uri.file(_rawScript));
+  }
+}
+
+_setupHooks() {
+  VMLibraryHooks.platformScript = _scriptUri;
+}
+
+// -----------------------------------------------------------------
+
+main() {}
diff --git a/pkg/vm/testcases/bytecode/boostrapping.dart.expect b/pkg/vm/testcases/bytecode/boostrapping.dart.expect
new file mode 100644
index 0000000..8070f3e
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/boostrapping.dart.expect
@@ -0,0 +1,742 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+typedef _ScheduleImmediateClosure = (() → void) → void;
+class _ScheduleImmediate extends core::Object {
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]  static field (() → void) → void _closure = null;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  PushConstant         CP#1
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = StaticICData target 'dart.core::Object::', arg-desc CP#0
+  [2] = Null
+}
+]  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class _NamespaceImpl extends core::Object implements self::_Namespace {
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]  static field self::_NamespaceImpl _cachedNamespace = null;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  PushConstant         CP#1
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = StaticICData target 'dart.core::Object::', arg-desc CP#0
+  [2] = Null
+}
+]  constructor _() → void
+    : super core::Object::•()
+    ;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]  @_in::ExternalName::•("Namespace_Create")
+  external static method _create(self::_NamespaceImpl namespace, dynamic n) → self::_NamespaceImpl;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]  @_in::ExternalName::•("Namespace_GetPointer")
+  external static method _getPointer(self::_NamespaceImpl namespace) → core::int;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]  @_in::ExternalName::•("Namespace_GetDefault")
+  external static method _getDefault() → core::int;
+[@vm.bytecode=
+Bytecode {
+  Entry                1
+  CheckStack
+  Allocate             CP#0
+  StoreLocal           r0
+  Push                 r0
+  PushConstant         CP#2
+  IndirectStaticCall   1, CP#1
+  Drop1
+  Push                 FP[-5]
+  PushConstant         CP#4
+  IndirectStaticCall   2, CP#3
+  StoreStaticTOS       CP#5
+  Drop1
+  PushConstant         CP#6
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Class #lib::_NamespaceImpl
+  [1] = ArgDesc num-args 1, num-type-args 0, names []
+  [2] = StaticICData target '#lib::_NamespaceImpl::_', arg-desc CP#1
+  [3] = ArgDesc num-args 2, num-type-args 0, names []
+  [4] = StaticICData target '#lib::_NamespaceImpl::_create', arg-desc CP#3
+  [5] = Field #lib::_NamespaceImpl::_cachedNamespace
+  [6] = Null
+}
+]  static method _setupNamespace(dynamic namespace) → void {
+    self::_NamespaceImpl::_cachedNamespace = self::_NamespaceImpl::_create(new self::_NamespaceImpl::_(), namespace);
+  }
+[@vm.bytecode=
+Bytecode {
+  Entry                1
+  CheckStack
+  PushConstant         CP#0
+  PushStatic           CP#0
+  PushConstant         CP#1
+  InstanceCall1        2, CP#3
+  PushConstant         CP#4
+  IfNeStrictTOS
+  Jump                 L1
+  Allocate             CP#5
+  StoreLocal           r0
+  Push                 r0
+  PushConstant         CP#7
+  IndirectStaticCall   1, CP#6
+  Drop1
+  PushConstant         CP#9
+  IndirectStaticCall   0, CP#8
+  PushConstant         CP#10
+  IndirectStaticCall   2, CP#2
+  StoreStaticTOS       CP#0
+  Drop1
+L1:
+  PushConstant         CP#0
+  PushStatic           CP#0
+  ReturnTOS
+  PushConstant         CP#1
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Field #lib::_NamespaceImpl::_cachedNamespace
+  [1] = Null
+  [2] = ArgDesc num-args 2, num-type-args 0, names []
+  [3] = ICData target-name '==', arg-desc CP#2
+  [4] = Bool true
+  [5] = Class #lib::_NamespaceImpl
+  [6] = ArgDesc num-args 1, num-type-args 0, names []
+  [7] = StaticICData target '#lib::_NamespaceImpl::_', arg-desc CP#6
+  [8] = ArgDesc num-args 0, num-type-args 0, names []
+  [9] = StaticICData target '#lib::_NamespaceImpl::_getDefault', arg-desc CP#8
+  [10] = StaticICData target '#lib::_NamespaceImpl::_create', arg-desc CP#2
+}
+]  static get _namespace() → self::_NamespaceImpl {
+    if(self::_NamespaceImpl::_cachedNamespace.{core::Object::==}(null)) {
+      self::_NamespaceImpl::_cachedNamespace = self::_NamespaceImpl::_create(new self::_NamespaceImpl::_(), self::_NamespaceImpl::_getDefault());
+    }
+    return self::_NamespaceImpl::_cachedNamespace;
+  }
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#1
+  IndirectStaticCall   0, CP#0
+  PushConstant         CP#3
+  IndirectStaticCall   1, CP#2
+  ReturnTOS
+  PushConstant         CP#4
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 0, num-type-args 0, names []
+  [1] = StaticICData target '#lib::_NamespaceImpl::_namespace', arg-desc CP#0
+  [2] = ArgDesc num-args 1, num-type-args 0, names []
+  [3] = StaticICData target '#lib::_NamespaceImpl::_getPointer', arg-desc CP#2
+  [4] = Null
+}
+]  static get _namespacePointer() → core::int
+    return self::_NamespaceImpl::_getPointer(self::_NamespaceImpl::_namespace);
+}
+class _Namespace extends core::Object {
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  PushConstant         CP#1
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = StaticICData target 'dart.core::Object::', arg-desc CP#0
+  [2] = Null
+}
+]  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  PushConstant         CP#1
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = StaticICData target '#lib::_NamespaceImpl::_setupNamespace', arg-desc CP#0
+  [2] = Null
+}
+]  static method _setupNamespace(dynamic namespace) → void {
+    self::_NamespaceImpl::_setupNamespace(namespace);
+  }
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#1
+  IndirectStaticCall   0, CP#0
+  ReturnTOS
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 0, num-type-args 0, names []
+  [1] = StaticICData target '#lib::_NamespaceImpl::_namespace', arg-desc CP#0
+  [2] = Null
+}
+]  static get _namespace() → self::_Namespace
+    return self::_NamespaceImpl::_namespace;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#1
+  IndirectStaticCall   0, CP#0
+  ReturnTOS
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 0, num-type-args 0, names []
+  [1] = StaticICData target '#lib::_NamespaceImpl::_namespacePointer', arg-desc CP#0
+  [2] = Null
+}
+]  static get _namespacePointer() → core::int
+    return self::_NamespaceImpl::_namespacePointer;
+}
+class VMLibraryHooks extends core::Object {
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]  static field dynamic timerFactory = null;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]  static field dynamic eventHandlerSendData = null;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]  static field dynamic timerMillisecondClock = null;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]  static field dynamic resourceReadAsBytes = null;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]  static field dynamic packageRootString = null;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]  static field dynamic packageConfigString = null;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]  static field dynamic packageRootUriFuture = null;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]  static field dynamic packageConfigUriFuture = null;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]  static field dynamic resolvePackageUriFuture = null;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]  static field dynamic _computeScriptUri = null;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]  static field dynamic _cachedScript = null;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  PushConstant         CP#1
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = StaticICData target 'dart.core::Object::', arg-desc CP#0
+  [2] = Null
+}
+]  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  StoreStaticTOS       CP#0
+  Drop1
+  PushConstant         CP#1
+  StoreStaticTOS       CP#2
+  Drop1
+  PushConstant         CP#1
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Field #lib::VMLibraryHooks::_computeScriptUri
+  [1] = Null
+  [2] = Field #lib::VMLibraryHooks::_cachedScript
+}
+]  static set platformScript(dynamic f) → void {
+    self::VMLibraryHooks::_computeScriptUri = f;
+    self::VMLibraryHooks::_cachedScript = null;
+  }
+[@vm.bytecode=
+Bytecode {
+  Entry                1
+  CheckStack
+  PushConstant         CP#0
+  PushStatic           CP#0
+  PushConstant         CP#1
+  InstanceCall1        2, CP#3
+  PushConstant         CP#4
+  IfNeStrictTOS
+  Jump                 L1
+  PushConstant         CP#5
+  PushStatic           CP#5
+  PushConstant         CP#1
+  InstanceCall1        2, CP#6
+  BooleanNegateTOS
+  PopLocal             r0
+  Jump                 L2
+L1:
+  PushConstant         CP#7
+  PopLocal             r0
+L2:
+  Push                 r0
+  PushConstant         CP#4
+  IfNeStrictTOS
+  Jump                 L3
+  PushConstant         CP#5
+  PushStatic           CP#5
+  InstanceCall1        1, CP#9
+  StoreStaticTOS       CP#0
+  Drop1
+L3:
+  PushConstant         CP#0
+  PushStatic           CP#0
+  ReturnTOS
+  PushConstant         CP#1
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Field #lib::VMLibraryHooks::_cachedScript
+  [1] = Null
+  [2] = ArgDesc num-args 2, num-type-args 0, names []
+  [3] = ICData target-name '==', arg-desc CP#2
+  [4] = Bool true
+  [5] = Field #lib::VMLibraryHooks::_computeScriptUri
+  [6] = ICData target-name '==', arg-desc CP#2
+  [7] = Bool false
+  [8] = ArgDesc num-args 1, num-type-args 0, names []
+  [9] = ICData target-name 'call', arg-desc CP#8
+}
+]  static get platformScript() → dynamic {
+    if(self::VMLibraryHooks::_cachedScript.==(null) && !self::VMLibraryHooks::_computeScriptUri.==(null)) {
+      self::VMLibraryHooks::_cachedScript = self::VMLibraryHooks::_computeScriptUri.call();
+    }
+    return self::VMLibraryHooks::_cachedScript;
+  }
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 0
+}
+]static field core::int _stdinFD = 0;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 1
+}
+]static field core::int _stdoutFD = 1;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 2
+}
+]static field core::int _stderrFD = 2;
+static field core::String _rawScript;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]@_in::ExternalName::•("Builtin_PrintString")
+external static method _printString(core::String s) → void;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  InstanceCall1        1, CP#1
+  PushConstant         CP#2
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#3
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = ICData target-name 'toString', arg-desc CP#0
+  [2] = StaticICData target '#lib::_printString', arg-desc CP#0
+  [3] = Null
+}
+]static method _print(dynamic arg) → void {
+  self::_printString(arg.toString() as{TypeError} core::String);
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+  PushConstant         CP#1
+  ReturnTOS
+}
+ConstantPool {
+  [0] = TearOff #lib::_print
+  [1] = Null
+}
+]static method _getPrintClosure() → dynamic
+  return self::_print;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  StoreStaticTOS       CP#0
+  Drop1
+  PushConstant         CP#1
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Field #lib::_ScheduleImmediate::_closure
+  [1] = Null
+}
+]static method _setScheduleImmediateClosure((() → void) → void closure) → void {
+  self::_ScheduleImmediate::_closure = closure;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-7]
+  StoreStaticTOS       CP#0
+  Drop1
+  Push                 FP[-6]
+  StoreStaticTOS       CP#1
+  Drop1
+  Push                 FP[-5]
+  StoreStaticTOS       CP#2
+  Drop1
+  PushConstant         CP#3
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Field #lib::_stdinFD
+  [1] = Field #lib::_stdoutFD
+  [2] = Field #lib::_stderrFD
+  [3] = Null
+}
+]static method _setStdioFDs(core::int stdin, core::int stdout, core::int stderr) → void {
+  self::_stdinFD = stdin;
+  self::_stdoutFD = stdout;
+  self::_stderrFD = stderr;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                2
+  CheckStack
+  PushConstant         CP#0
+  PushStatic           CP#0
+  PushConstant         CP#1
+  InstanceCall1        2, CP#3
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L1
+  PushConstant         CP#0
+  PushStatic           CP#0
+  PushConstant         CP#5
+  InstanceCall1        2, CP#6
+  PopLocal             r1
+  Jump                 L2
+L1:
+  PushConstant         CP#4
+  PopLocal             r1
+L2:
+  Push                 r1
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L3
+  PushConstant         CP#0
+  PushStatic           CP#0
+  PushConstant         CP#7
+  InstanceCall1        2, CP#8
+  PopLocal             r0
+  Jump                 L4
+L3:
+  PushConstant         CP#4
+  PopLocal             r0
+L4:
+  Push                 r0
+  PushConstant         CP#4
+  IfNeStrictTOS
+  Jump                 L5
+  PushConstant         CP#0
+  PushStatic           CP#0
+  PushConstant         CP#10
+  IndirectStaticCall   1, CP#9
+  ReturnTOS
+  Jump                 L6
+L5:
+  PushConstant         CP#12
+  IndirectStaticCall   0, CP#11
+  PushConstant         CP#13
+  PushConstant         CP#0
+  PushStatic           CP#0
+  PushConstant         CP#14
+  IndirectStaticCall   2, CP#9
+  InstanceCall1        2, CP#15
+  ReturnTOS
+L6:
+  PushConstant         CP#13
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Field #lib::_rawScript
+  [1] = String 'http:'
+  [2] = ArgDesc num-args 2, num-type-args 0, names []
+  [3] = ICData target-name 'startsWith', arg-desc CP#2
+  [4] = Bool true
+  [5] = String 'https:'
+  [6] = ICData target-name 'startsWith', arg-desc CP#2
+  [7] = String 'file:'
+  [8] = ICData target-name 'startsWith', arg-desc CP#2
+  [9] = ArgDesc num-args 1, num-type-args 0, names []
+  [10] = StaticICData target 'dart.core::Uri::parse', arg-desc CP#9
+  [11] = ArgDesc num-args 0, num-type-args 0, names []
+  [12] = StaticICData target 'dart.core::Uri::base', arg-desc CP#11
+  [13] = Null
+  [14] = StaticICData target 'dart.core::_Uri::file', arg-desc CP#9
+  [15] = ICData target-name 'resolveUri', arg-desc CP#2
+}
+]static method _scriptUri() → core::Uri {
+  if(self::_rawScript.{core::String::startsWith}("http:") || self::_rawScript.{core::String::startsWith}("https:") || self::_rawScript.{core::String::startsWith}("file:")) {
+    return core::Uri::parse(self::_rawScript);
+  }
+  else {
+    return core::Uri::base.{core::Uri::resolveUri}(core::_Uri::file(self::_rawScript));
+  }
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  PushConstant         CP#2
+  IndirectStaticCall   1, CP#1
+  Drop1
+  PushConstant         CP#3
+  ReturnTOS
+}
+ConstantPool {
+  [0] = TearOff #lib::_scriptUri
+  [1] = ArgDesc num-args 1, num-type-args 0, names []
+  [2] = StaticICData target '#lib::VMLibraryHooks::platformScript', arg-desc CP#1
+  [3] = Null
+}
+]static method _setupHooks() → dynamic {
+  self::VMLibraryHooks::platformScript = self::_scriptUri;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]static method main() → dynamic {}
diff --git a/pkg/vm/testcases/bytecode/field_initializers.dart b/pkg/vm/testcases/bytecode/field_initializers.dart
new file mode 100644
index 0000000..6d9f57e
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/field_initializers.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+  int foo1;
+  int foo2 = null;
+  int foo3 = 42;
+  int foo4;
+  int foo5 = 43;
+
+  A(this.foo4) : foo5 = 44;
+  A.constr2(int x, int y)
+      : foo1 = x,
+        foo5 = y + 1;
+
+  A.redirecting1() : this(45);
+  A.redirecting2(int a, int b, int c) : this.constr2(a, b * c);
+}
+
+class B extends A {
+  int foo6 = 46;
+  static int foo7 = 47;
+  static const int foo8 = 48;
+
+  B() : super(49);
+  B.c2(int i, int j)
+      : foo6 = 50,
+        super.redirecting2(i, j, 51);
+}
+
+main() {}
diff --git a/pkg/vm/testcases/bytecode/field_initializers.dart.expect b/pkg/vm/testcases/bytecode/field_initializers.dart.expect
new file mode 100644
index 0000000..b11ce7f
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/field_initializers.dart.expect
@@ -0,0 +1,217 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int foo1;
+  field core::int foo2 = null;
+  field core::int foo3 = 42;
+  field core::int foo4;
+  field core::int foo5 = 43;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-6]
+  PushConstant         CP#0
+  StoreFieldTOS        CP#1
+  Push                 FP[-6]
+  Push                 FP[-5]
+  StoreFieldTOS        CP#2
+  Push                 FP[-6]
+  PushConstant         CP#3
+  StoreFieldTOS        CP#4
+  Push                 FP[-6]
+  PushConstant         CP#6
+  IndirectStaticCall   1, CP#5
+  Drop1
+  PushConstant         CP#7
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 42
+  [1] = FieldOffset #lib::A::foo3
+  [2] = FieldOffset #lib::A::foo4
+  [3] = Int 44
+  [4] = FieldOffset #lib::A::foo5
+  [5] = ArgDesc num-args 1, num-type-args 0, names []
+  [6] = StaticICData target 'dart.core::Object::', arg-desc CP#5
+  [7] = Null
+}
+]  constructor •(core::int foo4) → void
+    : self::A::foo1 = null, self::A::foo4 = foo4, self::A::foo5 = 44, super core::Object::•()
+    ;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-7]
+  PushConstant         CP#0
+  StoreFieldTOS        CP#1
+  Push                 FP[-7]
+  Push                 FP[-6]
+  StoreFieldTOS        CP#2
+  Push                 FP[-7]
+  Push                 FP[-5]
+  PushConstant         CP#3
+  InstanceCall1        2, CP#5
+  StoreFieldTOS        CP#6
+  Push                 FP[-7]
+  PushConstant         CP#8
+  IndirectStaticCall   1, CP#7
+  Drop1
+  PushConstant         CP#9
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 42
+  [1] = FieldOffset #lib::A::foo3
+  [2] = FieldOffset #lib::A::foo1
+  [3] = Int 1
+  [4] = ArgDesc num-args 2, num-type-args 0, names []
+  [5] = ICData target-name '+', arg-desc CP#4
+  [6] = FieldOffset #lib::A::foo5
+  [7] = ArgDesc num-args 1, num-type-args 0, names []
+  [8] = StaticICData target 'dart.core::Object::', arg-desc CP#7
+  [9] = Null
+}
+]  constructor constr2(core::int x, core::int y) → void
+    : self::A::foo4 = null, self::A::foo1 = x, self::A::foo5 = y.{core::num::+}(1), super core::Object::•()
+    ;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  PushConstant         CP#0
+  PushConstant         CP#2
+  IndirectStaticCall   2, CP#1
+  Drop1
+  PushConstant         CP#3
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 45
+  [1] = ArgDesc num-args 2, num-type-args 0, names []
+  [2] = StaticICData target '#lib::A::', arg-desc CP#1
+  [3] = Null
+}
+]  constructor redirecting1() → void
+    : this self::A::•(45)
+    ;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-8]
+  Push                 FP[-7]
+  Push                 FP[-6]
+  Push                 FP[-5]
+  InstanceCall1        2, CP#1
+  PushConstant         CP#3
+  IndirectStaticCall   3, CP#2
+  Drop1
+  PushConstant         CP#4
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 2, num-type-args 0, names []
+  [1] = ICData target-name '*', arg-desc CP#0
+  [2] = ArgDesc num-args 3, num-type-args 0, names []
+  [3] = StaticICData target '#lib::A::constr2', arg-desc CP#2
+  [4] = Null
+}
+]  constructor redirecting2(core::int a, core::int b, core::int c) → void
+    : this self::A::constr2(a, b.{core::num::*}(c))
+    ;
+}
+class B extends self::A {
+  field core::int foo6 = 46;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 47
+}
+]  static field core::int foo7 = 47;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 48
+}
+]  static const field core::int foo8 = 48;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  PushConstant         CP#0
+  StoreFieldTOS        CP#1
+  Push                 FP[-5]
+  PushConstant         CP#2
+  PushConstant         CP#4
+  IndirectStaticCall   2, CP#3
+  Drop1
+  PushConstant         CP#5
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 46
+  [1] = FieldOffset #lib::B::foo6
+  [2] = Int 49
+  [3] = ArgDesc num-args 2, num-type-args 0, names []
+  [4] = StaticICData target '#lib::A::', arg-desc CP#3
+  [5] = Null
+}
+]  constructor •() → void
+    : super self::A::•(49)
+    ;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-7]
+  PushConstant         CP#0
+  StoreFieldTOS        CP#1
+  Push                 FP[-7]
+  Push                 FP[-6]
+  Push                 FP[-5]
+  PushConstant         CP#2
+  PushConstant         CP#4
+  IndirectStaticCall   4, CP#3
+  Drop1
+  PushConstant         CP#5
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 50
+  [1] = FieldOffset #lib::B::foo6
+  [2] = Int 51
+  [3] = ArgDesc num-args 4, num-type-args 0, names []
+  [4] = StaticICData target '#lib::A::redirecting2', arg-desc CP#3
+  [5] = Null
+}
+]  constructor c2(core::int i, core::int j) → void
+    : self::B::foo6 = 50, super self::A::redirecting2(i, j, 51)
+    ;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]static method main() → dynamic {}
diff --git a/pkg/vm/testcases/bytecode/hello.dart b/pkg/vm/testcases/bytecode/hello.dart
new file mode 100644
index 0000000..65a1a2a
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/hello.dart
@@ -0,0 +1,7 @@
+// 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.
+
+main() {
+  print('Hello, Dart Bytecode!');
+}
diff --git a/pkg/vm/testcases/bytecode/hello.dart.expect b/pkg/vm/testcases/bytecode/hello.dart.expect
new file mode 100644
index 0000000..7147dbc
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/hello.dart.expect
@@ -0,0 +1,24 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  PushConstant         CP#2
+  IndirectStaticCall   1, CP#1
+  Drop1
+  PushConstant         CP#3
+  ReturnTOS
+}
+ConstantPool {
+  [0] = String 'Hello, Dart Bytecode!'
+  [1] = ArgDesc num-args 1, num-type-args 0, names []
+  [2] = StaticICData target 'dart.core::print', arg-desc CP#1
+  [3] = Null
+}
+]static method main() → dynamic {
+  core::print("Hello, Dart Bytecode!");
+}
diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart b/pkg/vm/testcases/bytecode/instance_creation.dart
new file mode 100644
index 0000000..98259da
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart
@@ -0,0 +1,45 @@
+// 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.
+
+class Base<T1, T2> {
+  T1 t1;
+  T2 t2;
+
+  Base() {
+    print('Base: $T1, $T2');
+  }
+}
+
+class A extends Base<int, String> {
+  A(String s);
+}
+
+class B<T> extends Base<List<T>, String> {
+  B() {
+    print('B: $T');
+  }
+}
+
+class C {
+  C(String s) {
+    print('C: $s');
+  }
+}
+
+foo1() => new C('hello');
+
+void foo2() {
+  new A('hi');
+  new B<int>();
+}
+
+void foo3<T>() {
+  new B<List<T>>();
+}
+
+main() {
+  foo1();
+  foo2();
+  foo3<String>();
+}
diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart.expect b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
new file mode 100644
index 0000000..e4dca47
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
@@ -0,0 +1,315 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+class Base<T1 extends core::Object, T2 extends core::Object> extends core::Object {
+  generic-covariant-impl generic-covariant-interface field self::Base::T1 t1 = null;
+  generic-covariant-impl generic-covariant-interface field self::Base::T2 t2 = null;
+[@vm.bytecode=
+Bytecode {
+  Entry                1
+  CheckStack
+  Push                 FP[-5]
+  PushConstant         CP#1
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#2
+  PushConstant         CP#3
+  CreateArrayTOS
+  StoreLocal           r0
+  Push                 r0
+  PushConstant         CP#4
+  PushConstant         CP#5
+  StoreIndexedTOS
+  Push                 r0
+  PushConstant         CP#6
+  Push                 FP[-5]
+  LoadFieldTOS         CP#8
+  PushConstant         CP#2
+  InstantiateType      CP#7
+  StoreIndexedTOS
+  Push                 r0
+  PushConstant         CP#9
+  PushConstant         CP#10
+  StoreIndexedTOS
+  Push                 r0
+  PushConstant         CP#11
+  Push                 FP[-5]
+  LoadFieldTOS         CP#8
+  PushConstant         CP#2
+  InstantiateType      CP#12
+  StoreIndexedTOS
+  PushConstant         CP#13
+  IndirectStaticCall   1, CP#0
+  PushConstant         CP#14
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = StaticICData target 'dart.core::Object::', arg-desc CP#0
+  [2] = Null
+  [3] = Int 4
+  [4] = Int 0
+  [5] = String 'Base: '
+  [6] = Int 1
+  [7] = Type #lib::Base::T1
+  [8] = TypeArgumentsFieldOffset #lib::Base
+  [9] = Int 2
+  [10] = String ', '
+  [11] = Int 3
+  [12] = Type #lib::Base::T2
+  [13] = StaticICData target 'dart.core::_StringBase::_interpolate', arg-desc CP#0
+  [14] = StaticICData target 'dart.core::print', arg-desc CP#0
+}
+]  constructor •() → void
+    : super core::Object::•() {
+    core::print("Base: ${self::Base::T1}, ${self::Base::T2}");
+  }
+}
+class A extends self::Base<core::int, core::String> {
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-6]
+  PushConstant         CP#1
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = StaticICData target '#lib::Base::', arg-desc CP#0
+  [2] = Null
+}
+]  constructor •(core::String s) → void
+    : super self::Base::•()
+    ;
+  abstract forwarding-stub set t1(generic-covariant-impl core::int _) → void;
+  abstract forwarding-stub set t2(generic-covariant-impl core::String _) → void;
+}
+class B<T extends core::Object> extends self::Base<core::List<self::B::T>, core::String> {
+[@vm.bytecode=
+Bytecode {
+  Entry                1
+  CheckStack
+  Push                 FP[-5]
+  PushConstant         CP#1
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#2
+  PushConstant         CP#3
+  CreateArrayTOS
+  StoreLocal           r0
+  Push                 r0
+  PushConstant         CP#4
+  PushConstant         CP#5
+  StoreIndexedTOS
+  Push                 r0
+  PushConstant         CP#6
+  Push                 FP[-5]
+  LoadFieldTOS         CP#8
+  PushConstant         CP#2
+  InstantiateType      CP#7
+  StoreIndexedTOS
+  PushConstant         CP#9
+  IndirectStaticCall   1, CP#0
+  PushConstant         CP#10
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = StaticICData target '#lib::Base::', arg-desc CP#0
+  [2] = Null
+  [3] = Int 2
+  [4] = Int 0
+  [5] = String 'B: '
+  [6] = Int 1
+  [7] = Type #lib::B::T
+  [8] = TypeArgumentsFieldOffset #lib::B
+  [9] = StaticICData target 'dart.core::_StringBase::_interpolate', arg-desc CP#0
+  [10] = StaticICData target 'dart.core::print', arg-desc CP#0
+}
+]  constructor •() → void
+    : super self::Base::•() {
+    core::print("B: ${self::B::T}");
+  }
+  abstract forwarding-stub set t2(generic-covariant-impl core::String _) → void;
+}
+class C extends core::Object {
+[@vm.bytecode=
+Bytecode {
+  Entry                1
+  CheckStack
+  Push                 FP[-6]
+  PushConstant         CP#1
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#2
+  PushConstant         CP#3
+  CreateArrayTOS
+  StoreLocal           r0
+  Push                 r0
+  PushConstant         CP#4
+  PushConstant         CP#5
+  StoreIndexedTOS
+  Push                 r0
+  PushConstant         CP#6
+  Push                 FP[-5]
+  StoreIndexedTOS
+  PushConstant         CP#7
+  IndirectStaticCall   1, CP#0
+  PushConstant         CP#8
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = StaticICData target 'dart.core::Object::', arg-desc CP#0
+  [2] = Null
+  [3] = Int 2
+  [4] = Int 0
+  [5] = String 'C: '
+  [6] = Int 1
+  [7] = StaticICData target 'dart.core::_StringBase::_interpolate', arg-desc CP#0
+  [8] = StaticICData target 'dart.core::print', arg-desc CP#0
+}
+]  constructor •(core::String s) → void
+    : super core::Object::•() {
+    core::print("C: ${s}");
+  }
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                1
+  CheckStack
+  Allocate             CP#0
+  StoreLocal           r0
+  Push                 r0
+  PushConstant         CP#1
+  PushConstant         CP#3
+  IndirectStaticCall   2, CP#2
+  Drop1
+  ReturnTOS
+  PushConstant         CP#4
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Class #lib::C
+  [1] = String 'hello'
+  [2] = ArgDesc num-args 2, num-type-args 0, names []
+  [3] = StaticICData target '#lib::C::', arg-desc CP#2
+  [4] = Null
+}
+]static method foo1() → dynamic
+  return new self::C::•("hello");
+[@vm.bytecode=
+Bytecode {
+  Entry                2
+  CheckStack
+  PushConstant         CP#1
+  PushConstant         CP#0
+  AllocateT
+  StoreLocal           r0
+  Push                 r0
+  PushConstant         CP#2
+  PushConstant         CP#4
+  IndirectStaticCall   2, CP#3
+  Drop1
+  Drop1
+  PushConstant         CP#6
+  PushConstant         CP#5
+  AllocateT
+  StoreLocal           r1
+  Push                 r1
+  PushConstant         CP#8
+  IndirectStaticCall   1, CP#7
+  Drop1
+  Drop1
+  PushConstant         CP#9
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Class #lib::A
+  [1] = TypeArgs [dart.core::int, dart.core::String]
+  [2] = String 'hi'
+  [3] = ArgDesc num-args 2, num-type-args 0, names []
+  [4] = StaticICData target '#lib::A::', arg-desc CP#3
+  [5] = Class #lib::B
+  [6] = TypeArgs [dart.core::List<dart.core::int>, dart.core::String, dart.core::int]
+  [7] = ArgDesc num-args 1, num-type-args 0, names []
+  [8] = StaticICData target '#lib::B::', arg-desc CP#7
+  [9] = Null
+}
+]static method foo2() → void {
+  new self::A::•("hi");
+  new self::B::•<core::int>();
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                1
+  CheckStack
+  PushConstant         CP#2
+  Push                 FP[-5]
+  InstantiateTypeArgumentsTOS 1, CP#1
+  PushConstant         CP#0
+  AllocateT
+  StoreLocal           r0
+  Push                 r0
+  PushConstant         CP#4
+  IndirectStaticCall   1, CP#3
+  Drop1
+  Drop1
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Class #lib::B
+  [1] = TypeArgs [dart.core::List<dart.core::List<#lib::foo3::T>>, dart.core::String, dart.core::List<#lib::foo3::T>]
+  [2] = Null
+  [3] = ArgDesc num-args 1, num-type-args 0, names []
+  [4] = StaticICData target '#lib::B::', arg-desc CP#3
+}
+]static method foo3<T extends core::Object>() → void {
+  new self::B::•<core::List<self::foo3::T>>();
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#1
+  IndirectStaticCall   0, CP#0
+  Drop1
+  PushConstant         CP#2
+  IndirectStaticCall   0, CP#0
+  Drop1
+  PushConstant         CP#3
+  PushConstant         CP#5
+  IndirectStaticCall   1, CP#4
+  Drop1
+  PushConstant         CP#6
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 0, num-type-args 0, names []
+  [1] = StaticICData target '#lib::foo1', arg-desc CP#0
+  [2] = StaticICData target '#lib::foo2', arg-desc CP#0
+  [3] = TypeArgs [dart.core::String]
+  [4] = ArgDesc num-args 0, num-type-args 1, names []
+  [5] = StaticICData target '#lib::foo3', arg-desc CP#4
+  [6] = Null
+}
+]static method main() → dynamic {
+  self::foo1();
+  self::foo2();
+  self::foo3<core::String>();
+}
diff --git a/pkg/vm/testcases/bytecode/literals.dart b/pkg/vm/testcases/bytecode/literals.dart
new file mode 100644
index 0000000..69a0e85
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/literals.dart
@@ -0,0 +1,75 @@
+// 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.
+
+enum A {
+  elem1,
+  elem2,
+  elem3,
+  elem4,
+}
+
+class B {
+  final int i;
+  const B(this.i);
+}
+
+class C extends B {
+  final int j;
+  const C(int a, int b, int c)
+      : j = a + b,
+        super(c * 5);
+}
+
+class D {
+  final x;
+  final y;
+  const D(this.x, [this.y]);
+}
+
+const c1 = A.elem3;
+const c2 = 'hello!';
+const c3 = c2.length;
+const c4 = const C(1, 2, 3);
+const c5 = const D(const B(4));
+
+void test_constants1() {
+  print(c1);
+  print(c2);
+  print(c3);
+  print(c4);
+  print(c5);
+}
+
+void test_constants2() {
+  print(42);
+  print('foo');
+  print(A.elem2);
+  print(const [42, 'foo']);
+  print(const <String, A>{'E2': A.elem2, 'E4': A.elem4});
+  print(
+      const D(const C(4, 5, 6), const {'foo': 42, 'bar': const B(c2.length)}));
+}
+
+void test_list_literal(int a) {
+  print([1, a, 3]);
+  print(<String>['a', a.toString(), 'b']);
+}
+
+void test_map_literal<T>(int a, int b, T c) {
+  print({1: a, b: 2});
+  print(<String, int>{'foo': a, b.toString(): 3});
+  print(<String, T>{});
+  print(<T, int>{c: 4});
+}
+
+void test_symbol() {
+  print(#test_symbol);
+}
+
+void test_type_literal<T>() {
+  print(String);
+  print(T);
+}
+
+main() {}
diff --git a/pkg/vm/testcases/bytecode/literals.dart.expect b/pkg/vm/testcases/bytecode/literals.dart.expect
new file mode 100644
index 0000000..b56cae6
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/literals.dart.expect
@@ -0,0 +1,677 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  final field core::int index;
+  final field core::String _name;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#13
+  ReturnTOS
+}
+ConstantPool {
+  [0] = TypeArgs []
+  [1] = Int 0
+  [2] = String 'A.elem1'
+  [3] = Instance #lib::A type-args CP#0 {index: 1, _name: 2}
+  [4] = Int 1
+  [5] = String 'A.elem2'
+  [6] = Instance #lib::A type-args CP#0 {index: 4, _name: 5}
+  [7] = Int 2
+  [8] = String 'A.elem3'
+  [9] = Instance #lib::A type-args CP#0 {index: 7, _name: 8}
+  [10] = Int 3
+  [11] = String 'A.elem4'
+  [12] = Instance #lib::A type-args CP#0 {index: 10, _name: 11}
+  [13] = List type-arg #lib::A, entries CP# [3, 6, 9, 12]
+}
+]  static const field core::List<self::A> values = const <self::A>[self::A::elem1, self::A::elem2, self::A::elem3, self::A::elem4];
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#3
+  ReturnTOS
+}
+ConstantPool {
+  [0] = TypeArgs []
+  [1] = Int 0
+  [2] = String 'A.elem1'
+  [3] = Instance #lib::A type-args CP#0 {index: 1, _name: 2}
+}
+]  static const field self::A elem1 = const self::A::•(0, "A.elem1");
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#3
+  ReturnTOS
+}
+ConstantPool {
+  [0] = TypeArgs []
+  [1] = Int 1
+  [2] = String 'A.elem2'
+  [3] = Instance #lib::A type-args CP#0 {index: 1, _name: 2}
+}
+]  static const field self::A elem2 = const self::A::•(1, "A.elem2");
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#3
+  ReturnTOS
+}
+ConstantPool {
+  [0] = TypeArgs []
+  [1] = Int 2
+  [2] = String 'A.elem3'
+  [3] = Instance #lib::A type-args CP#0 {index: 1, _name: 2}
+}
+]  static const field self::A elem3 = const self::A::•(2, "A.elem3");
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#3
+  ReturnTOS
+}
+ConstantPool {
+  [0] = TypeArgs []
+  [1] = Int 3
+  [2] = String 'A.elem4'
+  [3] = Instance #lib::A type-args CP#0 {index: 1, _name: 2}
+}
+]  static const field self::A elem4 = const self::A::•(3, "A.elem4");
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-7]
+  Push                 FP[-6]
+  StoreFieldTOS        CP#0
+  Push                 FP[-7]
+  Push                 FP[-5]
+  StoreFieldTOS        CP#1
+  Push                 FP[-7]
+  PushConstant         CP#3
+  IndirectStaticCall   1, CP#2
+  Drop1
+  PushConstant         CP#4
+  ReturnTOS
+}
+ConstantPool {
+  [0] = FieldOffset #lib::A::index
+  [1] = FieldOffset #lib::A::_name
+  [2] = ArgDesc num-args 1, num-type-args 0, names []
+  [3] = StaticICData target 'dart.core::Object::', arg-desc CP#2
+  [4] = Null
+}
+]  const constructor •(core::int index, core::String _name) → void
+    : self::A::index = index, self::A::_name = _name, super core::Object::•()
+    ;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  PushConstant         CP#1
+  IndirectStaticCall   1, CP#0
+  ReturnTOS
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = StaticICData target '#lib::A::_name', arg-desc CP#0
+  [2] = Null
+}
+]  method toString() → core::String
+    return this.{=self::A::_name};
+}
+class B extends core::Object {
+  final field core::int i;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-6]
+  Push                 FP[-5]
+  StoreFieldTOS        CP#0
+  Push                 FP[-6]
+  PushConstant         CP#2
+  IndirectStaticCall   1, CP#1
+  Drop1
+  PushConstant         CP#3
+  ReturnTOS
+}
+ConstantPool {
+  [0] = FieldOffset #lib::B::i
+  [1] = ArgDesc num-args 1, num-type-args 0, names []
+  [2] = StaticICData target 'dart.core::Object::', arg-desc CP#1
+  [3] = Null
+}
+]  const constructor •(core::int i) → void
+    : self::B::i = i, super core::Object::•()
+    ;
+}
+class C extends self::B {
+  final field core::int j;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-8]
+  Push                 FP[-7]
+  Push                 FP[-6]
+  InstanceCall1        2, CP#1
+  StoreFieldTOS        CP#2
+  Push                 FP[-8]
+  Push                 FP[-5]
+  PushConstant         CP#3
+  InstanceCall1        2, CP#4
+  PushConstant         CP#5
+  IndirectStaticCall   2, CP#0
+  Drop1
+  PushConstant         CP#6
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 2, num-type-args 0, names []
+  [1] = ICData target-name '+', arg-desc CP#0
+  [2] = FieldOffset #lib::C::j
+  [3] = Int 5
+  [4] = ICData target-name '*', arg-desc CP#0
+  [5] = StaticICData target '#lib::B::', arg-desc CP#0
+  [6] = Null
+}
+]  const constructor •(core::int a, core::int b, core::int c) → void
+    : self::C::j = a.{core::num::+}(b), super self::B::•(c.{core::num::*}(5))
+    ;
+}
+class D extends core::Object {
+  final field dynamic x;
+  final field dynamic y;
+[@vm.bytecode=
+Bytecode {
+  EntryOptional        2, 1, 0
+  LoadConstant         r2, CP#0
+  Frame                0
+  CheckStack
+  Push                 r0
+  Push                 r1
+  StoreFieldTOS        CP#1
+  Push                 r0
+  Push                 r2
+  StoreFieldTOS        CP#2
+  Push                 r0
+  PushConstant         CP#4
+  IndirectStaticCall   1, CP#3
+  Drop1
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+  [1] = FieldOffset #lib::D::x
+  [2] = FieldOffset #lib::D::y
+  [3] = ArgDesc num-args 1, num-type-args 0, names []
+  [4] = StaticICData target 'dart.core::Object::', arg-desc CP#3
+}
+]  const constructor •(dynamic x, [dynamic y = null]) → void
+    : self::D::x = x, self::D::y = y, super core::Object::•()
+    ;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#3
+  ReturnTOS
+}
+ConstantPool {
+  [0] = TypeArgs []
+  [1] = Int 2
+  [2] = String 'A.elem3'
+  [3] = Instance #lib::A type-args CP#0 {index: 1, _name: 2}
+}
+]static const field self::A c1 = self::A::elem3;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = String 'hello!'
+}
+]static const field core::String c2 = "hello!";
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 6
+}
+]static const field core::int c3 = self::c2.{core::String::length};
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#3
+  ReturnTOS
+}
+ConstantPool {
+  [0] = TypeArgs []
+  [1] = Int 3
+  [2] = Int 15
+  [3] = Instance #lib::C type-args CP#0 {j: 1, i: 2}
+}
+]static const field self::C c4 = const self::C::•(1, 2, 3);
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#4
+  ReturnTOS
+}
+ConstantPool {
+  [0] = TypeArgs []
+  [1] = Int 4
+  [2] = Instance #lib::B type-args CP#0 {i: 1}
+  [3] = Null
+  [4] = Instance #lib::D type-args CP#0 {x: 2, y: 3}
+}
+]static const field self::D c5 = const self::D::•(const self::B::•(4));
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#3
+  PushConstant         CP#5
+  IndirectStaticCall   1, CP#4
+  Drop1
+  PushConstant         CP#6
+  PushConstant         CP#7
+  IndirectStaticCall   1, CP#4
+  Drop1
+  PushConstant         CP#8
+  PushConstant         CP#9
+  IndirectStaticCall   1, CP#4
+  Drop1
+  PushConstant         CP#12
+  PushConstant         CP#13
+  IndirectStaticCall   1, CP#4
+  Drop1
+  PushConstant         CP#17
+  PushConstant         CP#18
+  IndirectStaticCall   1, CP#4
+  Drop1
+  PushConstant         CP#16
+  ReturnTOS
+}
+ConstantPool {
+  [0] = TypeArgs []
+  [1] = Int 2
+  [2] = String 'A.elem3'
+  [3] = Instance #lib::A type-args CP#0 {index: 1, _name: 2}
+  [4] = ArgDesc num-args 1, num-type-args 0, names []
+  [5] = StaticICData target 'dart.core::print', arg-desc CP#4
+  [6] = String 'hello!'
+  [7] = StaticICData target 'dart.core::print', arg-desc CP#4
+  [8] = Int 6
+  [9] = StaticICData target 'dart.core::print', arg-desc CP#4
+  [10] = Int 3
+  [11] = Int 15
+  [12] = Instance #lib::C type-args CP#0 {j: 10, i: 11}
+  [13] = StaticICData target 'dart.core::print', arg-desc CP#4
+  [14] = Int 4
+  [15] = Instance #lib::B type-args CP#0 {i: 14}
+  [16] = Null
+  [17] = Instance #lib::D type-args CP#0 {x: 15, y: 16}
+  [18] = StaticICData target 'dart.core::print', arg-desc CP#4
+}
+]static method test_constants1() → void {
+  core::print(self::c1);
+  core::print(self::c2);
+  core::print(self::c3);
+  core::print(self::c4);
+  core::print(self::c5);
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  PushConstant         CP#2
+  IndirectStaticCall   1, CP#1
+  Drop1
+  PushConstant         CP#3
+  PushConstant         CP#4
+  IndirectStaticCall   1, CP#1
+  Drop1
+  PushConstant         CP#8
+  PushConstant         CP#9
+  IndirectStaticCall   1, CP#1
+  Drop1
+  PushConstant         CP#10
+  PushConstant         CP#11
+  IndirectStaticCall   1, CP#1
+  Drop1
+  PushConstant         CP#19
+  PushConstant         CP#20
+  IndirectStaticCall   1, CP#1
+  Drop1
+  PushConstant         CP#30
+  PushConstant         CP#31
+  IndirectStaticCall   1, CP#1
+  Drop1
+  PushConstant         CP#32
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 42
+  [1] = ArgDesc num-args 1, num-type-args 0, names []
+  [2] = StaticICData target 'dart.core::print', arg-desc CP#1
+  [3] = String 'foo'
+  [4] = StaticICData target 'dart.core::print', arg-desc CP#1
+  [5] = TypeArgs []
+  [6] = Int 1
+  [7] = String 'A.elem2'
+  [8] = Instance #lib::A type-args CP#5 {index: 6, _name: 7}
+  [9] = StaticICData target 'dart.core::print', arg-desc CP#1
+  [10] = List type-arg dart.core::Object, entries CP# [0, 3]
+  [11] = StaticICData target 'dart.core::print', arg-desc CP#1
+  [12] = TypeArgs [dart.core::String, #lib::A]
+  [13] = String 'E2'
+  [14] = String 'E4'
+  [15] = Int 3
+  [16] = String 'A.elem4'
+  [17] = Instance #lib::A type-args CP#5 {index: 15, _name: 16}
+  [18] = List type-arg dynamic, entries CP# [13, 8, 14, 17]
+  [19] = Instance dart.core::_ImmutableMap type-args CP#12 {_kvPairs: 18}
+  [20] = StaticICData target 'dart.core::print', arg-desc CP#1
+  [21] = Int 9
+  [22] = Int 30
+  [23] = Instance #lib::C type-args CP#5 {j: 21, i: 22}
+  [24] = TypeArgs [dart.core::String, dart.core::Object]
+  [25] = String 'bar'
+  [26] = Int 6
+  [27] = Instance #lib::B type-args CP#5 {i: 26}
+  [28] = List type-arg dynamic, entries CP# [3, 0, 25, 27]
+  [29] = Instance dart.core::_ImmutableMap type-args CP#24 {_kvPairs: 28}
+  [30] = Instance #lib::D type-args CP#5 {x: 23, y: 29}
+  [31] = StaticICData target 'dart.core::print', arg-desc CP#1
+  [32] = Null
+}
+]static method test_constants2() → void {
+  core::print(42);
+  core::print("foo");
+  core::print(self::A::elem2);
+  core::print(const <core::Object>[42, "foo"]);
+  core::print(const <core::String, self::A>{"E2": self::A::elem2, "E4": self::A::elem4});
+  core::print(const self::D::•(const self::C::•(4, 5, 6), const <core::String, core::Object>{"foo": 42, "bar": const self::B::•(self::c2.{core::String::length})}));
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                2
+  CheckStack
+  PushConstant         CP#0
+  StoreLocal           r0
+  Push                 r0
+  PushConstant         CP#1
+  CreateArrayTOS
+  StoreLocal           r0
+  Push                 r0
+  PushConstant         CP#2
+  PushConstant         CP#3
+  StoreIndexedTOS
+  Push                 r0
+  PushConstant         CP#3
+  Push                 FP[-5]
+  StoreIndexedTOS
+  Push                 r0
+  PushConstant         CP#4
+  PushConstant         CP#1
+  StoreIndexedTOS
+  PushConstant         CP#6
+  IndirectStaticCall   2, CP#5
+  PushConstant         CP#8
+  IndirectStaticCall   1, CP#7
+  Drop1
+  PushConstant         CP#9
+  StoreLocal           r1
+  Push                 r1
+  PushConstant         CP#1
+  CreateArrayTOS
+  StoreLocal           r1
+  Push                 r1
+  PushConstant         CP#2
+  PushConstant         CP#10
+  StoreIndexedTOS
+  Push                 r1
+  PushConstant         CP#3
+  Push                 FP[-5]
+  InstanceCall1        1, CP#11
+  StoreIndexedTOS
+  Push                 r1
+  PushConstant         CP#4
+  PushConstant         CP#12
+  StoreIndexedTOS
+  PushConstant         CP#13
+  IndirectStaticCall   2, CP#5
+  PushConstant         CP#14
+  IndirectStaticCall   1, CP#7
+  Drop1
+  PushConstant         CP#15
+  ReturnTOS
+}
+ConstantPool {
+  [0] = TypeArgs [dart.core::int]
+  [1] = Int 3
+  [2] = Int 0
+  [3] = Int 1
+  [4] = Int 2
+  [5] = ArgDesc num-args 1, num-type-args 1, names []
+  [6] = StaticICData target 'dart.core::List::_fromLiteral', arg-desc CP#5
+  [7] = ArgDesc num-args 1, num-type-args 0, names []
+  [8] = StaticICData target 'dart.core::print', arg-desc CP#7
+  [9] = TypeArgs [dart.core::String]
+  [10] = String 'a'
+  [11] = ICData target-name 'toString', arg-desc CP#7
+  [12] = String 'b'
+  [13] = StaticICData target 'dart.core::List::_fromLiteral', arg-desc CP#5
+  [14] = StaticICData target 'dart.core::print', arg-desc CP#7
+  [15] = Null
+}
+]static method test_list_literal(core::int a) → void {
+  core::print(<core::int>[1, a, 3]);
+  core::print(<core::String>["a", a.{core::int::toString}(), "b"]);
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                4
+  CheckStack
+  PushConstant         CP#0
+  PushConstant         CP#1
+  PushConstant         CP#2
+  CreateArrayTOS
+  StoreLocal           r0
+  Push                 r0
+  PushConstant         CP#3
+  PushConstant         CP#4
+  StoreIndexedTOS
+  Push                 r0
+  PushConstant         CP#4
+  Push                 FP[-7]
+  StoreIndexedTOS
+  Push                 r0
+  PushConstant         CP#5
+  Push                 FP[-6]
+  StoreIndexedTOS
+  Push                 r0
+  PushConstant         CP#6
+  PushConstant         CP#5
+  StoreIndexedTOS
+  PushConstant         CP#8
+  IndirectStaticCall   2, CP#7
+  PushConstant         CP#10
+  IndirectStaticCall   1, CP#9
+  Drop1
+  PushConstant         CP#11
+  PushConstant         CP#1
+  PushConstant         CP#2
+  CreateArrayTOS
+  StoreLocal           r1
+  Push                 r1
+  PushConstant         CP#3
+  PushConstant         CP#12
+  StoreIndexedTOS
+  Push                 r1
+  PushConstant         CP#4
+  Push                 FP[-7]
+  StoreIndexedTOS
+  Push                 r1
+  PushConstant         CP#5
+  Push                 FP[-6]
+  InstanceCall1        1, CP#13
+  StoreIndexedTOS
+  Push                 r1
+  PushConstant         CP#6
+  PushConstant         CP#6
+  StoreIndexedTOS
+  PushConstant         CP#14
+  IndirectStaticCall   2, CP#7
+  PushConstant         CP#15
+  IndirectStaticCall   1, CP#9
+  Drop1
+  PushConstant         CP#17
+  Push                 FP[-8]
+  InstantiateTypeArgumentsTOS 1, CP#16
+  PushConstant         CP#18
+  PushConstant         CP#19
+  IndirectStaticCall   2, CP#7
+  PushConstant         CP#20
+  IndirectStaticCall   1, CP#9
+  Drop1
+  PushConstant         CP#17
+  Push                 FP[-8]
+  InstantiateTypeArgumentsTOS 1, CP#21
+  PushConstant         CP#1
+  PushConstant         CP#5
+  CreateArrayTOS
+  StoreLocal           r3
+  Push                 r3
+  PushConstant         CP#3
+  Push                 FP[-5]
+  StoreIndexedTOS
+  Push                 r3
+  PushConstant         CP#4
+  PushConstant         CP#2
+  StoreIndexedTOS
+  PushConstant         CP#22
+  IndirectStaticCall   2, CP#7
+  PushConstant         CP#23
+  IndirectStaticCall   1, CP#9
+  Drop1
+  PushConstant         CP#17
+  ReturnTOS
+}
+ConstantPool {
+  [0] = TypeArgs [dart.core::int, dart.core::int]
+  [1] = TypeArgs [dynamic]
+  [2] = Int 4
+  [3] = Int 0
+  [4] = Int 1
+  [5] = Int 2
+  [6] = Int 3
+  [7] = ArgDesc num-args 1, num-type-args 1, names []
+  [8] = StaticICData target 'dart.core::Map::_fromLiteral', arg-desc CP#7
+  [9] = ArgDesc num-args 1, num-type-args 0, names []
+  [10] = StaticICData target 'dart.core::print', arg-desc CP#9
+  [11] = TypeArgs [dart.core::String, dart.core::int]
+  [12] = String 'foo'
+  [13] = ICData target-name 'toString', arg-desc CP#9
+  [14] = StaticICData target 'dart.core::Map::_fromLiteral', arg-desc CP#7
+  [15] = StaticICData target 'dart.core::print', arg-desc CP#9
+  [16] = TypeArgs [dart.core::String, #lib::test_map_literal::T]
+  [17] = Null
+  [18] = List type-arg dynamic, entries CP# []
+  [19] = StaticICData target 'dart.core::Map::_fromLiteral', arg-desc CP#7
+  [20] = StaticICData target 'dart.core::print', arg-desc CP#9
+  [21] = TypeArgs [#lib::test_map_literal::T, dart.core::int]
+  [22] = StaticICData target 'dart.core::Map::_fromLiteral', arg-desc CP#7
+  [23] = StaticICData target 'dart.core::print', arg-desc CP#9
+}
+]static method test_map_literal<T extends core::Object>(core::int a, core::int b, self::test_map_literal::T c) → void {
+  core::print(<core::int, core::int>{1: a, b: 2});
+  core::print(<core::String, core::int>{"foo": a, b.{core::int::toString}(): 3});
+  core::print(<core::String, self::test_map_literal::T>{});
+  core::print(<self::test_map_literal::T, core::int>{c: 4});
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  PushConstant         CP#2
+  IndirectStaticCall   1, CP#1
+  Drop1
+  PushConstant         CP#3
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Symbol 'test_symbol'
+  [1] = ArgDesc num-args 1, num-type-args 0, names []
+  [2] = StaticICData target 'dart.core::print', arg-desc CP#1
+  [3] = Null
+}
+]static method test_symbol() → void {
+  core::print(#test_symbol);
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  PushConstant         CP#2
+  IndirectStaticCall   1, CP#1
+  Drop1
+  PushConstant         CP#4
+  Push                 FP[-5]
+  InstantiateType      CP#3
+  PushConstant         CP#5
+  IndirectStaticCall   1, CP#1
+  Drop1
+  PushConstant         CP#4
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Type dart.core::String
+  [1] = ArgDesc num-args 1, num-type-args 0, names []
+  [2] = StaticICData target 'dart.core::print', arg-desc CP#1
+  [3] = Type #lib::test_type_literal::T
+  [4] = Null
+  [5] = StaticICData target 'dart.core::print', arg-desc CP#1
+}
+]static method test_type_literal<T extends core::Object>() → void {
+  core::print(core::String);
+  core::print(self::test_type_literal::T);
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]static method main() → dynamic {}
diff --git a/pkg/vm/testcases/bytecode/loops.dart b/pkg/vm/testcases/bytecode/loops.dart
new file mode 100644
index 0000000..a2d2d10
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/loops.dart
@@ -0,0 +1,62 @@
+// 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.
+
+int test_for(List<int> list) {
+  int sum = 0;
+  for (int i = 0; i < list.length; i++) {
+    sum = sum + list[i];
+  }
+  return sum;
+}
+
+int test_for_break(List<int> list) {
+  int sum = 0;
+  for (int i = 0; i >= 0; i++) {
+    if (i >= list.length) {
+      break;
+    }
+    sum = sum + list[i];
+  }
+  return sum;
+}
+
+int test_for_continue(List<int> list) {
+  int sum = 0;
+  for (int i = -100; i < list.length; i++) {
+    if (i < 0) {
+      continue;
+    }
+    sum = sum + list[i];
+  }
+  return sum;
+}
+
+int test_while(List<int> list) {
+  int sum = 0;
+  int i = 0;
+  while (i < list.length) {
+    sum = sum + list[i++];
+  }
+  return sum;
+}
+
+int test_do_while(List<int> list) {
+  int sum = 0;
+  int i = 0;
+  do {
+    sum = sum + list[i];
+    ++i;
+  } while (i < list.length);
+  return sum;
+}
+
+int test_for_in(List<int> list) {
+  int sum = 0;
+  for (var e in list) {
+    sum = sum + e;
+  }
+  return sum;
+}
+
+main() {}
diff --git a/pkg/vm/testcases/bytecode/loops.dart.expect b/pkg/vm/testcases/bytecode/loops.dart.expect
new file mode 100644
index 0000000..a23aa00
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/loops.dart.expect
@@ -0,0 +1,379 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+[@vm.bytecode=
+Bytecode {
+  Entry                2
+  CheckStack
+  PushConstant         CP#0
+  PopLocal             r0
+  PushConstant         CP#0
+  PopLocal             r1
+L2:
+  CheckStack
+  Push                 r1
+  Push                 FP[-5]
+  InstanceCall1        1, CP#2
+  InstanceCall1        2, CP#4
+  PushConstant         CP#5
+  IfNeStrictTOS
+  Jump                 L1
+  Push                 r0
+  Push                 FP[-5]
+  Push                 r1
+  InstanceCall1        2, CP#6
+  InstanceCall1        2, CP#7
+  StoreLocal           r0
+  Drop1
+  Push                 r1
+  PushConstant         CP#8
+  InstanceCall1        2, CP#9
+  StoreLocal           r1
+  Drop1
+  Jump                 L2
+L1:
+  Push                 r0
+  ReturnTOS
+  PushConstant         CP#10
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 0
+  [1] = ArgDesc num-args 1, num-type-args 0, names []
+  [2] = ICData target-name 'get:length', arg-desc CP#1
+  [3] = ArgDesc num-args 2, num-type-args 0, names []
+  [4] = ICData target-name '<', arg-desc CP#3
+  [5] = Bool true
+  [6] = ICData target-name '[]', arg-desc CP#3
+  [7] = ICData target-name '+', arg-desc CP#3
+  [8] = Int 1
+  [9] = ICData target-name '+', arg-desc CP#3
+  [10] = Null
+}
+]static method test_for(core::List<core::int> list) → core::int {
+  core::int sum = 0;
+  for (core::int i = 0; i.{core::num::<}(list.{core::List::length}); i = i.{core::num::+}(1)) {
+    sum = sum.{core::num::+}(list.{core::List::[]}(i));
+  }
+  return sum;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                2
+  CheckStack
+  PushConstant         CP#0
+  PopLocal             r0
+  PushConstant         CP#0
+  PopLocal             r1
+L3:
+  CheckStack
+  Push                 r1
+  PushConstant         CP#0
+  InstanceCall1        2, CP#2
+  PushConstant         CP#3
+  IfNeStrictTOS
+  Jump                 L1
+  Push                 r1
+  Push                 FP[-5]
+  InstanceCall1        1, CP#5
+  InstanceCall1        2, CP#6
+  PushConstant         CP#3
+  IfNeStrictTOS
+  Jump                 L2
+  Jump                 L1
+L2:
+  Push                 r0
+  Push                 FP[-5]
+  Push                 r1
+  InstanceCall1        2, CP#7
+  InstanceCall1        2, CP#8
+  StoreLocal           r0
+  Drop1
+  Push                 r1
+  PushConstant         CP#9
+  InstanceCall1        2, CP#10
+  StoreLocal           r1
+  Drop1
+  Jump                 L3
+L1:
+  Push                 r0
+  ReturnTOS
+  PushConstant         CP#11
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 0
+  [1] = ArgDesc num-args 2, num-type-args 0, names []
+  [2] = ICData target-name '>=', arg-desc CP#1
+  [3] = Bool true
+  [4] = ArgDesc num-args 1, num-type-args 0, names []
+  [5] = ICData target-name 'get:length', arg-desc CP#4
+  [6] = ICData target-name '>=', arg-desc CP#1
+  [7] = ICData target-name '[]', arg-desc CP#1
+  [8] = ICData target-name '+', arg-desc CP#1
+  [9] = Int 1
+  [10] = ICData target-name '+', arg-desc CP#1
+  [11] = Null
+}
+]static method test_for_break(core::List<core::int> list) → core::int {
+  core::int sum = 0;
+  #L1:
+  for (core::int i = 0; i.{core::num::>=}(0); i = i.{core::num::+}(1)) {
+    if(i.{core::num::>=}(list.{core::List::length})) {
+      break #L1;
+    }
+    sum = sum.{core::num::+}(list.{core::List::[]}(i));
+  }
+  return sum;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                2
+  CheckStack
+  PushConstant         CP#0
+  PopLocal             r0
+  PushConstant         CP#1
+  InstanceCall1        1, CP#3
+  PopLocal             r1
+L4:
+  CheckStack
+  Push                 r1
+  Push                 FP[-5]
+  InstanceCall1        1, CP#4
+  InstanceCall1        2, CP#6
+  PushConstant         CP#7
+  IfNeStrictTOS
+  Jump                 L1
+  Push                 r1
+  PushConstant         CP#0
+  InstanceCall1        2, CP#8
+  PushConstant         CP#7
+  IfNeStrictTOS
+  Jump                 L2
+  Jump                 L3
+L2:
+  Push                 r0
+  Push                 FP[-5]
+  Push                 r1
+  InstanceCall1        2, CP#9
+  InstanceCall1        2, CP#10
+  StoreLocal           r0
+  Drop1
+L3:
+  Push                 r1
+  PushConstant         CP#11
+  InstanceCall1        2, CP#12
+  StoreLocal           r1
+  Drop1
+  Jump                 L4
+L1:
+  Push                 r0
+  ReturnTOS
+  PushConstant         CP#13
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 0
+  [1] = Int 100
+  [2] = ArgDesc num-args 1, num-type-args 0, names []
+  [3] = ICData target-name 'unary-', arg-desc CP#2
+  [4] = ICData target-name 'get:length', arg-desc CP#2
+  [5] = ArgDesc num-args 2, num-type-args 0, names []
+  [6] = ICData target-name '<', arg-desc CP#5
+  [7] = Bool true
+  [8] = ICData target-name '<', arg-desc CP#5
+  [9] = ICData target-name '[]', arg-desc CP#5
+  [10] = ICData target-name '+', arg-desc CP#5
+  [11] = Int 1
+  [12] = ICData target-name '+', arg-desc CP#5
+  [13] = Null
+}
+]static method test_for_continue(core::List<core::int> list) → core::int {
+  core::int sum = 0;
+  for (core::int i = 100.{core::int::unary-}(); i.{core::num::<}(list.{core::List::length}); i = i.{core::num::+}(1))
+    #L2:
+    {
+      if(i.{core::num::<}(0)) {
+        break #L2;
+      }
+      sum = sum.{core::num::+}(list.{core::List::[]}(i));
+    }
+  return sum;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                4
+  CheckStack
+  PushConstant         CP#0
+  PopLocal             r0
+  PushConstant         CP#0
+  PopLocal             r1
+L2:
+  CheckStack
+  Push                 r1
+  Push                 FP[-5]
+  InstanceCall1        1, CP#2
+  InstanceCall1        2, CP#4
+  PushConstant         CP#5
+  IfNeStrictTOS
+  Jump                 L1
+  Push                 r0
+  Push                 FP[-5]
+  Push                 r1
+  PopLocal             r2
+  Push                 r2
+  PushConstant         CP#6
+  InstanceCall1        2, CP#7
+  StoreLocal           r1
+  PopLocal             r3
+  Push                 r2
+  InstanceCall1        2, CP#8
+  InstanceCall1        2, CP#9
+  StoreLocal           r0
+  Drop1
+  Jump                 L2
+L1:
+  Push                 r0
+  ReturnTOS
+  PushConstant         CP#10
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 0
+  [1] = ArgDesc num-args 1, num-type-args 0, names []
+  [2] = ICData target-name 'get:length', arg-desc CP#1
+  [3] = ArgDesc num-args 2, num-type-args 0, names []
+  [4] = ICData target-name '<', arg-desc CP#3
+  [5] = Bool true
+  [6] = Int 1
+  [7] = ICData target-name '+', arg-desc CP#3
+  [8] = ICData target-name '[]', arg-desc CP#3
+  [9] = ICData target-name '+', arg-desc CP#3
+  [10] = Null
+}
+]static method test_while(core::List<core::int> list) → core::int {
+  core::int sum = 0;
+  core::int i = 0;
+  while (i.{core::num::<}(list.{core::List::length})) {
+    sum = sum.{core::num::+}(list.{core::List::[]}(let final core::int #t1 = i in let final core::int #t2 = i = #t1.{core::num::+}(1) in #t1));
+  }
+  return sum;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                2
+  CheckStack
+  PushConstant         CP#0
+  PopLocal             r0
+  PushConstant         CP#0
+  PopLocal             r1
+L1:
+  CheckStack
+  Push                 r0
+  Push                 FP[-5]
+  Push                 r1
+  InstanceCall1        2, CP#2
+  InstanceCall1        2, CP#3
+  StoreLocal           r0
+  Drop1
+  Push                 r1
+  PushConstant         CP#4
+  InstanceCall1        2, CP#5
+  StoreLocal           r1
+  Drop1
+  Push                 r1
+  Push                 FP[-5]
+  InstanceCall1        1, CP#7
+  InstanceCall1        2, CP#8
+  PushConstant         CP#9
+  IfEqStrictTOS
+  Jump                 L1
+  Push                 r0
+  ReturnTOS
+  PushConstant         CP#10
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 0
+  [1] = ArgDesc num-args 2, num-type-args 0, names []
+  [2] = ICData target-name '[]', arg-desc CP#1
+  [3] = ICData target-name '+', arg-desc CP#1
+  [4] = Int 1
+  [5] = ICData target-name '+', arg-desc CP#1
+  [6] = ArgDesc num-args 1, num-type-args 0, names []
+  [7] = ICData target-name 'get:length', arg-desc CP#6
+  [8] = ICData target-name '<', arg-desc CP#1
+  [9] = Bool true
+  [10] = Null
+}
+]static method test_do_while(core::List<core::int> list) → core::int {
+  core::int sum = 0;
+  core::int i = 0;
+  do {
+    sum = sum.{core::num::+}(list.{core::List::[]}(i));
+    i = i.{core::num::+}(1);
+  }
+  while (i.{core::num::<}(list.{core::List::length}))
+  return sum;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                3
+  CheckStack
+  PushConstant         CP#0
+  PopLocal             r0
+  Push                 FP[-5]
+  InstanceCall1        1, CP#2
+  PopLocal             r1
+L2:
+  CheckStack
+  Push                 r1
+  InstanceCall1        1, CP#3
+  PushConstant         CP#4
+  IfNeStrictTOS
+  Jump                 L1
+  Push                 r1
+  InstanceCall1        1, CP#5
+  PopLocal             r2
+  Push                 r0
+  Push                 r2
+  InstanceCall1        2, CP#7
+  StoreLocal           r0
+  Drop1
+  Jump                 L2
+L1:
+  Push                 r0
+  ReturnTOS
+  PushConstant         CP#8
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Int 0
+  [1] = ArgDesc num-args 1, num-type-args 0, names []
+  [2] = ICData target-name 'get:iterator', arg-desc CP#1
+  [3] = ICData target-name 'moveNext', arg-desc CP#1
+  [4] = Bool true
+  [5] = ICData target-name 'current', arg-desc CP#1
+  [6] = ArgDesc num-args 2, num-type-args 0, names []
+  [7] = ICData target-name '+', arg-desc CP#6
+  [8] = Null
+}
+]static method test_for_in(core::List<core::int> list) → core::int {
+  core::int sum = 0;
+  for (core::int e in list) {
+    sum = sum.{core::num::+}(e);
+  }
+  return sum;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]static method main() → dynamic {}
diff --git a/pkg/vm/testcases/bytecode/optional_params.dart b/pkg/vm/testcases/bytecode/optional_params.dart
new file mode 100644
index 0000000..b41298a
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/optional_params.dart
@@ -0,0 +1,22 @@
+// 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.
+
+void foo1(x, [a = 'default_a', b = 'default_b']) {
+  print('x = $x');
+  print('a = $a');
+  print('b = $b');
+}
+
+void foo2(y, z, {c = 'default_c', a = 42, b = const ['default_b']}) {
+  print('y = $y');
+  print('z = $z');
+  print('a = $a');
+  print('b = $b');
+  print('c = $c');
+}
+
+main() {
+  foo1('fixed_x', 'concrete_a');
+  foo2('fixed_y', 'fixed_z', a: 'concrete_a');
+}
diff --git a/pkg/vm/testcases/bytecode/optional_params.dart.expect b/pkg/vm/testcases/bytecode/optional_params.dart.expect
new file mode 100644
index 0000000..36b3b1a
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/optional_params.dart.expect
@@ -0,0 +1,256 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+[@vm.bytecode=
+Bytecode {
+  EntryOptional        1, 2, 0
+  LoadConstant         r1, CP#0
+  LoadConstant         r2, CP#1
+  Frame                3
+  CheckStack
+  PushConstant         CP#2
+  PushConstant         CP#3
+  CreateArrayTOS
+  StoreLocal           r3
+  Push                 r3
+  PushConstant         CP#4
+  PushConstant         CP#5
+  StoreIndexedTOS
+  Push                 r3
+  PushConstant         CP#6
+  Push                 r0
+  StoreIndexedTOS
+  PushConstant         CP#8
+  IndirectStaticCall   1, CP#7
+  PushConstant         CP#9
+  IndirectStaticCall   1, CP#7
+  Drop1
+  PushConstant         CP#2
+  PushConstant         CP#3
+  CreateArrayTOS
+  StoreLocal           r4
+  Push                 r4
+  PushConstant         CP#4
+  PushConstant         CP#10
+  StoreIndexedTOS
+  Push                 r4
+  PushConstant         CP#6
+  Push                 r1
+  StoreIndexedTOS
+  PushConstant         CP#11
+  IndirectStaticCall   1, CP#7
+  PushConstant         CP#12
+  IndirectStaticCall   1, CP#7
+  Drop1
+  PushConstant         CP#2
+  PushConstant         CP#3
+  CreateArrayTOS
+  StoreLocal           r5
+  Push                 r5
+  PushConstant         CP#4
+  PushConstant         CP#13
+  StoreIndexedTOS
+  Push                 r5
+  PushConstant         CP#6
+  Push                 r2
+  StoreIndexedTOS
+  PushConstant         CP#14
+  IndirectStaticCall   1, CP#7
+  PushConstant         CP#15
+  IndirectStaticCall   1, CP#7
+  Drop1
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = String 'default_a'
+  [1] = String 'default_b'
+  [2] = Null
+  [3] = Int 2
+  [4] = Int 0
+  [5] = String 'x = '
+  [6] = Int 1
+  [7] = ArgDesc num-args 1, num-type-args 0, names []
+  [8] = StaticICData target 'dart.core::_StringBase::_interpolate', arg-desc CP#7
+  [9] = StaticICData target 'dart.core::print', arg-desc CP#7
+  [10] = String 'a = '
+  [11] = StaticICData target 'dart.core::_StringBase::_interpolate', arg-desc CP#7
+  [12] = StaticICData target 'dart.core::print', arg-desc CP#7
+  [13] = String 'b = '
+  [14] = StaticICData target 'dart.core::_StringBase::_interpolate', arg-desc CP#7
+  [15] = StaticICData target 'dart.core::print', arg-desc CP#7
+}
+]static method foo1(dynamic x, [dynamic a = "default_a", dynamic b = "default_b"]) → void {
+  core::print("x = ${x}");
+  core::print("a = ${a}");
+  core::print("b = ${b}");
+}
+[@vm.bytecode=
+Bytecode {
+  EntryOptional        2, 0, 3
+  LoadConstant         r2, CP#0
+  LoadConstant         r2, CP#1
+  LoadConstant         r3, CP#2
+  LoadConstant         r3, CP#4
+  LoadConstant         r4, CP#5
+  LoadConstant         r4, CP#6
+  Frame                5
+  CheckStack
+  PushConstant         CP#7
+  PushConstant         CP#8
+  CreateArrayTOS
+  StoreLocal           r5
+  Push                 r5
+  PushConstant         CP#9
+  PushConstant         CP#10
+  StoreIndexedTOS
+  Push                 r5
+  PushConstant         CP#11
+  Push                 r0
+  StoreIndexedTOS
+  PushConstant         CP#13
+  IndirectStaticCall   1, CP#12
+  PushConstant         CP#14
+  IndirectStaticCall   1, CP#12
+  Drop1
+  PushConstant         CP#7
+  PushConstant         CP#8
+  CreateArrayTOS
+  StoreLocal           r6
+  Push                 r6
+  PushConstant         CP#9
+  PushConstant         CP#15
+  StoreIndexedTOS
+  Push                 r6
+  PushConstant         CP#11
+  Push                 r1
+  StoreIndexedTOS
+  PushConstant         CP#16
+  IndirectStaticCall   1, CP#12
+  PushConstant         CP#17
+  IndirectStaticCall   1, CP#12
+  Drop1
+  PushConstant         CP#7
+  PushConstant         CP#8
+  CreateArrayTOS
+  StoreLocal           r7
+  Push                 r7
+  PushConstant         CP#9
+  PushConstant         CP#18
+  StoreIndexedTOS
+  Push                 r7
+  PushConstant         CP#11
+  Push                 r2
+  StoreIndexedTOS
+  PushConstant         CP#19
+  IndirectStaticCall   1, CP#12
+  PushConstant         CP#20
+  IndirectStaticCall   1, CP#12
+  Drop1
+  PushConstant         CP#7
+  PushConstant         CP#8
+  CreateArrayTOS
+  StoreLocal           r8
+  Push                 r8
+  PushConstant         CP#9
+  PushConstant         CP#21
+  StoreIndexedTOS
+  Push                 r8
+  PushConstant         CP#11
+  Push                 r3
+  StoreIndexedTOS
+  PushConstant         CP#22
+  IndirectStaticCall   1, CP#12
+  PushConstant         CP#23
+  IndirectStaticCall   1, CP#12
+  Drop1
+  PushConstant         CP#7
+  PushConstant         CP#8
+  CreateArrayTOS
+  StoreLocal           r9
+  Push                 r9
+  PushConstant         CP#9
+  PushConstant         CP#24
+  StoreIndexedTOS
+  Push                 r9
+  PushConstant         CP#11
+  Push                 r4
+  StoreIndexedTOS
+  PushConstant         CP#25
+  IndirectStaticCall   1, CP#12
+  PushConstant         CP#26
+  IndirectStaticCall   1, CP#12
+  Drop1
+  PushConstant         CP#7
+  ReturnTOS
+}
+ConstantPool {
+  [0] = String 'a'
+  [1] = Int 42
+  [2] = String 'b'
+  [3] = String 'default_b'
+  [4] = List type-arg dart.core::String, entries CP# [3]
+  [5] = String 'c'
+  [6] = String 'default_c'
+  [7] = Null
+  [8] = Int 2
+  [9] = Int 0
+  [10] = String 'y = '
+  [11] = Int 1
+  [12] = ArgDesc num-args 1, num-type-args 0, names []
+  [13] = StaticICData target 'dart.core::_StringBase::_interpolate', arg-desc CP#12
+  [14] = StaticICData target 'dart.core::print', arg-desc CP#12
+  [15] = String 'z = '
+  [16] = StaticICData target 'dart.core::_StringBase::_interpolate', arg-desc CP#12
+  [17] = StaticICData target 'dart.core::print', arg-desc CP#12
+  [18] = String 'a = '
+  [19] = StaticICData target 'dart.core::_StringBase::_interpolate', arg-desc CP#12
+  [20] = StaticICData target 'dart.core::print', arg-desc CP#12
+  [21] = String 'b = '
+  [22] = StaticICData target 'dart.core::_StringBase::_interpolate', arg-desc CP#12
+  [23] = StaticICData target 'dart.core::print', arg-desc CP#12
+  [24] = String 'c = '
+  [25] = StaticICData target 'dart.core::_StringBase::_interpolate', arg-desc CP#12
+  [26] = StaticICData target 'dart.core::print', arg-desc CP#12
+}
+]static method foo2(dynamic y, dynamic z, {dynamic a = 42, dynamic b = const <core::String>["default_b"], dynamic c = "default_c"}) → void {
+  core::print("y = ${y}");
+  core::print("z = ${z}");
+  core::print("a = ${a}");
+  core::print("b = ${b}");
+  core::print("c = ${c}");
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  PushConstant         CP#1
+  PushConstant         CP#3
+  IndirectStaticCall   2, CP#2
+  Drop1
+  PushConstant         CP#4
+  PushConstant         CP#5
+  PushConstant         CP#1
+  PushConstant         CP#7
+  IndirectStaticCall   3, CP#6
+  Drop1
+  PushConstant         CP#8
+  ReturnTOS
+}
+ConstantPool {
+  [0] = String 'fixed_x'
+  [1] = String 'concrete_a'
+  [2] = ArgDesc num-args 2, num-type-args 0, names []
+  [3] = StaticICData target '#lib::foo1', arg-desc CP#2
+  [4] = String 'fixed_y'
+  [5] = String 'fixed_z'
+  [6] = ArgDesc num-args 3, num-type-args 0, names [a]
+  [7] = StaticICData target '#lib::foo2', arg-desc CP#6
+  [8] = Null
+}
+]static method main() → dynamic {
+  self::foo1("fixed_x", "concrete_a");
+  self::foo2("fixed_y", "fixed_z", a: "concrete_a");
+}
diff --git a/pkg/vm/testcases/bytecode/switch.dart b/pkg/vm/testcases/bytecode/switch.dart
new file mode 100644
index 0000000..da20adb
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/switch.dart
@@ -0,0 +1,60 @@
+// 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.
+
+int foo1(int x) {
+  int y;
+  switch (x) {
+    case 1:
+      y = 11;
+      break;
+    case 2:
+      y = 22;
+      break;
+    case 3:
+      y = 33;
+      break;
+  }
+  return y;
+}
+
+int foo2(int x) {
+  int y;
+  switch (x) {
+    case 1:
+    case 2:
+    case 3:
+      y = 11;
+      break;
+    case 4:
+    case 5:
+    case 6:
+      y = 22;
+      break;
+    default:
+      y = 33;
+  }
+  return y;
+}
+
+int foo3(int x) {
+  int y;
+  switch (x) {
+    case 1:
+    case 2:
+    case 3:
+      y = 11;
+      continue L5;
+    case 4:
+    L5:
+    case 5:
+    case 6:
+      y = 22;
+      return 42;
+    default:
+      y = 33;
+  }
+  return y;
+}
+
+main() {}
diff --git a/pkg/vm/testcases/bytecode/switch.dart.expect b/pkg/vm/testcases/bytecode/switch.dart.expect
new file mode 100644
index 0000000..cf87dfd
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/switch.dart.expect
@@ -0,0 +1,328 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+[@vm.bytecode=
+Bytecode {
+  Entry                2
+  CheckStack
+  PushConstant         CP#0
+  PopLocal             r0
+  Push                 FP[-5]
+  PopLocal             r1
+  Push                 r1
+  PushConstant         CP#2
+  InstanceCall2        2, CP#3
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L1
+  Push                 r1
+  PushConstant         CP#5
+  InstanceCall2        2, CP#6
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L2
+  Push                 r1
+  PushConstant         CP#7
+  InstanceCall2        2, CP#8
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L3
+  Jump                 L4
+L1:
+  PushConstant         CP#9
+  StoreLocal           r0
+  Drop1
+  Jump                 L4
+L2:
+  PushConstant         CP#10
+  StoreLocal           r0
+  Drop1
+  Jump                 L4
+L3:
+  PushConstant         CP#11
+  StoreLocal           r0
+  Drop1
+  Jump                 L4
+L4:
+  Push                 r0
+  ReturnTOS
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+  [1] = ArgDesc num-args 2, num-type-args 0, names []
+  [2] = Int 1
+  [3] = ICData target-name '==', arg-desc CP#1
+  [4] = Bool true
+  [5] = Int 2
+  [6] = ICData target-name '==', arg-desc CP#1
+  [7] = Int 3
+  [8] = ICData target-name '==', arg-desc CP#1
+  [9] = Int 11
+  [10] = Int 22
+  [11] = Int 33
+}
+]static method foo1(core::int x) → core::int {
+  core::int y;
+  #L1:
+  switch(x) {
+    #L2:
+    case 1:
+      {
+        y = 11;
+        break #L1;
+      }
+    #L3:
+    case 2:
+      {
+        y = 22;
+        break #L1;
+      }
+    #L4:
+    case 3:
+      {
+        y = 33;
+        break #L1;
+      }
+  }
+  return y;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                2
+  CheckStack
+  PushConstant         CP#0
+  PopLocal             r0
+  Push                 FP[-5]
+  PopLocal             r1
+  Push                 r1
+  PushConstant         CP#2
+  InstanceCall2        2, CP#3
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L1
+  Push                 r1
+  PushConstant         CP#5
+  InstanceCall2        2, CP#6
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L1
+  Push                 r1
+  PushConstant         CP#7
+  InstanceCall2        2, CP#8
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L1
+  Push                 r1
+  PushConstant         CP#9
+  InstanceCall2        2, CP#10
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L2
+  Push                 r1
+  PushConstant         CP#11
+  InstanceCall2        2, CP#12
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L2
+  Push                 r1
+  PushConstant         CP#13
+  InstanceCall2        2, CP#14
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L2
+  Jump                 L3
+L1:
+  PushConstant         CP#15
+  StoreLocal           r0
+  Drop1
+  Jump                 L4
+L2:
+  PushConstant         CP#16
+  StoreLocal           r0
+  Drop1
+  Jump                 L4
+L3:
+  PushConstant         CP#17
+  StoreLocal           r0
+  Drop1
+L4:
+  Push                 r0
+  ReturnTOS
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+  [1] = ArgDesc num-args 2, num-type-args 0, names []
+  [2] = Int 1
+  [3] = ICData target-name '==', arg-desc CP#1
+  [4] = Bool true
+  [5] = Int 2
+  [6] = ICData target-name '==', arg-desc CP#1
+  [7] = Int 3
+  [8] = ICData target-name '==', arg-desc CP#1
+  [9] = Int 4
+  [10] = ICData target-name '==', arg-desc CP#1
+  [11] = Int 5
+  [12] = ICData target-name '==', arg-desc CP#1
+  [13] = Int 6
+  [14] = ICData target-name '==', arg-desc CP#1
+  [15] = Int 11
+  [16] = Int 22
+  [17] = Int 33
+}
+]static method foo2(core::int x) → core::int {
+  core::int y;
+  #L5:
+  switch(x) {
+    #L6:
+    case 1:
+    case 2:
+    case 3:
+      {
+        y = 11;
+        break #L5;
+      }
+    #L7:
+    case 4:
+    case 5:
+    case 6:
+      {
+        y = 22;
+        break #L5;
+      }
+    #L8:
+    default:
+      {
+        y = 33;
+      }
+  }
+  return y;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                2
+  CheckStack
+  PushConstant         CP#0
+  PopLocal             r0
+  Push                 FP[-5]
+  PopLocal             r1
+  Push                 r1
+  PushConstant         CP#2
+  InstanceCall2        2, CP#3
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L1
+  Push                 r1
+  PushConstant         CP#5
+  InstanceCall2        2, CP#6
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L1
+  Push                 r1
+  PushConstant         CP#7
+  InstanceCall2        2, CP#8
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L1
+  Push                 r1
+  PushConstant         CP#9
+  InstanceCall2        2, CP#10
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L2
+  Push                 r1
+  PushConstant         CP#11
+  InstanceCall2        2, CP#12
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L2
+  Push                 r1
+  PushConstant         CP#13
+  InstanceCall2        2, CP#14
+  PushConstant         CP#4
+  IfEqStrictTOS
+  Jump                 L2
+  Jump                 L3
+L1:
+  PushConstant         CP#15
+  StoreLocal           r0
+  Drop1
+  Jump                 L2
+L2:
+  PushConstant         CP#16
+  StoreLocal           r0
+  Drop1
+  PushConstant         CP#17
+  ReturnTOS
+L3:
+  PushConstant         CP#18
+  StoreLocal           r0
+  Drop1
+  Push                 r0
+  ReturnTOS
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+  [1] = ArgDesc num-args 2, num-type-args 0, names []
+  [2] = Int 1
+  [3] = ICData target-name '==', arg-desc CP#1
+  [4] = Bool true
+  [5] = Int 2
+  [6] = ICData target-name '==', arg-desc CP#1
+  [7] = Int 3
+  [8] = ICData target-name '==', arg-desc CP#1
+  [9] = Int 4
+  [10] = ICData target-name '==', arg-desc CP#1
+  [11] = Int 5
+  [12] = ICData target-name '==', arg-desc CP#1
+  [13] = Int 6
+  [14] = ICData target-name '==', arg-desc CP#1
+  [15] = Int 11
+  [16] = Int 22
+  [17] = Int 42
+  [18] = Int 33
+}
+]static method foo3(core::int x) → core::int {
+  core::int y;
+  switch(x) {
+    #L9:
+    case 1:
+    case 2:
+    case 3:
+      {
+        y = 11;
+        continue #L10;
+      }
+    #L10:
+    case 4:
+    case 5:
+    case 6:
+      {
+        y = 22;
+        return 42;
+      }
+    #L11:
+    default:
+      {
+        y = 33;
+      }
+  }
+  return y;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]static method main() → dynamic {}
diff --git a/pkg/vm/testcases/bytecode/type_ops.dart b/pkg/vm/testcases/bytecode/type_ops.dart
new file mode 100644
index 0000000..664dc6e
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/type_ops.dart
@@ -0,0 +1,45 @@
+// 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.
+
+class A<T> {}
+
+class B extends A<String> {}
+
+class C<T1, T2, T3> extends B {}
+
+foo1(x) {
+  if (x is B) {
+    print('11');
+  }
+  if (x is C<int, Object, dynamic>) {
+    print('12');
+  }
+  return x as A<int>;
+}
+
+class D<P, Q> extends C<int, Q, P> {
+  Map<P, Q> foo;
+
+  foo2(y) {
+    if (y is A<P>) {
+      print('21');
+    }
+    if (y is C<dynamic, Q, List<P>>) {
+      print('22');
+    }
+    foo = y;
+  }
+
+  foo3<T1, T2>(z) {
+    if (z is A<T1>) {
+      print('31');
+    }
+    if (z is C<Map<T1, P>, List<T2>, Q>) {
+      print('32');
+    }
+    return (z as Map<T2, Q>).values;
+  }
+}
+
+main() {}
diff --git a/pkg/vm/testcases/bytecode/type_ops.dart.expect b/pkg/vm/testcases/bytecode/type_ops.dart.expect
new file mode 100644
index 0000000..f53ec42
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/type_ops.dart.expect
@@ -0,0 +1,302 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object> extends core::Object {
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  PushConstant         CP#1
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = StaticICData target 'dart.core::Object::', arg-desc CP#0
+  [2] = Null
+}
+]  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class B extends self::A<core::String> {
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  PushConstant         CP#1
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = StaticICData target '#lib::A::', arg-desc CP#0
+  [2] = Null
+}
+]  synthetic constructor •() → void
+    : super self::A::•()
+    ;
+}
+class C<T1 extends core::Object, T2 extends core::Object, T3 extends core::Object> extends self::B {
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  PushConstant         CP#1
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = StaticICData target '#lib::B::', arg-desc CP#0
+  [2] = Null
+}
+]  synthetic constructor •() → void
+    : super self::B::•()
+    ;
+}
+class D<P extends core::Object, Q extends core::Object> extends self::C<core::int, self::D::Q, self::D::P> {
+  generic-covariant-impl generic-covariant-interface field core::Map<self::D::P, self::D::Q> foo = null;
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  PushConstant         CP#1
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushConstant         CP#2
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = StaticICData target '#lib::C::', arg-desc CP#0
+  [2] = Null
+}
+]  synthetic constructor •() → void
+    : super self::C::•()
+    ;
+[@vm.bytecode=
+Bytecode {
+  Entry                1
+  CheckStack
+  Push                 FP[-5]
+  Push                 FP[-6]
+  LoadFieldTOS         CP#0
+  PushConstant         CP#1
+  PushConstant         CP#2
+  InstanceCall1        4, CP#4
+  PushConstant         CP#5
+  IfNeStrictTOS
+  Jump                 L1
+  PushConstant         CP#6
+  PushConstant         CP#8
+  IndirectStaticCall   1, CP#7
+  Drop1
+L1:
+  Push                 FP[-5]
+  Push                 FP[-6]
+  LoadFieldTOS         CP#0
+  PushConstant         CP#1
+  PushConstant         CP#9
+  InstanceCall1        4, CP#10
+  PushConstant         CP#5
+  IfNeStrictTOS
+  Jump                 L2
+  PushConstant         CP#11
+  PushConstant         CP#12
+  IndirectStaticCall   1, CP#7
+  Drop1
+L2:
+  Push                 FP[-6]
+  Push                 FP[-5]
+  StoreLocal           r0
+  InstanceCall1        2, CP#14
+  Drop1
+  Push                 r0
+  Drop1
+  PushConstant         CP#1
+  ReturnTOS
+}
+ConstantPool {
+  [0] = TypeArgumentsFieldOffset #lib::D
+  [1] = Null
+  [2] = Type #lib::A<#lib::D::P>
+  [3] = ArgDesc num-args 4, num-type-args 0, names []
+  [4] = ICData target-name '_instanceOf', arg-desc CP#3
+  [5] = Bool true
+  [6] = String '21'
+  [7] = ArgDesc num-args 1, num-type-args 0, names []
+  [8] = StaticICData target 'dart.core::print', arg-desc CP#7
+  [9] = Type #lib::C<dynamic, #lib::D::Q, dart.core::List<#lib::D::P>>
+  [10] = ICData target-name '_instanceOf', arg-desc CP#3
+  [11] = String '22'
+  [12] = StaticICData target 'dart.core::print', arg-desc CP#7
+  [13] = ArgDesc num-args 2, num-type-args 0, names []
+  [14] = ICData target-name 'set:foo', arg-desc CP#13
+}
+]  method foo2(dynamic y) → dynamic {
+    if(y is self::A<self::D::P>) {
+      core::print("21");
+    }
+    if(y is self::C<dynamic, self::D::Q, core::List<self::D::P>>) {
+      core::print("22");
+    }
+    this.{self::D::foo} = y as{TypeError} core::Map<self::D::P, self::D::Q>;
+  }
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  Push                 FP[-6]
+  LoadFieldTOS         CP#0
+  Push                 FP[-7]
+  PushConstant         CP#1
+  InstanceCall1        4, CP#3
+  PushConstant         CP#4
+  IfNeStrictTOS
+  Jump                 L1
+  PushConstant         CP#5
+  PushConstant         CP#7
+  IndirectStaticCall   1, CP#6
+  Drop1
+L1:
+  Push                 FP[-5]
+  Push                 FP[-6]
+  LoadFieldTOS         CP#0
+  Push                 FP[-7]
+  PushConstant         CP#8
+  InstanceCall1        4, CP#9
+  PushConstant         CP#4
+  IfNeStrictTOS
+  Jump                 L2
+  PushConstant         CP#10
+  PushConstant         CP#11
+  IndirectStaticCall   1, CP#6
+  Drop1
+L2:
+  Push                 FP[-5]
+  Push                 FP[-6]
+  LoadFieldTOS         CP#0
+  Push                 FP[-7]
+  PushConstant         CP#12
+  InstanceCall1        4, CP#13
+  InstanceCall1        1, CP#14
+  ReturnTOS
+  PushConstant         CP#15
+  ReturnTOS
+}
+ConstantPool {
+  [0] = TypeArgumentsFieldOffset #lib::D
+  [1] = Type #lib::A<#lib::D::foo3::T1>
+  [2] = ArgDesc num-args 4, num-type-args 0, names []
+  [3] = ICData target-name '_instanceOf', arg-desc CP#2
+  [4] = Bool true
+  [5] = String '31'
+  [6] = ArgDesc num-args 1, num-type-args 0, names []
+  [7] = StaticICData target 'dart.core::print', arg-desc CP#6
+  [8] = Type #lib::C<dart.core::Map<#lib::D::foo3::T1, #lib::D::P>, dart.core::List<#lib::D::foo3::T2>, #lib::D::Q>
+  [9] = ICData target-name '_instanceOf', arg-desc CP#2
+  [10] = String '32'
+  [11] = StaticICData target 'dart.core::print', arg-desc CP#6
+  [12] = Type dart.core::Map<#lib::D::foo3::T2, #lib::D::Q>
+  [13] = ICData target-name '_as', arg-desc CP#2
+  [14] = ICData target-name 'get:values', arg-desc CP#6
+  [15] = Null
+}
+]  method foo3<T1 extends core::Object, T2 extends core::Object>(dynamic z) → dynamic {
+    if(z is self::A<self::D::foo3::T1>) {
+      core::print("31");
+    }
+    if(z is self::C<core::Map<self::D::foo3::T1, self::D::P>, core::List<self::D::foo3::T2>, self::D::Q>) {
+      core::print("32");
+    }
+    return (z as core::Map<self::D::foo3::T2, self::D::Q>).{core::Map::values};
+  }
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  Push                 FP[-5]
+  PushConstant         CP#0
+  PushConstant         CP#0
+  PushConstant         CP#1
+  InstanceCall1        4, CP#3
+  PushConstant         CP#4
+  IfNeStrictTOS
+  Jump                 L1
+  PushConstant         CP#5
+  PushConstant         CP#7
+  IndirectStaticCall   1, CP#6
+  Drop1
+L1:
+  Push                 FP[-5]
+  PushConstant         CP#0
+  PushConstant         CP#0
+  PushConstant         CP#8
+  InstanceCall1        4, CP#9
+  PushConstant         CP#4
+  IfNeStrictTOS
+  Jump                 L2
+  PushConstant         CP#10
+  PushConstant         CP#11
+  IndirectStaticCall   1, CP#6
+  Drop1
+L2:
+  Push                 FP[-5]
+  PushConstant         CP#0
+  PushConstant         CP#0
+  PushConstant         CP#12
+  InstanceCall1        4, CP#13
+  ReturnTOS
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+  [1] = Type #lib::B
+  [2] = ArgDesc num-args 4, num-type-args 0, names []
+  [3] = ICData target-name '_instanceOf', arg-desc CP#2
+  [4] = Bool true
+  [5] = String '11'
+  [6] = ArgDesc num-args 1, num-type-args 0, names []
+  [7] = StaticICData target 'dart.core::print', arg-desc CP#6
+  [8] = Type #lib::C<dart.core::int, dart.core::Object, dynamic>
+  [9] = ICData target-name '_instanceOf', arg-desc CP#2
+  [10] = String '12'
+  [11] = StaticICData target 'dart.core::print', arg-desc CP#6
+  [12] = Type #lib::A<dart.core::int>
+  [13] = ICData target-name '_as', arg-desc CP#2
+}
+]static method foo1(dynamic x) → dynamic {
+  if(x is self::B) {
+    core::print("11");
+  }
+  if(x is self::C<core::int, core::Object, dynamic>) {
+    core::print("12");
+  }
+  return x as self::A<core::int>;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]static method main() → dynamic {}
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index a735862..db2fa71 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -1132,7 +1132,7 @@
   import("//build/package.gni")
 
   package("package") {
-    system_image = true
+    deprecated_system_image = true
 
     package_name = "dart"
 
@@ -1152,7 +1152,7 @@
   }
 
   package("dart_tests") {
-    system_image = true
+    deprecated_system_image = true
 
     deps = [
       ":hello_fuchsia",
diff --git a/runtime/bin/namespace_fuchsia.cc b/runtime/bin/namespace_fuchsia.cc
index b8bb20a..384aa9d 100644
--- a/runtime/bin/namespace_fuchsia.cc
+++ b/runtime/bin/namespace_fuchsia.cc
@@ -11,6 +11,7 @@
 #include <fcntl.h>
 #include <fdio/namespace.h>
 #include <fdio/private.h>
+#include <zircon/status.h>
 
 #include "bin/file.h"
 #include "platform/signal_blocker.h"
@@ -42,7 +43,9 @@
   ~NamespaceImpl() {
     if (fdio_ns_ != NULL) {
       zx_status_t status = fdio_ns_destroy(fdio_ns_);
-      ASSERT(status == ZX_OK);
+      if (status != ZX_OK) {
+        Log::PrintErr("fdio_ns_destroy: %s\n", zx_status_get_string(status));
+      }
     }
     NO_RETRY_EXPECTED(close(rootfd_));
     free(cwd_);
diff --git a/runtime/bin/platform_android.cc b/runtime/bin/platform_android.cc
index b14fb90..a7afafe 100644
--- a/runtime/bin/platform_android.cc
+++ b/runtime/bin/platform_android.cc
@@ -26,7 +26,7 @@
 
 static void segv_handler(int signal, siginfo_t* siginfo, void* context) {
   Log::PrintErr(
-      "\n===== DART STANDALONE VM CRASH =====\n"
+      "\n===== CRASH =====\n"
       "version=%s\n"
       "si_signo=%s(%d), si_code=%d, si_addr=%p\n",
       Dart_VersionString(), strsignal(siginfo->si_signo), siginfo->si_signo,
diff --git a/runtime/bin/platform_linux.cc b/runtime/bin/platform_linux.cc
index 9cd4f71..a8dccc5 100644
--- a/runtime/bin/platform_linux.cc
+++ b/runtime/bin/platform_linux.cc
@@ -26,7 +26,7 @@
 
 static void segv_handler(int signal, siginfo_t* siginfo, void* context) {
   Log::PrintErr(
-      "\n===== DART STANDALONE VM CRASH =====\n"
+      "\n===== CRASH =====\n"
       "version=%s\n"
       "si_signo=%s(%d), si_code=%d, si_addr=%p\n",
       Dart_VersionString(), strsignal(siginfo->si_signo), siginfo->si_signo,
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc
index 3dfe9e5..1cf7f46 100644
--- a/runtime/bin/platform_macos.cc
+++ b/runtime/bin/platform_macos.cc
@@ -34,7 +34,7 @@
 
 static void segv_handler(int signal, siginfo_t* siginfo, void* context) {
   Log::PrintErr(
-      "\n===== DART STANDALONE VM CRASH =====\n"
+      "\n===== CRASH =====\n"
       "version=%s\n"
       "si_signo=%s(%d), si_code=%d, si_addr=%p\n",
       Dart_VersionString(), strsignal(siginfo->si_signo), siginfo->si_signo,
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index 796f250..069b9e5 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -64,7 +64,7 @@
         (ExceptionInfo->ExceptionRecord->ExceptionCode ==
          EXCEPTION_ILLEGAL_INSTRUCTION)) {
       Log::PrintErr(
-          "\n===== DART STANDALONE VM CRASH =====\n"
+          "\n===== CRASH =====\n"
           "version=%s\n"
           "ExceptionCode=%d, ExceptionFlags=%d, ExceptionAddress=%p\n",
           Dart_VersionString(), ExceptionInfo->ExceptionRecord->ExceptionCode,
diff --git a/runtime/bin/secure_socket_filter.h b/runtime/bin/secure_socket_filter.h
index dda69eb..e09f0e6 100644
--- a/runtime/bin/secure_socket_filter.h
+++ b/runtime/bin/secure_socket_filter.h
@@ -49,6 +49,10 @@
 
   ~SSLFilter();
 
+  char* hostname() const { return hostname_; }
+  bool is_server() const { return is_server_; }
+  bool is_client() const { return !is_server_; }
+
   Dart_Handle Init(Dart_Handle dart_this);
   void Connect(const char* hostname,
                SSLCertContext* context,
diff --git a/runtime/bin/security_context.cc b/runtime/bin/security_context.cc
index 397ed30..56d99e4 100644
--- a/runtime/bin/security_context.cc
+++ b/runtime/bin/security_context.cc
@@ -661,7 +661,6 @@
 }
 
 Dart_Handle X509Helper::GetIssuer(Dart_NativeArguments args) {
-  fprintf(stdout, "Getting issuer!\n");
   X509* certificate = GetX509Certificate(args);
   X509_NAME* issuer = X509_get_issuer_name(certificate);
   char* issuer_string = X509_NAME_oneline(issuer, NULL, 0);
diff --git a/runtime/bin/security_context_macos.cc b/runtime/bin/security_context_macos.cc
index 1f7a3bb..8dbb43e 100644
--- a/runtime/bin/security_context_macos.cc
+++ b/runtime/bin/security_context_macos.cc
@@ -28,7 +28,11 @@
  public:
   explicit ScopedCFType(T obj) : obj_(obj) {}
 
-  ~ScopedCFType() { CFRelease(obj_); }
+  ~ScopedCFType() {
+    if (obj_ != NULL) {
+      CFRelease(obj_);
+    }
+  }
 
   T get() { return obj_; }
   T* ptr() { return &obj_; }
@@ -45,6 +49,7 @@
 
 typedef ScopedCFType<CFMutableArrayRef> ScopedCFMutableArrayRef;
 typedef ScopedCFType<CFDataRef> ScopedCFDataRef;
+typedef ScopedCFType<CFStringRef> ScopedCFStringRef;
 typedef ScopedCFType<SecPolicyRef> ScopedSecPolicyRef;
 typedef ScopedCFType<SecCertificateRef> ScopedSecCertificateRef;
 typedef ScopedCFType<SecTrustRef> ScopedSecTrustRef;
@@ -112,8 +117,19 @@
     }
   }
 
-  // Generate a generic X509 verification policy.
-  ScopedSecPolicyRef policy(SecPolicyCreateBasicX509());
+  // Generate a policy for validating chains for SSL.
+  const int ssl_index = SSL_get_ex_data_X509_STORE_CTX_idx();
+  SSL* ssl = static_cast<SSL*>(X509_STORE_CTX_get_ex_data(ctx, ssl_index));
+  SSLFilter* filter = static_cast<SSLFilter*>(
+      SSL_get_ex_data(ssl, SSLFilter::filter_ssl_index));
+  CFStringRef cfhostname = NULL;
+  if (filter->hostname() != NULL) {
+    cfhostname = CFStringCreateWithCString(NULL, filter->hostname(),
+                                           kCFStringEncodingUTF8);
+  }
+  ScopedCFStringRef hostname(cfhostname);
+  ScopedSecPolicyRef policy(
+      SecPolicyCreateSSL(filter->is_client(), hostname.get()));
 
   // Create the trust object with the certificates provided by the user.
   ScopedSecTrustRef trust(NULL);
diff --git a/runtime/lib/function.dart b/runtime/lib/function.dart
index ebaa3ec..341758e 100644
--- a/runtime/lib/function.dart
+++ b/runtime/lib/function.dart
@@ -20,7 +20,7 @@
 
   int _computeHash() native "Closure_computeHash";
 
-  // No instance fields should be declared before the following 4 fields whose
+  // No instance fields should be declared before the following fields whose
   // offsets must be identical in Dart and C++.
 
   // The following fields are declared both in raw_object.h (for direct access
@@ -30,6 +30,7 @@
   // names do not need to match the C++ names, but they must be private.
   var _instantiator_type_arguments;
   var _function_type_arguments;
+  var _delayed_type_arguments;
   var _function;
   var _context;
 
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 43ff9094..5e29999 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -199,7 +199,7 @@
 #if defined(DEBUG)
       Context& ctx = Context::Handle();
       ctx = Closure::Cast(closure).context();
-      ASSERT(ctx.num_variables() == 0);
+      ASSERT(ctx.IsNull());
 #endif
       // Get the parent function so that we get the right function name.
       func = func.parent_function();
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index d586dc0..fe0711f 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -462,29 +462,9 @@
       TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0));
   const TypeArguments& parent_type_arguments =
       TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(1));
-  if (function_type_arguments.IsNull() && parent_type_arguments.IsNull()) {
-    return TypeArguments::null();
-  }
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_len, arguments->NativeArgAt(2));
   const intptr_t len = smi_len.Value();
-  const TypeArguments& result =
-      TypeArguments::Handle(zone, TypeArguments::New(len, Heap::kNew));
-  AbstractType& type = AbstractType::Handle(zone);
-  const intptr_t split = parent_type_arguments.IsNull()
-                             ? len - function_type_arguments.Length()
-                             : parent_type_arguments.Length();
-  for (intptr_t i = 0; i < split; i++) {
-    type = parent_type_arguments.IsNull() ? Type::DynamicType()
-                                          : parent_type_arguments.TypeAt(i);
-    result.SetTypeAt(i, type);
-  }
-  for (intptr_t i = split; i < len; i++) {
-    type = function_type_arguments.IsNull()
-               ? Type::DynamicType()
-               : function_type_arguments.TypeAt(i - split);
-    result.SetTypeAt(i, type);
-  }
-  return result.Canonicalize();
+  return function_type_arguments.Prepend(zone, parent_type_arguments, len);
 }
 
 DEFINE_NATIVE_ENTRY(InvocationMirror_unpackTypeArguments, 1) {
diff --git a/runtime/lib/typed_data_patch.dart b/runtime/lib/typed_data_patch.dart
index 83a4f54..383bfcd 100644
--- a/runtime/lib/typed_data_patch.dart
+++ b/runtime/lib/typed_data_patch.dart
@@ -3487,7 +3487,7 @@
   E get current => _current;
 }
 
-class _TypedListView extends _TypedListBase implements TypedData {
+abstract class _TypedListView extends _TypedListBase implements TypedData {
   _TypedListView(_ByteBuffer _buffer, int _offset, int _length)
       : _typedData = _buffer._data,
         offsetInBytes = _offset,
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index a10cfaa..29800f7 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -2073,6 +2073,9 @@
   Iterable get values => _map.values;
   int get length => _map.length;
 
+  // Suppress compile-time error about missing Map methods.
+  noSuchMethod(_) => throw "Unimplemented ServiceMap method";
+
   String toString() => "ServiceMap($_map)";
 }
 
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 35c3305..07ba355 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -155,7 +155,6 @@
 cc/Debugger_PrintBreakpointsToJSONArray: Fail
 cc/Debugger_Rewind_Optimized: SkipSlow
 cc/Debugger_SetBreakpointInPartOfLibrary: Crash
-cc/FunctionSourceFingerprint: Fail # Issue 30756
 cc/IsolateReload_NotTypedefToTypedef: Fail
 cc/IsolateReload_TypedefToNotTypedef: Fail
 cc/Profiler_BasicSourcePositionOptimized: Skip
@@ -208,6 +207,9 @@
 cc/IsolateReload_LibraryImportAdded: Crash # Issue 32190
 cc/IsolateReload_LibraryImportRemoved: Fail # Issue 32190
 cc/IsolateReload_LibraryLookup: Fail, Crash # Issue 32190
+cc/MismatchedSnapshotKinds: Fail, Crash, OK # Script snapshots not supported in Dart 2
+cc/ScriptSnapshot1: Fail, Crash, OK # Script snapshots not supported in Dart 2
+cc/ScriptSnapshotsUpdateSubclasses: Fail, Crash, OK # Script snapshots not supported in Dart 2
 
 # Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
 # are to be triaged.  Isolate tests are skipped on purpose due to the usage of
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index 52b7a3b..2bd04fa 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -239,17 +239,19 @@
 #if defined(DEBUG)
   // Verify that closure field offsets are identical in Dart and C++.
   const Array& fields = Array::Handle(zone, cls.fields());
-  ASSERT(fields.Length() == 5);
+  ASSERT(fields.Length() == 6);
   Field& field = Field::Handle(zone);
   field ^= fields.At(0);
   ASSERT(field.Offset() == Closure::instantiator_type_arguments_offset());
   field ^= fields.At(1);
   ASSERT(field.Offset() == Closure::function_type_arguments_offset());
   field ^= fields.At(2);
-  ASSERT(field.Offset() == Closure::function_offset());
+  ASSERT(field.Offset() == Closure::delayed_type_arguments_offset());
   field ^= fields.At(3);
-  ASSERT(field.Offset() == Closure::context_offset());
+  ASSERT(field.Offset() == Closure::function_offset());
   field ^= fields.At(4);
+  ASSERT(field.Offset() == Closure::context_offset());
+  field ^= fields.At(5);
   ASSERT(field.Offset() == Closure::hash_offset());
 #endif  // defined(DEBUG)
 
diff --git a/runtime/vm/bootstrap_nocore.cc b/runtime/vm/bootstrap_nocore.cc
index 2a3e095..679c41f 100644
--- a/runtime/vm/bootstrap_nocore.cc
+++ b/runtime/vm/bootstrap_nocore.cc
@@ -49,17 +49,19 @@
 #if defined(DEBUG)
   // Verify that closure field offsets are identical in Dart and C++.
   const Array& fields = Array::Handle(zone, cls.fields());
-  ASSERT(fields.Length() == 5);
+  ASSERT(fields.Length() == 6);
   Field& field = Field::Handle(zone);
   field ^= fields.At(0);
   ASSERT(field.Offset() == Closure::instantiator_type_arguments_offset());
   field ^= fields.At(1);
   ASSERT(field.Offset() == Closure::function_type_arguments_offset());
   field ^= fields.At(2);
-  ASSERT(field.Offset() == Closure::function_offset());
+  ASSERT(field.Offset() == Closure::delayed_type_arguments_offset());
   field ^= fields.At(3);
-  ASSERT(field.Offset() == Closure::context_offset());
+  ASSERT(field.Offset() == Closure::function_offset());
   field ^= fields.At(4);
+  ASSERT(field.Offset() == Closure::context_offset());
+  field ^= fields.At(5);
   ASSERT(field.Offset() == Closure::hash_offset());
 #endif  // defined(DEBUG)
 
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 03dbd3b..6243d52 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -5062,13 +5062,13 @@
   AddBaseObject(Object::zero_array().raw());
   AddBaseObject(Object::dynamic_type().raw());
   AddBaseObject(Object::void_type().raw());
+  AddBaseObject(Object::empty_type_arguments().raw());
   AddBaseObject(Bool::True().raw());
   AddBaseObject(Bool::False().raw());
   ASSERT(Object::extractor_parameter_types().raw() != Object::null());
   AddBaseObject(Object::extractor_parameter_types().raw());
   ASSERT(Object::extractor_parameter_names().raw() != Object::null());
   AddBaseObject(Object::extractor_parameter_names().raw());
-  AddBaseObject(Object::empty_context().raw());
   AddBaseObject(Object::empty_context_scope().raw());
   AddBaseObject(Object::empty_descriptors().raw());
   AddBaseObject(Object::empty_var_descriptors().raw());
@@ -5507,13 +5507,13 @@
   AddBaseObject(Object::zero_array().raw());
   AddBaseObject(Object::dynamic_type().raw());
   AddBaseObject(Object::void_type().raw());
+  AddBaseObject(Object::empty_type_arguments().raw());
   AddBaseObject(Bool::True().raw());
   AddBaseObject(Bool::False().raw());
   ASSERT(Object::extractor_parameter_types().raw() != Object::null());
   AddBaseObject(Object::extractor_parameter_types().raw());
   ASSERT(Object::extractor_parameter_names().raw() != Object::null());
   AddBaseObject(Object::extractor_parameter_names().raw());
-  AddBaseObject(Object::empty_context().raw());
   AddBaseObject(Object::empty_context_scope().raw());
   AddBaseObject(Object::empty_descriptors().raw());
   AddBaseObject(Object::empty_var_descriptors().raw());
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 5d30eda..66f0543 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -26,6 +26,7 @@
 // Quick access to the current zone and isolate.
 #define I (isolate())
 #define Z (graph_->zone())
+#define T (graph_->thread())
 
 ConstantPropagator::ConstantPropagator(
     FlowGraph* graph,
@@ -1321,6 +1322,7 @@
   // instructions, previous pointers, predecessors, etc. after eliminating
   // unreachable code.  We do not maintain those properties during the
   // transformation.
+  auto& value = Object::Handle(Z);
   for (BlockIterator b = graph_->reverse_postorder_iterator(); !b.Done();
        b.Advance()) {
     BlockEntryInstr* block = b.Current();
@@ -1398,7 +1400,14 @@
           THR_Print("Constant v%" Pd " = %s\n", defn->ssa_temp_index(),
                     defn->constant_value().ToCString());
         }
-        ConstantInstr* constant = graph_->GetConstant(defn->constant_value());
+        value = defn->constant_value().raw();
+        if ((value.IsString() || value.IsMint() || value.IsDouble()) &&
+            !value.IsCanonical()) {
+          const char* error_str = nullptr;
+          value = Instance::Cast(value).CheckAndCanonicalize(T, &error_str);
+          ASSERT(!value.IsNull() && (error_str == nullptr));
+        }
+        ConstantInstr* constant = graph_->GetConstant(value);
         defn->ReplaceUsesWith(constant);
         i.RemoveCurrentFromGraph();
       }
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index cd4d8f0..9b5729c 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -2898,21 +2898,21 @@
 
     LocalVariable* closure_parameter = scope->VariableAt(0);
     ASSERT(!closure_parameter->is_captured());
-    __ LoadFromOffset(kWord, CTX, FP, closure_parameter->index() * kWordSize);
-    __ LoadFieldFromOffset(kWord, CTX, CTX, Closure::context_offset());
+    __ LoadFromOffset(kWord, R6, FP, closure_parameter->index() * kWordSize);
+    __ LoadFieldFromOffset(kWord, R6, R6, Closure::context_offset());
 
     const intptr_t context_index =
         parsed_function.current_context_var()->index();
-    __ StoreToOffset(kWord, CTX, FP, context_index * kWordSize);
+    __ StoreToOffset(kWord, R6, FP, context_index * kWordSize);
   }
 
   // Initialize exception and stack trace variables.
   if (exception_var().is_captured()) {
     ASSERT(stacktrace_var().is_captured());
-    __ StoreIntoObjectOffset(CTX,
+    __ StoreIntoObjectOffset(R6,
                              Context::variable_offset(exception_var().index()),
                              kExceptionObjectReg);
-    __ StoreIntoObjectOffset(CTX,
+    __ StoreIntoObjectOffset(R6,
                              Context::variable_offset(stacktrace_var().index()),
                              kStackTraceObjectReg);
   } else {
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 595c61a..9c0a698 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -2647,21 +2647,21 @@
 
     LocalVariable* closure_parameter = scope->VariableAt(0);
     ASSERT(!closure_parameter->is_captured());
-    __ LoadFromOffset(CTX, FP, closure_parameter->index() * kWordSize);
-    __ LoadFieldFromOffset(CTX, CTX, Closure::context_offset());
+    __ LoadFromOffset(R28, FP, closure_parameter->index() * kWordSize);
+    __ LoadFieldFromOffset(R28, R28, Closure::context_offset());
 
     const intptr_t context_index =
         parsed_function.current_context_var()->index();
-    __ StoreToOffset(CTX, FP, context_index * kWordSize);
+    __ StoreToOffset(R28, FP, context_index * kWordSize);
   }
 
   // Initialize exception and stack trace variables.
   if (exception_var().is_captured()) {
     ASSERT(stacktrace_var().is_captured());
-    __ StoreIntoObjectOffset(CTX,
+    __ StoreIntoObjectOffset(R28,
                              Context::variable_offset(exception_var().index()),
                              kExceptionObjectReg);
-    __ StoreIntoObjectOffset(CTX,
+    __ StoreIntoObjectOffset(R28,
                              Context::variable_offset(stacktrace_var().index()),
                              kStackTraceObjectReg);
   } else {
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 68ba62f..c92b517 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -2506,12 +2506,12 @@
 
     LocalVariable* closure_parameter = scope->VariableAt(0);
     ASSERT(!closure_parameter->is_captured());
-    __ movl(CTX, Address(EBP, closure_parameter->index() * kWordSize));
-    __ movl(CTX, FieldAddress(CTX, Closure::context_offset()));
+    __ movl(EDI, Address(EBP, closure_parameter->index() * kWordSize));
+    __ movl(EDI, FieldAddress(EDI, Closure::context_offset()));
 
 #ifdef DEBUG
     Label ok;
-    __ LoadClassId(EBX, CTX);
+    __ LoadClassId(EBX, EDI);
     __ cmpl(EBX, Immediate(kContextCid));
     __ j(EQUAL, &ok, Assembler::kNearJump);
     __ Stop("Incorrect context at entry");
@@ -2520,19 +2520,19 @@
 
     const intptr_t context_index =
         parsed_function.current_context_var()->index();
-    __ movl(Address(EBP, context_index * kWordSize), CTX);
+    __ movl(Address(EBP, context_index * kWordSize), EDI);
   }
 
   // Initialize exception and stack trace variables.
   if (exception_var().is_captured()) {
     ASSERT(stacktrace_var().is_captured());
     __ StoreIntoObject(
-        CTX,
-        FieldAddress(CTX, Context::variable_offset(exception_var().index())),
+        EDI,
+        FieldAddress(EDI, Context::variable_offset(exception_var().index())),
         kExceptionObjectReg);
     __ StoreIntoObject(
-        CTX,
-        FieldAddress(CTX, Context::variable_offset(stacktrace_var().index())),
+        EDI,
+        FieldAddress(EDI, Context::variable_offset(stacktrace_var().index())),
         kStackTraceObjectReg);
   } else {
     // Restore stack and initialize the two exception variables:
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 20495f3..b44d650 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -2581,12 +2581,12 @@
 
     LocalVariable* closure_parameter = scope->VariableAt(0);
     ASSERT(!closure_parameter->is_captured());
-    __ movq(CTX, Address(RBP, closure_parameter->index() * kWordSize));
-    __ movq(CTX, FieldAddress(CTX, Closure::context_offset()));
+    __ movq(R12, Address(RBP, closure_parameter->index() * kWordSize));
+    __ movq(R12, FieldAddress(R12, Closure::context_offset()));
 
 #ifdef DEBUG
     Label ok;
-    __ LoadClassId(RBX, CTX);
+    __ LoadClassId(RBX, R12);
     __ cmpq(RBX, Immediate(kContextCid));
     __ j(EQUAL, &ok, Assembler::kNearJump);
     __ Stop("Incorrect context at entry");
@@ -2595,19 +2595,19 @@
 
     const intptr_t context_index =
         parsed_function.current_context_var()->index();
-    __ movq(Address(RBP, context_index * kWordSize), CTX);
+    __ movq(Address(RBP, context_index * kWordSize), R12);
   }
 
   // Initialize exception and stack trace variables.
   if (exception_var().is_captured()) {
     ASSERT(stacktrace_var().is_captured());
     __ StoreIntoObject(
-        CTX,
-        FieldAddress(CTX, Context::variable_offset(exception_var().index())),
+        R12,
+        FieldAddress(R12, Context::variable_offset(exception_var().index())),
         kExceptionObjectReg);
     __ StoreIntoObject(
-        CTX,
-        FieldAddress(CTX, Context::variable_offset(stacktrace_var().index())),
+        R12,
+        FieldAddress(R12, Context::variable_offset(stacktrace_var().index())),
         kStackTraceObjectReg);
   } else {
     __ movq(Address(RBP, exception_var().index() * kWordSize),
diff --git a/runtime/vm/compiler/frontend/flow_graph_builder.cc b/runtime/vm/compiler/frontend/flow_graph_builder.cc
index 7ddfd0c..5c82158 100644
--- a/runtime/vm/compiler/frontend/flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/flow_graph_builder.cc
@@ -2318,6 +2318,17 @@
           type_arguments, kEmitStoreBarrier, node->token_pos()));
     }
 
+    // Mark that there are no delayed type arguments.
+    {
+      Value* closure_tmp_val =
+          Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos()));
+      Value* type_arguments =
+          Bind(new (Z) ConstantInstr(Object::empty_type_arguments()));
+      Do(new (Z) StoreInstanceFieldInstr(
+          Closure::delayed_type_arguments_offset(), closure_tmp_val,
+          type_arguments, kEmitStoreBarrier, node->token_pos()));
+    }
+
     // Store function.
     Value* closure_tmp_val =
         Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos()));
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index a0cb2ef..4b86b49 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -34,46 +34,46 @@
   // Ordered with fall-through.
   switch (next_read_) {
     case kStart: {
-      Tag tag = builder_->ReadTag();  // read tag.
+      Tag tag = helper_->ReadTag();  // read tag.
       ASSERT(tag == kFunctionNode);
       if (++next_read_ == field) return;
     }
     case kPosition:
-      position_ = builder_->ReadPosition();  // read position.
+      position_ = helper_->ReadPosition();  // read position.
       if (++next_read_ == field) return;
     case kEndPosition:
-      end_position_ = builder_->ReadPosition();  // read end position.
+      end_position_ = helper_->ReadPosition();  // read end position.
       if (++next_read_ == field) return;
     case kAsyncMarker:
-      async_marker_ = static_cast<AsyncMarker>(builder_->ReadByte());
+      async_marker_ = static_cast<AsyncMarker>(helper_->ReadByte());
       if (++next_read_ == field) return;
     case kDartAsyncMarker:
       dart_async_marker_ = static_cast<AsyncMarker>(
-          builder_->ReadByte());  // read dart async marker.
+          helper_->ReadByte());  // read dart async marker.
       if (++next_read_ == field) return;
     case kTypeParameters:
-      builder_->SkipTypeParametersList();  // read type parameters.
+      helper_->SkipTypeParametersList();  // read type parameters.
       if (++next_read_ == field) return;
     case kTotalParameterCount:
       total_parameter_count_ =
-          builder_->ReadUInt();  // read total parameter count.
+          helper_->ReadUInt();  // read total parameter count.
       if (++next_read_ == field) return;
     case kRequiredParameterCount:
       required_parameter_count_ =
-          builder_->ReadUInt();  // read required parameter count.
+          helper_->ReadUInt();  // read required parameter count.
       if (++next_read_ == field) return;
     case kPositionalParameters:
-      builder_->SkipListOfVariableDeclarations();  // read positionals.
+      helper_->SkipListOfVariableDeclarations();  // read positionals.
       if (++next_read_ == field) return;
     case kNamedParameters:
-      builder_->SkipListOfVariableDeclarations();  // read named.
+      helper_->SkipListOfVariableDeclarations();  // read named.
       if (++next_read_ == field) return;
     case kReturnType:
-      builder_->SkipDartType();  // read return type.
+      helper_->SkipDartType();  // read return type.
       if (++next_read_ == field) return;
     case kBody:
-      if (builder_->ReadTag() == kSomething)
-        builder_->SkipStatement();  // read body.
+      if (helper_->ReadTag() == kSomething)
+        helper_->SkipStatement();  // read body.
       if (++next_read_ == field) return;
     case kEnd:
       return;
@@ -84,20 +84,20 @@
   for (; next_read_ < field; ++next_read_) {
     switch (next_read_) {
       case kFlags:
-        flags_ = builder_->ReadFlags();
+        flags_ = helper_->ReadFlags();
         break;
       case kAnnotations:
-        builder_->SkipListOfExpressions();  // read annotations.
+        helper_->SkipListOfExpressions();  // read annotations.
         break;
       case kName:
-        name_index_ = builder_->ReadStringReference();  // read name index.
+        name_index_ = helper_->ReadStringReference();  // read name index.
         break;
       case kBound:
-        builder_->SkipDartType();
+        helper_->SkipDartType();
         break;
       case kDefaultType:
-        if (builder_->ReadTag() == kSomething) {
-          builder_->SkipDartType();
+        if (helper_->ReadTag() == kSomething) {
+          helper_->SkipDartType();
         }
         break;
       case kEnd:
@@ -112,37 +112,37 @@
   // Ordered with fall-through.
   switch (next_read_) {
     case kPosition:
-      position_ = builder_->ReadPosition();  // read position.
+      position_ = helper_->ReadPosition();  // read position.
       if (++next_read_ == field) return;
     case kEqualPosition:
-      equals_position_ = builder_->ReadPosition();  // read equals position.
+      equals_position_ = helper_->ReadPosition();  // read equals position.
       if (++next_read_ == field) return;
     case kAnnotations:
-      builder_->SkipListOfExpressions();  // read annotations.
+      helper_->SkipListOfExpressions();  // read annotations.
       if (++next_read_ == field) return;
     case kFlags:
-      flags_ = builder_->ReadFlags();
+      flags_ = helper_->ReadFlags();
       if (++next_read_ == field) return;
     case kNameIndex:
-      name_index_ = builder_->ReadStringReference();  // read name index.
+      name_index_ = helper_->ReadStringReference();  // read name index.
       if (++next_read_ == field) return;
     case kType:
-      builder_->SkipDartType();  // read type.
+      helper_->SkipDartType();  // read type.
       if (++next_read_ == field) return;
     case kInitializer:
-      if (builder_->ReadTag() == kSomething)
-        builder_->SkipExpression();  // read initializer.
+      if (helper_->ReadTag() == kSomething)
+        helper_->SkipExpression();  // read initializer.
       if (++next_read_ == field) return;
     case kEnd:
       return;
   }
 }
 
-FieldHelper::FieldHelper(StreamingFlowGraphBuilder* builder, intptr_t offset)
-    : builder_(builder),
+FieldHelper::FieldHelper(KernelReaderHelper* helper, intptr_t offset)
+    : helper_(helper),
       next_read_(kStart),
       has_function_literal_initializer_(false) {
-  builder_->SetOffset(offset);
+  helper_->SetOffset(offset);
 }
 
 void FieldHelper::ReadUntilExcluding(Field field,
@@ -152,62 +152,62 @@
   // Ordered with fall-through.
   switch (next_read_) {
     case kStart: {
-      Tag tag = builder_->ReadTag();  // read tag.
+      Tag tag = helper_->ReadTag();  // read tag.
       ASSERT(tag == kField);
       if (++next_read_ == field) return;
     }
     case kCanonicalName:
       canonical_name_ =
-          builder_->ReadCanonicalNameReference();  // read canonical_name.
+          helper_->ReadCanonicalNameReference();  // read canonical_name.
       if (++next_read_ == field) return;
     case kSourceUriIndex:
-      source_uri_index_ = builder_->ReadUInt();  // read source_uri_index.
-      builder_->current_script_id_ = source_uri_index_;
+      source_uri_index_ = helper_->ReadUInt();  // read source_uri_index.
+      helper_->set_current_script_id(source_uri_index_);
       if (++next_read_ == field) return;
     case kPosition:
-      position_ = builder_->ReadPosition(false);  // read position.
-      builder_->record_token_position(position_);
+      position_ = helper_->ReadPosition(false);  // read position.
+      helper_->RecordTokenPosition(position_);
       if (++next_read_ == field) return;
     case kEndPosition:
-      end_position_ = builder_->ReadPosition(false);  // read end position.
-      builder_->record_token_position(end_position_);
+      end_position_ = helper_->ReadPosition(false);  // read end position.
+      helper_->RecordTokenPosition(end_position_);
       if (++next_read_ == field) return;
     case kFlags:
-      flags_ = builder_->ReadFlags();
+      flags_ = helper_->ReadFlags();
       if (++next_read_ == field) return;
     case kFlags2:
-      builder_->ReadFlags();
+      secondary_flags_ = helper_->ReadFlags();
       if (++next_read_ == field) return;
     case kName:
-      builder_->SkipName();  // read name.
+      helper_->SkipName();  // read name.
       if (++next_read_ == field) return;
     case kAnnotations: {
-      annotation_count_ = builder_->ReadListLength();  // read list length.
+      annotation_count_ = helper_->ReadListLength();  // read list length.
       for (intptr_t i = 0; i < annotation_count_; ++i) {
-        builder_->SkipExpression();  // read ith expression.
+        helper_->SkipExpression();  // read ith expression.
       }
       if (++next_read_ == field) return;
     }
     case kType:
-      builder_->SkipDartType();  // read type.
+      helper_->SkipDartType();  // read type.
       if (++next_read_ == field) return;
     case kInitializer:
-      if (builder_->ReadTag() == kSomething) {
+      if (helper_->ReadTag() == kSomething) {
         if (detect_function_literal_initializer &&
-            builder_->PeekTag() == kFunctionExpression) {
-          AlternativeReadingScope alt(&builder_->reader_);
-          Tag tag = builder_->ReadTag();
+            helper_->PeekTag() == kFunctionExpression) {
+          AlternativeReadingScope alt(&helper_->reader_);
+          Tag tag = helper_->ReadTag();
           ASSERT(tag == kFunctionExpression);
-          builder_->ReadPosition();  // read position.
+          helper_->ReadPosition();  // read position.
 
-          FunctionNodeHelper helper(builder_);
+          FunctionNodeHelper helper(helper_);
           helper.ReadUntilIncluding(FunctionNodeHelper::kEndPosition);
 
           has_function_literal_initializer_ = true;
           function_literal_start_ = helper.position_;
           function_literal_end_ = helper.end_position_;
         }
-        builder_->SkipExpression();  // read initializer.
+        helper_->SkipExpression();  // read initializer.
       }
       if (++next_read_ == field) return;
     case kEnd:
@@ -221,56 +221,56 @@
   // Ordered with fall-through.
   switch (next_read_) {
     case kStart: {
-      Tag tag = builder_->ReadTag();  // read tag.
+      Tag tag = helper_->ReadTag();  // read tag.
       ASSERT(tag == kProcedure);
       if (++next_read_ == field) return;
     }
     case kCanonicalName:
       canonical_name_ =
-          builder_->ReadCanonicalNameReference();  // read canonical_name.
+          helper_->ReadCanonicalNameReference();  // read canonical_name.
       if (++next_read_ == field) return;
     case kSourceUriIndex:
-      source_uri_index_ = builder_->ReadUInt();  // read source_uri_index.
-      builder_->current_script_id_ = source_uri_index_;
+      source_uri_index_ = helper_->ReadUInt();  // read source_uri_index.
+      helper_->set_current_script_id(source_uri_index_);
       if (++next_read_ == field) return;
     case kPosition:
-      position_ = builder_->ReadPosition(false);  // read position.
-      builder_->record_token_position(position_);
+      position_ = helper_->ReadPosition(false);  // read position.
+      helper_->RecordTokenPosition(position_);
       if (++next_read_ == field) return;
     case kEndPosition:
-      end_position_ = builder_->ReadPosition(false);  // read end position.
-      builder_->record_token_position(end_position_);
+      end_position_ = helper_->ReadPosition(false);  // read end position.
+      helper_->RecordTokenPosition(end_position_);
       if (++next_read_ == field) return;
     case kKind:
-      kind_ = static_cast<Kind>(builder_->ReadByte());
+      kind_ = static_cast<Kind>(helper_->ReadByte());
       if (++next_read_ == field) return;
     case kFlags:
-      flags_ = builder_->ReadFlags();
-      flags2_ = builder_->ReadFlags();
+      flags_ = helper_->ReadFlags();
+      flags2_ = helper_->ReadFlags();
       if (++next_read_ == field) return;
     case kName:
-      builder_->SkipName();  // read name.
+      helper_->SkipName();  // read name.
       if (++next_read_ == field) return;
     case kAnnotations: {
-      annotation_count_ = builder_->ReadListLength();  // read list length.
+      annotation_count_ = helper_->ReadListLength();  // read list length.
       for (intptr_t i = 0; i < annotation_count_; ++i) {
-        builder_->SkipExpression();  // read ith expression.
+        helper_->SkipExpression();  // read ith expression.
       }
       if (++next_read_ == field) return;
     }
     case kForwardingStubSuperTarget:
-      if (builder_->ReadTag() == kSomething) {
-        forwarding_stub_super_target_ = builder_->ReadCanonicalNameReference();
+      if (helper_->ReadTag() == kSomething) {
+        forwarding_stub_super_target_ = helper_->ReadCanonicalNameReference();
       }
       if (++next_read_ == field) return;
     case kForwardingStubInterfaceTarget:
-      if (builder_->ReadTag() == kSomething) {
-        builder_->ReadCanonicalNameReference();
+      if (helper_->ReadTag() == kSomething) {
+        helper_->ReadCanonicalNameReference();
       }
       if (++next_read_ == field) return;
     case kFunction:
-      if (builder_->ReadTag() == kSomething)
-        builder_->SkipFunctionNode();  // read function node.
+      if (helper_->ReadTag() == kSomething)
+        helper_->SkipFunctionNode();  // read function node.
       if (++next_read_ == field) return;
     case kEnd:
       return;
@@ -283,47 +283,47 @@
   // Ordered with fall-through.
   switch (next_read_) {
     case kStart: {
-      Tag tag = builder_->ReadTag();  // read tag.
+      Tag tag = helper_->ReadTag();  // read tag.
       ASSERT(tag == kConstructor);
       if (++next_read_ == field) return;
     }
     case kCanonicalName:
       canonical_name_ =
-          builder_->ReadCanonicalNameReference();  // read canonical_name.
+          helper_->ReadCanonicalNameReference();  // read canonical_name.
       if (++next_read_ == field) return;
     case kSourceUriIndex:
-      source_uri_index_ = builder_->ReadUInt();  // read source_uri_index.
-      builder_->current_script_id_ = source_uri_index_;
+      source_uri_index_ = helper_->ReadUInt();  // read source_uri_index.
+      helper_->set_current_script_id(source_uri_index_);
       if (++next_read_ == field) return;
     case kPosition:
-      position_ = builder_->ReadPosition();  // read position.
-      builder_->record_token_position(position_);
+      position_ = helper_->ReadPosition();  // read position.
+      helper_->RecordTokenPosition(position_);
       if (++next_read_ == field) return;
     case kEndPosition:
-      end_position_ = builder_->ReadPosition();  // read end position.
-      builder_->record_token_position(end_position_);
+      end_position_ = helper_->ReadPosition();  // read end position.
+      helper_->RecordTokenPosition(end_position_);
       if (++next_read_ == field) return;
     case kFlags:
-      flags_ = builder_->ReadFlags();
+      flags_ = helper_->ReadFlags();
       if (++next_read_ == field) return;
     case kName:
-      builder_->SkipName();  // read name.
+      helper_->SkipName();  // read name.
       if (++next_read_ == field) return;
     case kAnnotations: {
-      annotation_count_ = builder_->ReadListLength();  // read list length.
+      annotation_count_ = helper_->ReadListLength();  // read list length.
       for (intptr_t i = 0; i < annotation_count_; ++i) {
-        builder_->SkipExpression();  // read ith expression.
+        helper_->SkipExpression();  // read ith expression.
       }
       if (++next_read_ == field) return;
     }
     case kFunction:
-      builder_->SkipFunctionNode();  // read function.
+      helper_->SkipFunctionNode();  // read function.
       if (++next_read_ == field) return;
     case kInitializers: {
       intptr_t list_length =
-          builder_->ReadListLength();  // read initializers list length.
+          helper_->ReadListLength();  // read initializers list length.
       for (intptr_t i = 0; i < list_length; i++) {
-        builder_->SkipInitializer();
+        helper_->SkipInitializer();
       }
       if (++next_read_ == field) return;
     }
@@ -338,82 +338,82 @@
   // Ordered with fall-through.
   switch (next_read_) {
     case kStart: {
-      Tag tag = builder_->ReadTag();  // read tag.
+      Tag tag = helper_->ReadTag();  // read tag.
       ASSERT(tag == kClass);
       if (++next_read_ == field) return;
     }
     case kCanonicalName:
       canonical_name_ =
-          builder_->ReadCanonicalNameReference();  // read canonical_name.
+          helper_->ReadCanonicalNameReference();  // read canonical_name.
       if (++next_read_ == field) return;
     case kSourceUriIndex:
-      source_uri_index_ = builder_->ReadUInt();  // read source_uri_index.
-      builder_->current_script_id_ = source_uri_index_;
+      source_uri_index_ = helper_->ReadUInt();  // read source_uri_index.
+      helper_->set_current_script_id(source_uri_index_);
       if (++next_read_ == field) return;
     case kPosition:
-      position_ = builder_->ReadPosition(false);  // read position.
-      builder_->record_token_position(position_);
+      position_ = helper_->ReadPosition(false);  // read position.
+      helper_->RecordTokenPosition(position_);
       if (++next_read_ == field) return;
     case kEndPosition:
-      end_position_ = builder_->ReadPosition();  // read end position.
-      builder_->record_token_position(end_position_);
+      end_position_ = helper_->ReadPosition();  // read end position.
+      helper_->RecordTokenPosition(end_position_);
       if (++next_read_ == field) return;
     case kFlags:
-      flags_ = builder_->ReadFlags();  // read flags.
+      flags_ = helper_->ReadFlags();  // read flags.
       if (++next_read_ == field) return;
     case kNameIndex:
-      name_index_ = builder_->ReadStringReference();  // read name index.
+      name_index_ = helper_->ReadStringReference();  // read name index.
       if (++next_read_ == field) return;
     case kAnnotations: {
-      annotation_count_ = builder_->ReadListLength();  // read list length.
+      annotation_count_ = helper_->ReadListLength();  // read list length.
       for (intptr_t i = 0; i < annotation_count_; ++i) {
-        builder_->SkipExpression();  // read ith expression.
+        helper_->SkipExpression();  // read ith expression.
       }
       if (++next_read_ == field) return;
     }
     case kTypeParameters:
-      builder_->SkipTypeParametersList();  // read type parameters.
+      helper_->SkipTypeParametersList();  // read type parameters.
       if (++next_read_ == field) return;
     case kSuperClass: {
-      Tag type_tag = builder_->ReadTag();  // read super class type (part 1).
+      Tag type_tag = helper_->ReadTag();  // read super class type (part 1).
       if (type_tag == kSomething) {
-        builder_->SkipDartType();  // read super class type (part 2).
+        helper_->SkipDartType();  // read super class type (part 2).
       }
       if (++next_read_ == field) return;
     }
     case kMixinType: {
-      Tag type_tag = builder_->ReadTag();  // read mixin type (part 1).
+      Tag type_tag = helper_->ReadTag();  // read mixin type (part 1).
       if (type_tag == kSomething) {
-        builder_->SkipDartType();  // read mixin type (part 2).
+        helper_->SkipDartType();  // read mixin type (part 2).
       }
       if (++next_read_ == field) return;
     }
     case kImplementedClasses:
-      builder_->SkipListOfDartTypes();  // read implemented_classes.
+      helper_->SkipListOfDartTypes();  // read implemented_classes.
       if (++next_read_ == field) return;
     case kFields: {
       intptr_t list_length =
-          builder_->ReadListLength();  // read fields list length.
+          helper_->ReadListLength();  // read fields list length.
       for (intptr_t i = 0; i < list_length; i++) {
-        FieldHelper field_helper(builder_);
+        FieldHelper field_helper(helper_);
         field_helper.ReadUntilExcluding(FieldHelper::kEnd);  // read field.
       }
       if (++next_read_ == field) return;
     }
     case kConstructors: {
       intptr_t list_length =
-          builder_->ReadListLength();  // read constructors list length.
+          helper_->ReadListLength();  // read constructors list length.
       for (intptr_t i = 0; i < list_length; i++) {
-        ConstructorHelper constructor_helper(builder_);
+        ConstructorHelper constructor_helper(helper_);
         constructor_helper.ReadUntilExcluding(
             ConstructorHelper::kEnd);  // read constructor.
       }
       if (++next_read_ == field) return;
     }
     case kProcedures: {
-      procedure_count_ = builder_->ReadListLength();  // read procedures #.
+      procedure_count_ = helper_->ReadListLength();  // read procedures #.
       for (intptr_t i = 0; i < procedure_count_; i++) {
-        ProcedureHelper procedure_helper(builder_);
+        ProcedureHelper procedure_helper(helper_);
         procedure_helper.ReadUntilExcluding(
             ProcedureHelper::kEnd);  // read procedure.
       }
@@ -422,10 +422,10 @@
     case kClassIndex:
       // Read class index.
       for (intptr_t i = 0; i < procedure_count_; ++i) {
-        builder_->reader_.ReadUInt32();
+        helper_->reader_.ReadUInt32();
       }
-      builder_->reader_.ReadUInt32();
-      builder_->reader_.ReadUInt32();
+      helper_->reader_.ReadUInt32();
+      helper_->reader_.ReadUInt32();
       if (++next_read_ == field) return;
     case kEnd:
       return;
@@ -438,71 +438,71 @@
   // Ordered with fall-through.
   switch (next_read_) {
     case kFlags: {
-      flags_ = builder_->ReadFlags();
+      flags_ = helper_->ReadFlags();
       if (++next_read_ == field) return;
     }
     case kCanonicalName:
       canonical_name_ =
-          builder_->ReadCanonicalNameReference();  // read canonical_name.
+          helper_->ReadCanonicalNameReference();  // read canonical_name.
       if (++next_read_ == field) return;
     case kName:
-      name_index_ = builder_->ReadStringReference();  // read name index.
+      name_index_ = helper_->ReadStringReference();  // read name index.
       if (++next_read_ == field) return;
     case kSourceUriIndex:
-      source_uri_index_ = builder_->ReadUInt();  // read source_uri_index.
-      builder_->current_script_id_ = source_uri_index_;
+      source_uri_index_ = helper_->ReadUInt();  // read source_uri_index.
+      helper_->set_current_script_id(source_uri_index_);
       if (++next_read_ == field) return;
     case kAnnotations:
-      builder_->SkipListOfExpressions();  // read annotations.
+      helper_->SkipListOfExpressions();  // read annotations.
       if (++next_read_ == field) return;
     case kDependencies: {
-      intptr_t dependency_count = builder_->ReadUInt();  // read list length.
+      intptr_t dependency_count = helper_->ReadUInt();  // read list length.
       for (intptr_t i = 0; i < dependency_count; ++i) {
-        builder_->SkipLibraryDependency();
+        helper_->SkipLibraryDependency();
       }
       if (++next_read_ == field) return;
     }
     case kAdditionalExports: {
-      intptr_t name_count = builder_->ReadUInt();
+      intptr_t name_count = helper_->ReadUInt();
       for (intptr_t i = 0; i < name_count; ++i) {
-        builder_->SkipCanonicalNameReference();
+        helper_->SkipCanonicalNameReference();
       }
       if (++next_read_ == field) return;
     }
     case kParts: {
-      intptr_t part_count = builder_->ReadUInt();  // read list length.
+      intptr_t part_count = helper_->ReadUInt();  // read list length.
       for (intptr_t i = 0; i < part_count; ++i) {
-        builder_->SkipLibraryPart();
+        helper_->SkipLibraryPart();
       }
       if (++next_read_ == field) return;
     }
     case kTypedefs: {
-      intptr_t typedef_count = builder_->ReadListLength();  // read list length.
+      intptr_t typedef_count = helper_->ReadListLength();  // read list length.
       for (intptr_t i = 0; i < typedef_count; i++) {
-        builder_->SkipLibraryTypedef();
+        helper_->SkipLibraryTypedef();
       }
       if (++next_read_ == field) return;
     }
     case kClasses: {
-      class_count_ = builder_->ReadListLength();  // read list length.
+      class_count_ = helper_->ReadListLength();  // read list length.
       for (intptr_t i = 0; i < class_count_; ++i) {
-        ClassHelper class_helper(builder_);
+        ClassHelper class_helper(helper_);
         class_helper.ReadUntilExcluding(ClassHelper::kEnd);
       }
       if (++next_read_ == field) return;
     }
     case kToplevelField: {
-      intptr_t field_count = builder_->ReadListLength();  // read list length.
+      intptr_t field_count = helper_->ReadListLength();  // read list length.
       for (intptr_t i = 0; i < field_count; ++i) {
-        FieldHelper field_helper(builder_);
+        FieldHelper field_helper(helper_);
         field_helper.ReadUntilExcluding(FieldHelper::kEnd);
       }
       if (++next_read_ == field) return;
     }
     case kToplevelProcedures: {
-      procedure_count_ = builder_->ReadListLength();  // read list length.
+      procedure_count_ = helper_->ReadListLength();  // read list length.
       for (intptr_t i = 0; i < procedure_count_; ++i) {
-        ProcedureHelper procedure_helper(builder_);
+        ProcedureHelper procedure_helper(helper_);
         procedure_helper.ReadUntilExcluding(ProcedureHelper::kEnd);
       }
       if (++next_read_ == field) return;
@@ -510,15 +510,15 @@
     case kLibraryIndex:
       // Read library index.
       for (intptr_t i = 0; i < class_count_; ++i) {
-        builder_->reader_.ReadUInt32();
+        helper_->reader_.ReadUInt32();
       }
-      builder_->reader_.ReadUInt32();
-      builder_->reader_.ReadUInt32();
+      helper_->reader_.ReadUInt32();
+      helper_->reader_.ReadUInt32();
       for (intptr_t i = 0; i < procedure_count_; ++i) {
-        builder_->reader_.ReadUInt32();
+        helper_->reader_.ReadUInt32();
       }
-      builder_->reader_.ReadUInt32();
-      builder_->reader_.ReadUInt32();
+      helper_->reader_.ReadUInt32();
+      helper_->reader_.ReadUInt32();
       if (++next_read_ == field) return;
     case kEnd:
       return;
@@ -531,32 +531,32 @@
   // Ordered with fall-through.
   switch (next_read_) {
     case kFileOffset: {
-      builder_->ReadPosition();
+      helper_->ReadPosition();
       if (++next_read_ == field) return;
     }
     case kFlags: {
-      flags_ = builder_->ReadFlags();
+      flags_ = helper_->ReadFlags();
       if (++next_read_ == field) return;
     }
     case kAnnotations: {
-      builder_->SkipListOfExpressions();
+      helper_->SkipListOfExpressions();
       if (++next_read_ == field) return;
     }
     case kTargetLibrary: {
-      target_library_canonical_name_ = builder_->ReadCanonicalNameReference();
+      target_library_canonical_name_ = helper_->ReadCanonicalNameReference();
       if (++next_read_ == field) return;
     }
     case kName: {
-      name_index_ = builder_->ReadStringReference();
+      name_index_ = helper_->ReadStringReference();
       if (++next_read_ == field) return;
     }
     case kCombinators: {
-      intptr_t count = builder_->ReadListLength();
+      intptr_t count = helper_->ReadListLength();
       for (intptr_t i = 0; i < count; ++i) {
         // Skip flags
-        builder_->SkipBytes(1);
+        helper_->SkipBytes(1);
         // Skip list of names.
-        builder_->SkipListOfStrings();
+        helper_->SkipListOfStrings();
       }
       if (++next_read_ == field) return;
     }
@@ -894,7 +894,8 @@
   scope_->set_end_token_pos(function.end_token_pos());
 
   // Add function type arguments variable before current context variable.
-  if (I->reify_generic_functions() && function.IsGeneric()) {
+  if (I->reify_generic_functions() &&
+      (function.IsGeneric() || function.HasGenericParent())) {
     LocalVariable* type_args_var = MakeVariable(
         TokenPosition::kNoSource, TokenPosition::kNoSource,
         Symbols::FunctionTypeArgumentsVar(), AbstractType::dynamic_type());
@@ -3775,6 +3776,705 @@
   }
 }
 
+void KernelFingerprintHelper::BuildHash(uint32_t val) {
+  hash_ = CalculateHash(hash_, val);
+}
+
+void KernelFingerprintHelper::CalculateConstructorFingerprint() {
+  ConstructorHelper helper(this);
+
+  helper.ReadUntilExcluding(ConstructorHelper::kAnnotations);
+  CalculateListOfExpressionsFingerprint();
+  CalculateFunctionNodeFingerprint();
+  intptr_t len = ReadListLength();
+  for (intptr_t i = 0; i < len; ++i) {
+    CalculateInitializerFingerprint();
+  }
+  helper.SetJustRead(ConstructorHelper::kInitializers);
+  BuildHash(helper.flags_);
+  BuildHash(helper.annotation_count_);
+}
+
+void KernelFingerprintHelper::CalculateArgumentsFingerprint() {
+  BuildHash(ReadUInt());  // read argument count.
+
+  CalculateListOfDartTypesFingerprint();    // read list of types.
+  CalculateListOfExpressionsFingerprint();  // read positionals.
+
+  // List of named.
+  intptr_t list_length = ReadListLength();  // read list length.
+  for (intptr_t i = 0; i < list_length; ++i) {
+    CalculateStringReferenceFingerprint();  // read ith name index.
+    CalculateExpressionFingerprint();       // read ith expression.
+  }
+}
+
+void KernelFingerprintHelper::CalculateVariableDeclarationFingerprint() {
+  VariableDeclarationHelper helper(this);
+
+  helper.ReadUntilExcluding(VariableDeclarationHelper::kAnnotations);
+  CalculateListOfExpressionsFingerprint();
+  helper.SetJustRead(VariableDeclarationHelper::kAnnotations);
+
+  helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
+  // We don't need to use the helper after this point.
+  CalculateDartTypeFingerprint();
+  if (ReadTag() == kSomething) {
+    CalculateExpressionFingerprint();
+  }
+
+  BuildHash(helper.flags_);
+}
+
+void KernelFingerprintHelper::CalculateStatementListFingerprint() {
+  intptr_t list_length = ReadListLength();  // read list length.
+  for (intptr_t i = 0; i < list_length; ++i) {
+    CalculateStatementFingerprint();  // read ith expression.
+  }
+}
+
+void KernelFingerprintHelper::CalculateListOfExpressionsFingerprint() {
+  intptr_t list_length = ReadListLength();  // read list length.
+  for (intptr_t i = 0; i < list_length; ++i) {
+    CalculateExpressionFingerprint();  // read ith expression.
+  }
+}
+
+void KernelFingerprintHelper::CalculateListOfDartTypesFingerprint() {
+  intptr_t list_length = ReadListLength();  // read list length.
+  for (intptr_t i = 0; i < list_length; ++i) {
+    CalculateDartTypeFingerprint();  // read ith type.
+  }
+}
+
+void KernelFingerprintHelper::CalculateStringReferenceFingerprint() {
+  BuildHash(
+      H.DartString(ReadStringReference()).Hash());  // read ith string index.
+}
+
+void KernelFingerprintHelper::CalculateListOfStringsFingerprint() {
+  intptr_t list_length = ReadListLength();  // read list length.
+  for (intptr_t i = 0; i < list_length; ++i) {
+    CalculateStringReferenceFingerprint();  // read ith string index.
+  }
+}
+
+void KernelFingerprintHelper::CalculateListOfVariableDeclarationsFingerprint() {
+  intptr_t list_length = ReadListLength();  // read list length.
+  for (intptr_t i = 0; i < list_length; ++i) {
+    // read ith variable declaration.
+    CalculateVariableDeclarationFingerprint();
+  }
+}
+
+void KernelFingerprintHelper::CalculateTypeParameterFingerprint() {
+  TypeParameterHelper helper(this);
+
+  helper.ReadUntilExcluding(TypeParameterHelper::kAnnotations);
+  CalculateListOfExpressionsFingerprint();
+  helper.SetJustRead(TypeParameterHelper::kAnnotations);
+
+  helper.ReadUntilExcluding(TypeParameterHelper::kBound);
+  // The helper isn't needed after this point.
+  CalculateDartTypeFingerprint();
+  if (ReadTag() == kSomething) {
+    CalculateDartTypeFingerprint();
+  }
+  BuildHash(helper.flags_);
+}
+
+void KernelFingerprintHelper::CalculateTypeParametersListFingerprint() {
+  intptr_t list_length = ReadListLength();  // read list length.
+  for (intptr_t i = 0; i < list_length; ++i) {
+    CalculateTypeParameterFingerprint();
+  }
+}
+
+void KernelFingerprintHelper::CalculateCanonicalNameFingerprint() {
+  const StringIndex i = H.CanonicalNameString(ReadCanonicalNameReference());
+  BuildHash(H.DartString(i).Hash());
+}
+
+void KernelFingerprintHelper::CalculateInitializerFingerprint() {
+  Tag tag = ReadTag();
+  ReadByte();  // read isSynthetic flag.
+  switch (tag) {
+    case kInvalidInitializer:
+      return;
+    case kFieldInitializer:
+      BuildHash(H.DartFieldName(ReadCanonicalNameReference()).Hash());
+      CalculateExpressionFingerprint();  // read value.
+      return;
+    case kSuperInitializer:
+      CalculateCanonicalNameFingerprint();  // read target_reference
+      CalculateArgumentsFingerprint();      // read arguments.
+      return;
+    case kRedirectingInitializer:
+      CalculateCanonicalNameFingerprint();  // read target_reference
+      CalculateArgumentsFingerprint();      // read arguments.
+      return;
+    case kLocalInitializer:
+      CalculateVariableDeclarationFingerprint();  // read variable.
+      return;
+    case kAssertInitializer:
+      CalculateStatementFingerprint();
+      return;
+    default:
+      ReportUnexpectedTag("initializer", tag);
+      UNREACHABLE();
+  }
+}
+
+void KernelFingerprintHelper::CalculateDartTypeFingerprint() {
+  Tag tag = ReadTag();
+  BuildHash(tag);
+  switch (tag) {
+    case kInvalidType:
+    case kDynamicType:
+    case kVoidType:
+    case kBottomType:
+    case kVectorType:
+      // those contain nothing.
+      break;
+    case kInterfaceType:
+      CalculateInterfaceTypeFingerprint(false);
+      break;
+    case kSimpleInterfaceType:
+      CalculateInterfaceTypeFingerprint(true);
+      break;
+    case kFunctionType:
+      CalculateFunctionTypeFingerprint(false);
+      break;
+    case kSimpleFunctionType:
+      CalculateFunctionTypeFingerprint(true);
+      break;
+    case kTypeParameterType:
+      ReadUInt();                              // read index for parameter.
+      CalculateOptionalDartTypeFingerprint();  // read bound bound.
+      break;
+    default:
+      ReportUnexpectedTag("type", tag);
+      UNREACHABLE();
+  }
+}
+
+void KernelFingerprintHelper::CalculateOptionalDartTypeFingerprint() {
+  Tag tag = ReadTag();  // read tag.
+  BuildHash(tag);
+  if (tag == kNothing) {
+    return;
+  }
+  ASSERT(tag == kSomething);
+  CalculateDartTypeFingerprint();  // read type.
+}
+
+void KernelFingerprintHelper::CalculateInterfaceTypeFingerprint(bool simple) {
+  BuildHash(ReadUInt());  // read klass_name.
+  if (!simple) {
+    CalculateListOfDartTypesFingerprint();  // read list of types.
+  }
+}
+
+void KernelFingerprintHelper::CalculateFunctionTypeFingerprint(bool simple) {
+  if (!simple) {
+    CalculateTypeParametersListFingerprint();  // read type_parameters.
+    BuildHash(ReadUInt());                     // read required parameter count.
+    BuildHash(ReadUInt());                     // read total parameter count.
+  }
+
+  CalculateListOfDartTypesFingerprint();  // read positional_parameters types.
+
+  if (!simple) {
+    const intptr_t named_count =
+        ReadListLength();  // read named_parameters list length.
+    BuildHash(named_count);
+    for (intptr_t i = 0; i < named_count; ++i) {
+      // read string reference (i.e. named_parameters[i].name).
+      CalculateStringReferenceFingerprint();
+      CalculateDartTypeFingerprint();  // read named_parameters[i].type.
+    }
+  }
+
+  CalculateListOfStringsFingerprint();  // read positional parameter names.
+
+  if (!simple) {
+    // TODO(bkonyi): include in hash.
+    SkipCanonicalNameReference();  // read typedef reference.
+  }
+
+  CalculateDartTypeFingerprint();  // read return type.
+}
+
+void KernelFingerprintHelper::CalculateGetterNameFingerprint() {
+  const NameIndex name = ReadCanonicalNameReference();
+  if (I->strong() && !H.IsRoot(name) && (H.IsGetter(name) || H.IsField(name))) {
+    BuildHash(H.DartGetterName(name).Hash());
+  }
+}
+
+void KernelFingerprintHelper::CalculateSetterNameFingerprint() {
+  const NameIndex name = ReadCanonicalNameReference();
+  if (I->strong() && !H.IsRoot(name)) {
+    BuildHash(H.DartSetterName(name).Hash());
+  }
+}
+
+void KernelFingerprintHelper::CalculateMethodNameFingerprint() {
+  const NameIndex name =
+      ReadCanonicalNameReference();  // read interface_target_reference.
+  if (I->strong() && !H.IsRoot(name) && !H.IsField(name)) {
+    BuildHash(H.DartProcedureName(name).Hash());
+  }
+}
+
+void KernelFingerprintHelper::CalculateExpressionFingerprint() {
+  uint8_t payload = 0;
+  Tag tag = ReadTag(&payload);
+  BuildHash(tag);
+  switch (tag) {
+    case kInvalidExpression:
+      ReadPosition();
+      CalculateStringReferenceFingerprint();
+      return;
+    case kVariableGet:
+      ReadPosition();                          // read position.
+      ReadUInt();                              // read kernel position.
+      ReadUInt();                              // read relative variable index.
+      CalculateOptionalDartTypeFingerprint();  // read promoted type.
+      return;
+    case kSpecializedVariableGet:
+      ReadPosition();  // read position.
+      ReadUInt();      // read kernel position.
+      return;
+    case kVariableSet:
+      ReadPosition();                    // read position.
+      ReadUInt();                        // read kernel position.
+      ReadUInt();                        // read relative variable index.
+      CalculateExpressionFingerprint();  // read expression.
+      return;
+    case kSpecializedVariableSet:
+      ReadPosition();                    // read position.
+      ReadUInt();                        // read kernel position.
+      CalculateExpressionFingerprint();  // read expression.
+      return;
+    case kPropertyGet:
+      ReadPosition();                            // read position.
+      CalculateExpressionFingerprint();          // read receiver.
+      BuildHash(ReadNameAsGetterName().Hash());  // read name.
+      CalculateGetterNameFingerprint();  // read interface_target_reference.
+      return;
+    case kPropertySet:
+      ReadPosition();                            // read position.
+      CalculateExpressionFingerprint();          // read receiver.
+      BuildHash(ReadNameAsSetterName().Hash());  // read name.
+      CalculateExpressionFingerprint();          // read value.
+      CalculateSetterNameFingerprint();  // read interface_target_reference.
+      return;
+    case kSuperPropertyGet:
+      ReadPosition();                            // read position.
+      BuildHash(ReadNameAsGetterName().Hash());  // read name.
+      CalculateGetterNameFingerprint();  // read interface_target_reference.
+      return;
+    case kSuperPropertySet:
+      ReadPosition();                            // read position.
+      BuildHash(ReadNameAsSetterName().Hash());  // read name.
+      CalculateExpressionFingerprint();          // read value.
+      CalculateSetterNameFingerprint();  // read interface_target_reference.
+      return;
+    case kDirectPropertyGet:
+      ReadPosition();                       // read position.
+      CalculateExpressionFingerprint();     // read receiver.
+      CalculateCanonicalNameFingerprint();  // read target_reference.
+      return;
+    case kDirectPropertySet:
+      ReadPosition();                       // read position.
+      CalculateExpressionFingerprint();     // read receiver.
+      CalculateCanonicalNameFingerprint();  // read target_reference.
+      CalculateExpressionFingerprint();     // read value·
+      return;
+    case kStaticGet:
+      ReadPosition();                       // read position.
+      CalculateCanonicalNameFingerprint();  // read target_reference.
+      return;
+    case kStaticSet:
+      ReadPosition();                       // read position.
+      CalculateCanonicalNameFingerprint();  // read target_reference.
+      CalculateExpressionFingerprint();     // read expression.
+      return;
+    case kMethodInvocation:
+      ReadPosition();                            // read position.
+      CalculateExpressionFingerprint();          // read receiver.
+      BuildHash(ReadNameAsMethodName().Hash());  // read name.
+      CalculateArgumentsFingerprint();           // read arguments.
+      CalculateMethodNameFingerprint();  // read interface_target_reference.
+      return;
+    case kSuperMethodInvocation:
+      ReadPosition();                            // read position.
+      BuildHash(ReadNameAsMethodName().Hash());  // read name.
+      CalculateArgumentsFingerprint();           // read arguments.
+      CalculateCanonicalNameFingerprint();       // read target_reference.
+      return;
+    case kDirectMethodInvocation:
+      ReadPosition();                       // read position.
+      CalculateExpressionFingerprint();     // read receiver.
+      CalculateCanonicalNameFingerprint();  // read target_reference.
+      CalculateArgumentsFingerprint();      // read arguments.
+      return;
+    case kStaticInvocation:
+    case kConstStaticInvocation:
+      ReadPosition();                       // read position.
+      CalculateCanonicalNameFingerprint();  // read target_reference.
+      CalculateArgumentsFingerprint();      // read arguments.
+      return;
+    case kConstructorInvocation:
+    case kConstConstructorInvocation:
+      ReadPosition();                       // read position.
+      CalculateCanonicalNameFingerprint();  // read target_reference.
+      CalculateArgumentsFingerprint();      // read arguments.
+      return;
+    case kNot:
+      CalculateExpressionFingerprint();  // read expression.
+      return;
+    case kLogicalExpression:
+      CalculateExpressionFingerprint();  // read left.
+      SkipBytes(1);                      // read operator.
+      CalculateExpressionFingerprint();  // read right.
+      return;
+    case kConditionalExpression:
+      CalculateExpressionFingerprint();        // read condition.
+      CalculateExpressionFingerprint();        // read then.
+      CalculateExpressionFingerprint();        // read otherwise.
+      CalculateOptionalDartTypeFingerprint();  // read unused static type.
+      return;
+    case kStringConcatenation:
+      ReadPosition();                           // read position.
+      CalculateListOfExpressionsFingerprint();  // read list of expressions.
+      return;
+    case kIsExpression:
+      ReadPosition();                    // read position.
+      CalculateExpressionFingerprint();  // read operand.
+      CalculateDartTypeFingerprint();    // read type.
+      return;
+    case kAsExpression:
+      ReadPosition();                    // read position.
+      BuildHash(ReadFlags());            // read flags.
+      CalculateExpressionFingerprint();  // read operand.
+      CalculateDartTypeFingerprint();    // read type.
+      return;
+    case kSymbolLiteral:
+      CalculateStringReferenceFingerprint();  // read index into string table.
+      return;
+    case kTypeLiteral:
+      CalculateDartTypeFingerprint();  // read type.
+      return;
+    case kThisExpression:
+      return;
+    case kRethrow:
+      ReadPosition();  // read position.
+      return;
+    case kThrow:
+      ReadPosition();                    // read position.
+      CalculateExpressionFingerprint();  // read expression.
+      return;
+    case kListLiteral:
+    case kConstListLiteral:
+      ReadPosition();                           // read position.
+      CalculateDartTypeFingerprint();           // read type.
+      CalculateListOfExpressionsFingerprint();  // read list of expressions.
+      return;
+    case kMapLiteral:
+    case kConstMapLiteral: {
+      ReadPosition();                           // read position.
+      CalculateDartTypeFingerprint();           // read type.
+      CalculateDartTypeFingerprint();           // read value type.
+      intptr_t list_length = ReadListLength();  // read list length.
+      for (intptr_t i = 0; i < list_length; ++i) {
+        CalculateExpressionFingerprint();  // read ith key.
+        CalculateExpressionFingerprint();  // read ith value.
+      }
+      return;
+    }
+    case kFunctionExpression:
+      ReadPosition();                      // read position.
+      CalculateFunctionNodeFingerprint();  // read function node.
+      return;
+    case kLet:
+      CalculateVariableDeclarationFingerprint();  // read variable declaration.
+      CalculateExpressionFingerprint();           // read expression.
+      return;
+    case kInstantiation:
+      CalculateExpressionFingerprint();       // read expression.
+      CalculateListOfDartTypesFingerprint();  // read type arguments.
+      return;
+    case kVectorCreation:
+      BuildHash(ReadUInt());  // read value.
+      return;
+    case kVectorGet:
+      CalculateExpressionFingerprint();  // read vector expression.
+      BuildHash(ReadUInt());             // read index.
+      return;
+    case kVectorSet:
+      CalculateExpressionFingerprint();  // read vector expression.
+      BuildHash(ReadUInt());             // read index.
+      CalculateExpressionFingerprint();  // read value.
+      return;
+    case kVectorCopy:
+      CalculateExpressionFingerprint();  // read vector expression.
+      return;
+    case kClosureCreation:
+      // read top-level function reference.
+      CalculateCanonicalNameFingerprint();
+      CalculateExpressionFingerprint();       // read context vector.
+      CalculateDartTypeFingerprint();         // read function type.
+      CalculateListOfDartTypesFingerprint();  // read type arguments.
+      return;
+    case kBigIntLiteral:
+      CalculateStringReferenceFingerprint();  // read string reference.
+      return;
+    case kStringLiteral:
+      CalculateStringReferenceFingerprint();  // read string reference.
+      return;
+    case kSpecializedIntLiteral:
+      return;
+    case kNegativeIntLiteral:
+      BuildHash(ReadUInt());  // read value.
+      return;
+    case kPositiveIntLiteral:
+      BuildHash(ReadUInt());  // read value.
+      return;
+    case kDoubleLiteral:
+      CalculateStringReferenceFingerprint();  // read index into string table.
+      return;
+    case kTrueLiteral:
+      return;
+    case kFalseLiteral:
+      return;
+    case kNullLiteral:
+      return;
+    case kConstantExpression:
+      SkipConstantReference();
+      return;
+    case kLoadLibrary:
+    case kCheckLibraryIsLoaded:
+      ReadUInt();  // skip library index
+      return;
+    default:
+      ReportUnexpectedTag("expression", tag);
+      UNREACHABLE();
+  }
+}
+
+void KernelFingerprintHelper::CalculateStatementFingerprint() {
+  Tag tag = ReadTag();  // read tag.
+  BuildHash(tag);
+  switch (tag) {
+    case kExpressionStatement:
+      CalculateExpressionFingerprint();  // read expression.
+      return;
+    case kBlock:
+      CalculateStatementListFingerprint();
+      return;
+    case kEmptyStatement:
+      return;
+    case kAssertBlock:
+      CalculateStatementListFingerprint();
+      return;
+    case kAssertStatement:
+      CalculateExpressionFingerprint();  // Read condition.
+      ReadPosition();                    // read condition start offset.
+      ReadPosition();                    // read condition end offset.
+      if (ReadTag() == kSomething) {
+        CalculateExpressionFingerprint();  // read (rest of) message.
+      }
+      return;
+    case kLabeledStatement:
+      CalculateStatementFingerprint();  // read body.
+      return;
+    case kBreakStatement:
+      ReadPosition();  // read position.
+      ReadUInt();      // read target_index.
+      return;
+    case kWhileStatement:
+      ReadPosition();                    // read position.
+      CalculateExpressionFingerprint();  // read condition.
+      CalculateStatementFingerprint();   // read body.
+      return;
+    case kDoStatement:
+      ReadPosition();                    // read position.
+      CalculateStatementFingerprint();   // read body.
+      CalculateExpressionFingerprint();  // read condition.
+      return;
+    case kForStatement: {
+      ReadPosition();                                    // read position.
+      CalculateListOfVariableDeclarationsFingerprint();  // read variables.
+      Tag tag = ReadTag();  // Read first part of condition.
+      if (tag == kSomething) {
+        CalculateExpressionFingerprint();  // read rest of condition.
+      }
+      CalculateListOfExpressionsFingerprint();  // read updates.
+      CalculateStatementFingerprint();          // read body.
+      return;
+    }
+    case kForInStatement:
+    case kAsyncForInStatement:
+      ReadPosition();                             // read position.
+      ReadPosition();                             // read body position.
+      CalculateVariableDeclarationFingerprint();  // read variable.
+      CalculateExpressionFingerprint();           // read iterable.
+      CalculateStatementFingerprint();            // read body.
+      return;
+    case kSwitchStatement: {
+      ReadPosition();                     // read position.
+      CalculateExpressionFingerprint();   // read condition.
+      int case_count = ReadListLength();  // read number of cases.
+      for (intptr_t i = 0; i < case_count; ++i) {
+        int expression_count = ReadListLength();  // read number of expressions.
+        for (intptr_t j = 0; j < expression_count; ++j) {
+          ReadPosition();                    // read jth position.
+          CalculateExpressionFingerprint();  // read jth expression.
+        }
+        BuildHash(ReadBool());            // read is_default.
+        CalculateStatementFingerprint();  // read body.
+      }
+      return;
+    }
+    case kContinueSwitchStatement:
+      ReadPosition();  // read position.
+      ReadUInt();      // read target_index.
+      return;
+    case kIfStatement:
+      ReadPosition();                    // read position.
+      CalculateExpressionFingerprint();  // read condition.
+      CalculateStatementFingerprint();   // read then.
+      CalculateStatementFingerprint();   // read otherwise.
+      return;
+    case kReturnStatement: {
+      ReadPosition();       // read position
+      Tag tag = ReadTag();  // read (first part of) expression.
+      BuildHash(tag);
+      if (tag == kSomething) {
+        CalculateExpressionFingerprint();  // read (rest of) expression.
+      }
+      return;
+    }
+    case kTryCatch: {
+      CalculateStatementFingerprint();  // read body.
+      BuildHash(ReadBool());            // read any_catch_needs_stack_trace.
+      intptr_t catch_count = ReadListLength();  // read number of catches.
+      for (intptr_t i = 0; i < catch_count; ++i) {
+        ReadPosition();                  // read position.
+        CalculateDartTypeFingerprint();  // read guard.
+        tag = ReadTag();                 // read first part of exception.
+        BuildHash(tag);
+        if (tag == kSomething) {
+          CalculateVariableDeclarationFingerprint();  // read exception.
+        }
+        tag = ReadTag();  // read first part of stack trace.
+        BuildHash(tag);
+        if (tag == kSomething) {
+          CalculateVariableDeclarationFingerprint();  // read stack trace.
+        }
+        CalculateStatementFingerprint();  // read body.
+      }
+      return;
+    }
+    case kTryFinally:
+      CalculateStatementFingerprint();  // read body.
+      CalculateStatementFingerprint();  // read finalizer.
+      return;
+    case kYieldStatement: {
+      ReadPosition();                    // read position.
+      BuildHash(ReadByte());             // read flags.
+      CalculateExpressionFingerprint();  // read expression.
+      return;
+    }
+    case kVariableDeclaration:
+      CalculateVariableDeclarationFingerprint();  // read variable declaration.
+      return;
+    case kFunctionDeclaration:
+      ReadPosition();                             // read position.
+      CalculateVariableDeclarationFingerprint();  // read variable.
+      CalculateFunctionNodeFingerprint();         // read function node.
+      return;
+    default:
+      ReportUnexpectedTag("statement", tag);
+      UNREACHABLE();
+  }
+}
+
+uint32_t KernelFingerprintHelper::CalculateFieldFingerprint() {
+  hash_ = 0;
+  FieldHelper field_helper(this);
+
+  field_helper.ReadUntilExcluding(FieldHelper::kName);
+  const String& name = ReadNameAsFieldName();  // read name.
+  field_helper.SetJustRead(FieldHelper::kName);
+
+  field_helper.ReadUntilExcluding(FieldHelper::kType);
+  CalculateDartTypeFingerprint();  // read type.
+  field_helper.SetJustRead(FieldHelper::kType);
+
+  if (ReadTag() == kSomething) {
+    if (PeekTag() == kFunctionExpression) {
+      AlternativeReadingScope alt(&reader_);
+      CalculateExpressionFingerprint();
+    }
+    SkipExpression();
+  }
+
+  BuildHash(name.Hash());
+  BuildHash((field_helper.flags_ << 8) | field_helper.secondary_flags_);
+  BuildHash(field_helper.annotation_count_);
+  return hash_;
+}
+
+void KernelFingerprintHelper::CalculateFunctionNodeFingerprint() {
+  FunctionNodeHelper function_node_helper(this);
+
+  function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
+  CalculateTypeParametersListFingerprint();
+  function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters);
+
+  function_node_helper.ReadUntilExcluding(
+      FunctionNodeHelper::kPositionalParameters);
+  CalculateListOfVariableDeclarationsFingerprint();  // read positionals
+  CalculateListOfVariableDeclarationsFingerprint();  // read named
+  CalculateDartTypeFingerprint();                    // read return type.
+
+  if (ReadTag() == kSomething) {
+    CalculateStatementFingerprint();  // Read body.
+  }
+  BuildHash(function_node_helper.total_parameter_count_);
+  BuildHash(function_node_helper.required_parameter_count_);
+}
+
+uint32_t KernelFingerprintHelper::CalculateFunctionFingerprint() {
+  hash_ = 0;
+  Tag tag = PeekTag();
+  if (tag == kField) {
+    return CalculateFieldFingerprint();
+  } else if (tag == kConstructor) {
+    CalculateConstructorFingerprint();
+    return hash_;
+  }
+  ProcedureHelper procedure_helper(this);
+  procedure_helper.ReadUntilExcluding(ProcedureHelper::kName);
+  const String& name = ReadNameAsMethodName();  // Read name.
+  procedure_helper.SetJustRead(ProcedureHelper::kName);
+
+  procedure_helper.ReadUntilExcluding(ProcedureHelper::kFunction);
+  if (ReadTag() == kSomething) {
+    CalculateFunctionNodeFingerprint();
+  }
+
+  BuildHash(procedure_helper.kind_);
+  BuildHash(procedure_helper.flags_);
+  BuildHash(procedure_helper.flags2_);
+  BuildHash(procedure_helper.annotation_count_);
+  BuildHash(name.Hash());
+  return hash_;
+}
+
 void StreamingFlowGraphBuilder::ReadUntilFunctionNode(
     ParsedFunction* parsed_function) {
   const Tag tag = PeekTag();
@@ -4229,63 +4929,10 @@
   body +=
       flow_graph_builder_->CheckStackOverflowInPrologue(function.token_pos());
 
-  // Forwarding the type parameters is complicated by our approach to
-  // implementing the partial tearoff instantiation.
-  //
-  // When a tearoff is partially applied to a set of type arguments, the type
-  // arguments are saved in the closure's "function_type_arguments" field. The
-  // partial type application operator is guaranteed to provide arguments for
-  // all of a generic tearoff's type parameters, so we will only have to forward
-  // type arguments from the caller or from the closure object. In other words,
-  // if there are type arguments saved on the tearoff, we must throw
-  // NoSuchMethod.
   intptr_t type_args_len = 0;
   if (I->reify_generic_functions() && function.IsGeneric()) {
+    type_args_len = function.NumTypeParameters();
     ASSERT(parsed_function()->function_type_arguments() != NULL);
-    type_args_len = target.NumTypeParameters();
-
-    Fragment copy_type_args;
-
-    LocalVariable* closure =
-        parsed_function()->node_sequence()->scope()->VariableAt(0);
-    copy_type_args += LoadLocal(closure);
-    copy_type_args += LoadField(Closure::function_type_arguments_offset());
-
-    TargetEntryInstr *is_instantiated, *is_not_instantiated;
-    copy_type_args +=
-        BranchIfNull(&is_not_instantiated, &is_instantiated, /*negate=*/false);
-    JoinEntryInstr* join = BuildJoinEntry();
-
-    // We found type arguments saved on the tearoff to be provided to the
-    // function.
-
-    Fragment copy_instantiated_args(is_instantiated);
-
-    copy_instantiated_args +=
-        LoadLocal(parsed_function()->function_type_arguments());
-
-    TargetEntryInstr *no_type_args, *passed_type_args;
-    copy_instantiated_args +=
-        BranchIfNull(&no_type_args, &passed_type_args, /*negate=*/false);
-
-    Fragment use_instantiated_args(no_type_args);
-    use_instantiated_args += LoadLocal(closure);
-    use_instantiated_args +=
-        LoadField(Closure::function_type_arguments_offset());
-    use_instantiated_args += StoreLocal(
-        TokenPosition::kNoSource, parsed_function()->function_type_arguments());
-    use_instantiated_args += Drop();
-    use_instantiated_args += Goto(join);
-
-    Fragment goto_nsm(passed_type_args);
-    goto_nsm += Goto(flow_graph_builder_->BuildThrowNoSuchMethod());
-
-    // The tearoff was not partially applied, so we forward type arguments from
-    // the caller.
-    Fragment forward_caller_args(is_not_instantiated);
-    forward_caller_args += Goto(join);
-
-    body += Fragment(copy_type_args.entry, join);
     body += LoadLocal(parsed_function()->function_type_arguments());
     body += PushArgument();
   }
@@ -4766,55 +5413,58 @@
 
   Fragment body;
 
-  if (dart_function.IsConvertedClosureFunction()) {
-    LocalVariable* closure = new (Z) LocalVariable(
+  LocalVariable* closure = NULL;
+  if (dart_function.IsClosureFunction()) {
+    closure = parsed_function()->node_sequence()->scope()->VariableAt(0);
+  } else if (dart_function.IsConvertedClosureFunction()) {
+    closure = new (Z) LocalVariable(
         TokenPosition::kNoSource, TokenPosition::kNoSource,
         Symbols::TempParam(), AbstractType::ZoneHandle(Z, Type::DynamicType()));
     closure->set_index(parsed_function()->first_parameter_index());
     closure->set_is_captured_parameter(true);
+  }
+
+  if ((dart_function.IsClosureFunction() ||
+       dart_function.IsConvertedClosureFunction()) &&
+      dart_function.NumParentTypeParameters() > 0 &&
+      I->reify_generic_functions()) {
+    LocalVariable* fn_type_args = parsed_function()->function_type_arguments();
+    ASSERT(fn_type_args != NULL && closure != NULL);
+
+    if (dart_function.IsGeneric()) {
+      body += LoadLocal(fn_type_args);
+      body += PushArgument();
+      body += LoadLocal(closure);
+      body += LoadField(Closure::function_type_arguments_offset());
+      body += PushArgument();
+      body += IntConstant(dart_function.NumTypeParameters() +
+                          dart_function.NumParentTypeParameters());
+      body += PushArgument();
+
+      const Library& dart_internal =
+          Library::Handle(Z, Library::InternalLibrary());
+      const Function& prepend_function =
+          Function::ZoneHandle(Z, dart_internal.LookupFunctionAllowPrivate(
+                                      Symbols::PrependTypeArguments()));
+      ASSERT(!prepend_function.IsNull());
+
+      body += StaticCall(TokenPosition::kNoSource, prepend_function, 3,
+                         ICData::kStatic);
+      body += StoreLocal(TokenPosition::kNoSource, fn_type_args);
+      body += Drop();
+    } else {
+      body += LoadLocal(closure);
+      body += LoadField(Closure::function_type_arguments_offset());
+      body += StoreLocal(TokenPosition::kNoSource, fn_type_args);
+      body += Drop();
+    }
+  }
+
+  if (dart_function.IsConvertedClosureFunction()) {
     body += LoadLocal(closure);
     body += LoadField(Closure::context_offset());
     LocalVariable* context = closure;
     body += StoreLocal(TokenPosition::kNoSource, context);
-
-    // TODO(30455): Kernel generic methods undone. When generic closures are
-    // supported, the type arguments passed by the caller will actually need to
-    // be used here.
-    if (dart_function.IsGeneric() && I->reify_generic_functions()) {
-      LocalVariable* type_args_slot =
-          parsed_function()->function_type_arguments();
-      ASSERT(type_args_slot != NULL);
-      body += LoadField(Context::variable_offset(0));
-      body += StoreLocal(TokenPosition::kNoSource, type_args_slot);
-    }
-    body += Drop();
-  } else if (dart_function.IsClosureFunction() && dart_function.IsGeneric() &&
-             dart_function.NumParentTypeParameters() > 0 &&
-             I->reify_generic_functions()) {
-    LocalVariable* closure =
-        parsed_function()->node_sequence()->scope()->VariableAt(0);
-    LocalVariable* fn_type_args = parsed_function()->function_type_arguments();
-    ASSERT(fn_type_args != NULL && closure != NULL);
-
-    body += LoadLocal(fn_type_args);
-    body += PushArgument();
-    body += LoadLocal(closure);
-    body += LoadField(Closure::function_type_arguments_offset());
-    body += PushArgument();
-    body += IntConstant(dart_function.NumTypeParameters() +
-                        dart_function.NumParentTypeParameters());
-    body += PushArgument();
-
-    const Library& dart_internal =
-        Library::Handle(Z, Library::InternalLibrary());
-    const Function& prepend_function =
-        Function::ZoneHandle(Z, dart_internal.LookupFunctionAllowPrivate(
-                                    Symbols::PrependTypeArguments()));
-    ASSERT(!prepend_function.IsNull());
-
-    body += StaticCall(TokenPosition::kNoSource, prepend_function, 3,
-                       ICData::kStatic);
-    body += StoreLocal(TokenPosition::kNoSource, fn_type_args);
     body += Drop();
   }
 
@@ -5344,57 +5994,57 @@
   return Fragment();
 }
 
-intptr_t StreamingFlowGraphBuilder::ReaderOffset() {
+intptr_t KernelReaderHelper::ReaderOffset() const {
   return reader_.offset();
 }
 
-void StreamingFlowGraphBuilder::SetOffset(intptr_t offset) {
+void KernelReaderHelper::SetOffset(intptr_t offset) {
   reader_.set_offset(offset);
 }
 
-void StreamingFlowGraphBuilder::SkipBytes(intptr_t bytes) {
+void KernelReaderHelper::SkipBytes(intptr_t bytes) {
   reader_.set_offset(ReaderOffset() + bytes);
 }
 
-bool StreamingFlowGraphBuilder::ReadBool() {
+bool KernelReaderHelper::ReadBool() {
   return reader_.ReadBool();
 }
 
-uint8_t StreamingFlowGraphBuilder::ReadByte() {
+uint8_t KernelReaderHelper::ReadByte() {
   return reader_.ReadByte();
 }
 
-uint32_t StreamingFlowGraphBuilder::ReadUInt() {
+uint32_t KernelReaderHelper::ReadUInt() {
   return reader_.ReadUInt();
 }
 
-uint32_t StreamingFlowGraphBuilder::ReadUInt32() {
+uint32_t KernelReaderHelper::ReadUInt32() {
   return reader_.ReadUInt32();
 }
 
-uint32_t StreamingFlowGraphBuilder::PeekUInt() {
+uint32_t KernelReaderHelper::PeekUInt() {
   AlternativeReadingScope alt(&reader_);
   return reader_.ReadUInt();
 }
 
-uint32_t StreamingFlowGraphBuilder::PeekListLength() {
+uint32_t KernelReaderHelper::PeekListLength() {
   AlternativeReadingScope alt(&reader_);
   return reader_.ReadListLength();
 }
 
-intptr_t StreamingFlowGraphBuilder::ReadListLength() {
+intptr_t KernelReaderHelper::ReadListLength() {
   return reader_.ReadListLength();
 }
 
-StringIndex StreamingFlowGraphBuilder::ReadStringReference() {
+StringIndex KernelReaderHelper::ReadStringReference() {
   return StringIndex(ReadUInt());
 }
 
-NameIndex StreamingFlowGraphBuilder::ReadCanonicalNameReference() {
+NameIndex KernelReaderHelper::ReadCanonicalNameReference() {
   return reader_.ReadCanonicalNameReference();
 }
 
-StringIndex StreamingFlowGraphBuilder::ReadNameAsStringIndex() {
+StringIndex KernelReaderHelper::ReadNameAsStringIndex() {
   StringIndex name_index = ReadStringReference();  // read name index.
   if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
     ReadUInt();  // read library index.
@@ -5402,7 +6052,7 @@
   return name_index;
 }
 
-const String& StreamingFlowGraphBuilder::ReadNameAsMethodName() {
+const String& KernelReaderHelper::ReadNameAsMethodName() {
   StringIndex name_index = ReadStringReference();  // read name index.
   if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
     NameIndex library_reference =
@@ -5413,7 +6063,7 @@
   }
 }
 
-const String& StreamingFlowGraphBuilder::ReadNameAsSetterName() {
+const String& KernelReaderHelper::ReadNameAsSetterName() {
   StringIndex name_index = ReadStringReference();  // read name index.
   if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
     NameIndex library_reference =
@@ -5424,7 +6074,7 @@
   }
 }
 
-const String& StreamingFlowGraphBuilder::ReadNameAsGetterName() {
+const String& KernelReaderHelper::ReadNameAsGetterName() {
   StringIndex name_index = ReadStringReference();  // read name index.
   if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
     NameIndex library_reference =
@@ -5435,7 +6085,7 @@
   }
 }
 
-const String& StreamingFlowGraphBuilder::ReadNameAsFieldName() {
+const String& KernelReaderHelper::ReadNameAsFieldName() {
   StringIndex name_index = ReadStringReference();  // read name index.
   if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
     NameIndex library_reference =
@@ -5446,34 +6096,41 @@
   }
 }
 
-void StreamingFlowGraphBuilder::SkipFlags() {
+void KernelReaderHelper::SkipFlags() {
   ReadFlags();
 }
 
-void StreamingFlowGraphBuilder::SkipStringReference() {
+void KernelReaderHelper::SkipStringReference() {
   ReadUInt();
 }
 
-void StreamingFlowGraphBuilder::SkipConstantReference() {
+void KernelReaderHelper::SkipConstantReference() {
   ReadUInt();
 }
 
-void StreamingFlowGraphBuilder::SkipCanonicalNameReference() {
+void KernelReaderHelper::SkipCanonicalNameReference() {
   ReadUInt();
 }
 
+void KernelReaderHelper::ReportUnexpectedTag(const char* variant, Tag tag) {
+  H.ReportError(script_, TokenPosition::kNoSource,
+                "Unexpected tag %d (%s) in ?, expected %s", tag,
+                Reader::TagName(tag), variant);
+}
+
 void StreamingFlowGraphBuilder::ReportUnexpectedTag(const char* variant,
                                                     Tag tag) {
-  H.ReportError(script_, TokenPosition::kNoSource,
-                "Unexpected tag %d (%s) in %s, expected %s", tag,
-                Reader::TagName(tag),
-                flow_graph_builder_ != NULL && parsed_function() != NULL
-                    ? parsed_function()->function().ToQualifiedCString()
-                    : "?",
-                variant);
+  if ((flow_graph_builder_ == NULL) || (parsed_function() == NULL)) {
+    KernelReaderHelper::ReportUnexpectedTag(variant, tag);
+  } else {
+    H.ReportError(script_, TokenPosition::kNoSource,
+                  "Unexpected tag %d (%s) in %s, expected %s", tag,
+                  Reader::TagName(tag),
+                  parsed_function()->function().ToQualifiedCString(), variant);
+  }
 }
 
-void StreamingFlowGraphBuilder::SkipDartType() {
+void KernelReaderHelper::SkipDartType() {
   Tag tag = ReadTag();
   switch (tag) {
     case kInvalidType:
@@ -5505,7 +6162,7 @@
   }
 }
 
-void StreamingFlowGraphBuilder::SkipOptionalDartType() {
+void KernelReaderHelper::SkipOptionalDartType() {
   Tag tag = ReadTag();  // read tag.
   if (tag == kNothing) {
     return;
@@ -5515,14 +6172,14 @@
   SkipDartType();  // read type.
 }
 
-void StreamingFlowGraphBuilder::SkipInterfaceType(bool simple) {
+void KernelReaderHelper::SkipInterfaceType(bool simple) {
   ReadUInt();  // read klass_name.
   if (!simple) {
     SkipListOfDartTypes();  // read list of types.
   }
 }
 
-void StreamingFlowGraphBuilder::SkipFunctionType(bool simple) {
+void KernelReaderHelper::SkipFunctionType(bool simple) {
   if (!simple) {
     SkipTypeParametersList();  // read type_parameters.
     ReadUInt();                // read required parameter count.
@@ -5550,42 +6207,42 @@
   SkipDartType();  // read return type.
 }
 
-void StreamingFlowGraphBuilder::SkipStatementList() {
+void KernelReaderHelper::SkipStatementList() {
   intptr_t list_length = ReadListLength();  // read list length.
   for (intptr_t i = 0; i < list_length; ++i) {
     SkipStatement();  // read ith expression.
   }
 }
 
-void StreamingFlowGraphBuilder::SkipListOfExpressions() {
+void KernelReaderHelper::SkipListOfExpressions() {
   intptr_t list_length = ReadListLength();  // read list length.
   for (intptr_t i = 0; i < list_length; ++i) {
     SkipExpression();  // read ith expression.
   }
 }
 
-void StreamingFlowGraphBuilder::SkipListOfDartTypes() {
+void KernelReaderHelper::SkipListOfDartTypes() {
   intptr_t list_length = ReadListLength();  // read list length.
   for (intptr_t i = 0; i < list_length; ++i) {
     SkipDartType();  // read ith type.
   }
 }
 
-void StreamingFlowGraphBuilder::SkipListOfStrings() {
+void KernelReaderHelper::SkipListOfStrings() {
   intptr_t list_length = ReadListLength();  // read list length.
   for (intptr_t i = 0; i < list_length; ++i) {
     SkipStringReference();  // read ith string index.
   }
 }
 
-void StreamingFlowGraphBuilder::SkipListOfVariableDeclarations() {
+void KernelReaderHelper::SkipListOfVariableDeclarations() {
   intptr_t list_length = ReadListLength();  // read list length.
   for (intptr_t i = 0; i < list_length; ++i) {
     SkipVariableDeclaration();  // read ith variable declaration.
   }
 }
 
-void StreamingFlowGraphBuilder::SkipTypeParametersList() {
+void KernelReaderHelper::SkipTypeParametersList() {
   intptr_t list_length = ReadListLength();  // read list length.
   for (intptr_t i = 0; i < list_length; ++i) {
     TypeParameterHelper helper(this);
@@ -5593,7 +6250,7 @@
   }
 }
 
-void StreamingFlowGraphBuilder::SkipInitializer() {
+void KernelReaderHelper::SkipInitializer() {
   Tag tag = ReadTag();
   ReadByte();  // read isSynthetic flag.
   switch (tag) {
@@ -5623,7 +6280,7 @@
   }
 }
 
-void StreamingFlowGraphBuilder::SkipExpression() {
+void KernelReaderHelper::SkipExpression() {
   uint8_t payload = 0;
   Tag tag = ReadTag(&payload);
   switch (tag) {
@@ -5858,7 +6515,7 @@
   }
 }
 
-void StreamingFlowGraphBuilder::SkipStatement() {
+void KernelReaderHelper::SkipStatement() {
   Tag tag = ReadTag();  // read tag.
   switch (tag) {
     case kExpressionStatement:
@@ -5974,7 +6631,7 @@
       return;
     case kYieldStatement: {
       TokenPosition position = ReadPosition();  // read position.
-      record_yield_position(position);
+      RecordYieldPosition(position);
       ReadByte();        // read flags.
       SkipExpression();  // read expression.
       return;
@@ -5993,19 +6650,19 @@
   }
 }
 
-void StreamingFlowGraphBuilder::SkipFunctionNode() {
+void KernelReaderHelper::SkipFunctionNode() {
   FunctionNodeHelper function_node_helper(this);
   function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
 }
 
-void StreamingFlowGraphBuilder::SkipName() {
+void KernelReaderHelper::SkipName() {
   StringIndex name_index = ReadStringReference();  // read name index.
   if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
     SkipCanonicalNameReference();  // read library index.
   }
 }
 
-void StreamingFlowGraphBuilder::SkipArguments() {
+void KernelReaderHelper::SkipArguments() {
   ReadUInt();  // read argument count.
 
   SkipListOfDartTypes();    // read list of types.
@@ -6019,12 +6676,12 @@
   }
 }
 
-void StreamingFlowGraphBuilder::SkipVariableDeclaration() {
+void KernelReaderHelper::SkipVariableDeclaration() {
   VariableDeclarationHelper helper(this);
   helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);
 }
 
-void StreamingFlowGraphBuilder::SkipLibraryCombinator() {
+void KernelReaderHelper::SkipLibraryCombinator() {
   ReadBool();                        // read is_show.
   intptr_t name_count = ReadUInt();  // read list length.
   for (intptr_t j = 0; j < name_count; ++j) {
@@ -6032,7 +6689,7 @@
   }
 }
 
-void StreamingFlowGraphBuilder::SkipLibraryDependency() {
+void KernelReaderHelper::SkipLibraryDependency() {
   ReadPosition();  // read file offset.
   ReadFlags();
   SkipListOfExpressions();  // Annotations.
@@ -6044,12 +6701,12 @@
   }
 }
 
-void StreamingFlowGraphBuilder::SkipLibraryPart() {
+void KernelReaderHelper::SkipLibraryPart() {
   SkipListOfExpressions();  // Read annotations.
   SkipStringReference();    // Read part URI index.
 }
 
-void StreamingFlowGraphBuilder::SkipLibraryTypedef() {
+void KernelReaderHelper::SkipLibraryTypedef() {
   SkipCanonicalNameReference();  // read canonical name.
   ReadUInt();                    // read source_uri_index.
   ReadPosition();                // read position.
@@ -6059,33 +6716,33 @@
   SkipDartType();                // read type.
 }
 
-TokenPosition StreamingFlowGraphBuilder::ReadPosition(bool record) {
+TokenPosition KernelReaderHelper::ReadPosition(bool record) {
   TokenPosition position = reader_.ReadPosition();
   if (record) {
-    record_token_position(position);
+    RecordTokenPosition(position);
   }
   return position;
 }
 
-void StreamingFlowGraphBuilder::record_token_position(TokenPosition position) {
+void StreamingFlowGraphBuilder::RecordTokenPosition(TokenPosition position) {
   if (record_for_script_id_ == current_script_id_ &&
       record_token_positions_into_ != NULL && position.IsReal()) {
     record_token_positions_into_->Add(position.value());
   }
 }
 
-void StreamingFlowGraphBuilder::record_yield_position(TokenPosition position) {
+void StreamingFlowGraphBuilder::RecordYieldPosition(TokenPosition position) {
   if (record_for_script_id_ == current_script_id_ &&
       record_yield_positions_into_ != NULL && position.IsReal()) {
     record_yield_positions_into_->Add(position.value());
   }
 }
 
-Tag StreamingFlowGraphBuilder::ReadTag(uint8_t* payload) {
+Tag KernelReaderHelper::ReadTag(uint8_t* payload) {
   return reader_.ReadTag(payload);
 }
 
-Tag StreamingFlowGraphBuilder::PeekTag(uint8_t* payload) {
+Tag KernelReaderHelper::PeekTag(uint8_t* payload) {
   return reader_.PeekTag(payload);
 }
 
@@ -8328,9 +8985,9 @@
     TokenPosition* position) {
   if (position != NULL) *position = TokenPosition::kNoSource;
 
-  Double& constant =
-      Double::ZoneHandle(Z, Double::New(H.DartString(ReadStringReference()),
-                                        Heap::kOld));  // read string reference.
+  Double& constant = Double::ZoneHandle(
+      Z, Double::NewCanonical(
+             H.DartString(ReadStringReference())));  // read string reference.
   return Constant(constant);
 }
 
@@ -8423,7 +9080,15 @@
       ReadCanonicalNameReference();  // read function reference.
   Function& function = Function::ZoneHandle(
       Z, H.LookupStaticMethodByKernelProcedure(function_reference));
-  function = function.ConvertedClosureFunction();
+
+  intptr_t num_type_parameters;
+  {
+    AlternativeReadingScope _(&reader_);
+    SkipExpression();  // context vector
+    SkipDartType();    // skip function type
+    num_type_parameters = ReadListLength();
+  }
+  function = function.ConvertedClosureFunction(num_type_parameters);
   ASSERT(!function.IsNull());
 
   const Class& closure_class =
@@ -8444,34 +9109,25 @@
   instructions +=
       StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset());
 
-  SkipDartType();  // skip function type of the closure.
+  // Skip the function type of the closure (it's predicable from the
+  // target and the supplied type arguments).
+  SkipDartType();
 
-  // TODO(30455): Kernel generic methods undone. When generic methods are
-  // fully supported in kernel, we'll need to store a NULL in the type arguments
-  // slot when type arguments are absent, so the wrapper for the target function
-  // can tell how many type args are captured vs. provided by the caller of the
-  // closure.
-
-  intptr_t types_count = ReadListLength();  // read type count.
-  if (types_count > 0) {
-    const TypeArguments& type_args =
-        T.BuildTypeArguments(types_count);  // read list of type arguments.
-    instructions += TranslateInstantiatedTypeArguments(type_args);
-    LocalVariable* type_args_slot = MakeTemporary();
-
-    instructions += LoadLocal(context);
-    instructions += LoadLocal(type_args_slot);
-    instructions += StoreInstanceField(TokenPosition::kNoSource,
-                                       Context::variable_offset(0));
-
+  ReadListLength();  // type parameter count
+  if (num_type_parameters > 0) {
     instructions += LoadLocal(closure);
-    instructions += LoadLocal(type_args_slot);
+    const TypeArguments& type_args = T.BuildTypeArguments(
+        num_type_parameters);  // read list of type arguments.
+    instructions += TranslateInstantiatedTypeArguments(type_args);
     instructions += StoreInstanceField(
         TokenPosition::kNoSource, Closure::function_type_arguments_offset());
-
-    instructions += Drop();  // type args
   }
 
+  instructions += LoadLocal(closure);
+  instructions += Constant(Object::empty_type_arguments());
+  instructions += StoreInstanceField(TokenPosition::kNoSource,
+                                     Closure::delayed_type_arguments_offset());
+
   instructions += Drop();  // context
   return instructions;
 }
@@ -8500,23 +9156,10 @@
   instructions += LoadLocal(new_closure);
 
   intptr_t num_type_args = ReadListLength();
-  const TypeArguments* type_args = &T.BuildTypeArguments(num_type_args);
-
-  // Even if all dynamic types are passed in, we need to put a vector in here to
-  // distinguish this partially applied tearoff from a normal tearoff. This is
-  // necessary because the tearoff wrapper (BuildGraphOfImplicitClosureFunction)
-  // needs to throw NSM if type arguments are passed to a partially applied
-  // tearoff.
-  if (type_args->IsNull()) {
-    type_args =
-        &TypeArguments::ZoneHandle(Z, TypeArguments::New(num_type_args));
-    for (intptr_t i = 0; i < num_type_args; ++i) {
-      type_args->SetTypeAt(i, Type::ZoneHandle(Z, Type::DynamicType()));
-    }
-  }
-  instructions += TranslateInstantiatedTypeArguments(*type_args);
+  const TypeArguments& type_args = T.BuildTypeArguments(num_type_args);
+  instructions += TranslateInstantiatedTypeArguments(type_args);
   instructions += StoreInstanceField(TokenPosition::kNoSource,
-                                     Closure::function_type_arguments_offset());
+                                     Closure::delayed_type_arguments_offset());
 
   // Copy over the target function.
   instructions += LoadLocal(new_closure);
@@ -8532,6 +9175,13 @@
   instructions += StoreInstanceField(
       TokenPosition::kNoSource, Closure::instantiator_type_arguments_offset());
 
+  // Copy over the function type arguments.
+  instructions += LoadLocal(new_closure);
+  instructions += LoadLocal(original_closure);
+  instructions += LoadField(Closure::function_type_arguments_offset());
+  instructions += StoreInstanceField(TokenPosition::kNoSource,
+                                     Closure::function_type_arguments_offset());
+
   // Copy over the context.
   instructions += LoadLocal(new_closure);
   instructions += LoadLocal(original_closure);
@@ -9647,6 +10297,11 @@
   instructions += flow_graph_builder_->StoreInstanceField(
       TokenPosition::kNoSource, Closure::function_type_arguments_offset());
 
+  instructions += LoadLocal(closure);
+  instructions += Constant(Object::empty_type_arguments());
+  instructions += flow_graph_builder_->StoreInstanceField(
+      TokenPosition::kNoSource, Closure::delayed_type_arguments_offset());
+
   // Store the function and the context in the closure.
   instructions += LoadLocal(closure);
   instructions += Constant(function);
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 722e9ab..337c045d6 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -17,6 +17,8 @@
 namespace dart {
 namespace kernel {
 
+class KernelReaderHelper;
+
 // Helper class that reads a kernel FunctionNode from binary.
 //
 // Use ReadUntilExcluding to read up to but not including a field.
@@ -50,8 +52,8 @@
     kSyncYielding = 4,
   };
 
-  explicit FunctionNodeHelper(StreamingFlowGraphBuilder* builder) {
-    builder_ = builder;
+  explicit FunctionNodeHelper(KernelReaderHelper* helper) {
+    helper_ = helper;
     next_read_ = kStart;
   }
 
@@ -72,7 +74,7 @@
   intptr_t required_parameter_count_;
 
  private:
-  StreamingFlowGraphBuilder* builder_;
+  KernelReaderHelper* helper_;
   intptr_t next_read_;
 };
 
@@ -93,8 +95,8 @@
     kIsGenericCovariantInterface = 1 << 1
   };
 
-  explicit TypeParameterHelper(StreamingFlowGraphBuilder* builder) {
-    builder_ = builder;
+  explicit TypeParameterHelper(KernelReaderHelper* helper) {
+    helper_ = helper;
     next_read_ = kStart;
   }
 
@@ -119,7 +121,7 @@
   StringIndex name_index_;
 
  private:
-  StreamingFlowGraphBuilder* builder_;
+  KernelReaderHelper* helper_;
   intptr_t next_read_;
 };
 
@@ -151,10 +153,8 @@
     kIsGenericCovariantInterface = 1 << 6
   };
 
-  explicit VariableDeclarationHelper(StreamingFlowGraphBuilder* builder) {
-    builder_ = builder;
-    next_read_ = kPosition;
-  }
+  explicit VariableDeclarationHelper(KernelReaderHelper* helper)
+      : helper_(helper), next_read_(kPosition) {}
 
   void ReadUntilIncluding(Field field) {
     ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1));
@@ -182,7 +182,7 @@
   StringIndex name_index_;
 
  private:
-  StreamingFlowGraphBuilder* builder_;
+  KernelReaderHelper* helper_;
   intptr_t next_read_;
 };
 
@@ -219,12 +219,12 @@
     kIsGenericCovariantInterface = 1 << 7
   };
 
-  explicit FieldHelper(StreamingFlowGraphBuilder* builder)
-      : builder_(builder),
+  explicit FieldHelper(KernelReaderHelper* helper)
+      : helper_(helper),
         next_read_(kStart),
         has_function_literal_initializer_(false) {}
 
-  FieldHelper(StreamingFlowGraphBuilder* builder, intptr_t offset);
+  FieldHelper(KernelReaderHelper* helper, intptr_t offset);
 
   void ReadUntilIncluding(Field field) {
     ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1));
@@ -260,11 +260,12 @@
   TokenPosition position_;
   TokenPosition end_position_;
   uint8_t flags_;
+  uint8_t secondary_flags_;
   intptr_t source_uri_index_;
   intptr_t annotation_count_;
 
  private:
-  StreamingFlowGraphBuilder* builder_;
+  KernelReaderHelper* helper_;
   intptr_t next_read_;
 
   bool has_function_literal_initializer_;
@@ -320,10 +321,8 @@
     kNoSuchMethodForwarder = 1 << 0,
   };
 
-  explicit ProcedureHelper(StreamingFlowGraphBuilder* builder) {
-    builder_ = builder;
-    next_read_ = kStart;
-  }
+  explicit ProcedureHelper(KernelReaderHelper* helper)
+      : helper_(helper), next_read_(kStart) {}
 
   void ReadUntilIncluding(Field field) {
     ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1));
@@ -359,7 +358,7 @@
   NameIndex forwarding_stub_super_target_;
 
  private:
-  StreamingFlowGraphBuilder* builder_;
+  KernelReaderHelper* helper_;
   intptr_t next_read_;
 };
 
@@ -392,10 +391,8 @@
     kSynthetic = 1 << 2,
   };
 
-  explicit ConstructorHelper(StreamingFlowGraphBuilder* builder) {
-    builder_ = builder;
-    next_read_ = kStart;
-  }
+  explicit ConstructorHelper(KernelReaderHelper* helper)
+      : helper_(helper), next_read_(kStart) {}
 
   void ReadUntilIncluding(Field field) {
     ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1));
@@ -418,7 +415,7 @@
   intptr_t annotation_count_;
 
  private:
-  StreamingFlowGraphBuilder* builder_;
+  KernelReaderHelper* helper_;
   intptr_t next_read_;
 };
 
@@ -456,10 +453,8 @@
     kIsEnumClass = 2,
   };
 
-  explicit ClassHelper(StreamingFlowGraphBuilder* builder) {
-    builder_ = builder;
-    next_read_ = kStart;
-  }
+  explicit ClassHelper(KernelReaderHelper* helper)
+      : helper_(helper), next_read_(kStart) {}
 
   void ReadUntilIncluding(Field field) {
     ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1));
@@ -484,7 +479,7 @@
   uint8_t flags_;
 
  private:
-  StreamingFlowGraphBuilder* builder_;
+  KernelReaderHelper* helper_;
   intptr_t next_read_;
 };
 
@@ -518,10 +513,8 @@
     kExternal = 1,
   };
 
-  explicit LibraryHelper(StreamingFlowGraphBuilder* builder) {
-    builder_ = builder;
-    next_read_ = kFlags;
-  }
+  explicit LibraryHelper(KernelReaderHelper* helper)
+      : helper_(helper), next_read_(kFlags) {}
 
   void ReadUntilIncluding(Field field) {
     ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1));
@@ -542,7 +535,7 @@
   intptr_t procedure_count_;
 
  private:
-  StreamingFlowGraphBuilder* builder_;
+  KernelReaderHelper* helper_;
   intptr_t next_read_;
 };
 
@@ -567,10 +560,8 @@
     Show = 1 << 0,
   };
 
-  explicit LibraryDependencyHelper(StreamingFlowGraphBuilder* builder) {
-    builder_ = builder;
-    next_read_ = kFileOffset;
-  }
+  explicit LibraryDependencyHelper(KernelReaderHelper* helper)
+      : helper_(helper), next_read_(kFileOffset) {}
 
   void ReadUntilIncluding(Field field) {
     ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1));
@@ -583,7 +574,7 @@
   NameIndex target_library_canonical_name_;
 
  private:
-  StreamingFlowGraphBuilder* builder_;
+  KernelReaderHelper* helper_;
   intptr_t next_read_;
 };
 
@@ -792,7 +783,7 @@
   void EnterScope(intptr_t kernel_offset);
   void ExitScope(TokenPosition start_position, TokenPosition end_position);
 
-  void ReportUnexpectedTag(const char* variant, Tag tag);
+  virtual void ReportUnexpectedTag(const char* variant, Tag tag);
 
   // This enum controls which parameters would be marked as requring type
   // check on the callee side.
@@ -1002,132 +993,56 @@
   Instance& result_;
 };
 
-class StreamingFlowGraphBuilder {
+class KernelReaderHelper {
  public:
-  StreamingFlowGraphBuilder(FlowGraphBuilder* flow_graph_builder,
-                            const TypedData& data,
-                            intptr_t data_program_offset)
-      : flow_graph_builder_(flow_graph_builder),
-        translation_helper_(flow_graph_builder->translation_helper_),
-        zone_(flow_graph_builder->zone_),
-        reader_(data),
-        script_(Script::Handle(zone_, parsed_function()->function().script())),
-        constant_evaluator_(this),
-        type_translator_(this, /* finalize= */ true),
-        data_program_offset_(data_program_offset),
-        current_script_id_(-1),
-        record_for_script_id_(-1),
-        record_token_positions_into_(NULL),
-        record_yield_positions_into_(NULL),
-        direct_call_metadata_helper_(this),
-        inferred_type_metadata_helper_(this),
-        procedure_attributes_metadata_helper_(this),
-        metadata_scanned_(false) {}
-
-  StreamingFlowGraphBuilder(TranslationHelper* translation_helper,
-                            Zone* zone,
-                            const uint8_t* data_buffer,
-                            intptr_t buffer_length,
-                            intptr_t data_program_offset)
-      : flow_graph_builder_(NULL),
+  KernelReaderHelper(Zone* zone,
+                     TranslationHelper* translation_helper,
+                     const Script& script,
+                     const TypedData& data,
+                     intptr_t data_program_offset)
+      : zone_(zone),
         translation_helper_(*translation_helper),
-        zone_(zone),
-        reader_(data_buffer, buffer_length),
-        script_(Script::Handle(zone_)),
-        constant_evaluator_(this),
-        type_translator_(this, /* finalize= */ true),
-        data_program_offset_(data_program_offset),
-        current_script_id_(-1),
-        record_for_script_id_(-1),
-        record_token_positions_into_(NULL),
-        record_yield_positions_into_(NULL),
-        direct_call_metadata_helper_(this),
-        inferred_type_metadata_helper_(this),
-        procedure_attributes_metadata_helper_(this),
-        metadata_scanned_(false) {}
-
-  StreamingFlowGraphBuilder(TranslationHelper* translation_helper,
-                            const Script& script,
-                            Zone* zone,
-                            const TypedData& data,
-                            intptr_t data_program_offset)
-      : flow_graph_builder_(NULL),
-        translation_helper_(*translation_helper),
-        zone_(zone),
         reader_(data),
         script_(script),
-        constant_evaluator_(this),
-        type_translator_(this, /* finalize= */ true),
-        data_program_offset_(data_program_offset),
-        current_script_id_(-1),
-        record_for_script_id_(-1),
-        record_token_positions_into_(NULL),
-        record_yield_positions_into_(NULL),
-        direct_call_metadata_helper_(this),
-        inferred_type_metadata_helper_(this),
-        procedure_attributes_metadata_helper_(this),
-        metadata_scanned_(false) {}
+        data_program_offset_(data_program_offset) {}
 
-  ~StreamingFlowGraphBuilder() {}
+  KernelReaderHelper(Zone* zone,
+                     TranslationHelper* translation_helper,
+                     const uint8_t* data_buffer,
+                     intptr_t buffer_length,
+                     intptr_t data_program_offset)
+      : zone_(zone),
+        translation_helper_(*translation_helper),
+        reader_(data_buffer, buffer_length),
+        script_(Script::Handle(zone_)),
+        data_program_offset_(data_program_offset) {}
 
-  FlowGraph* BuildGraph(intptr_t kernel_offset);
+  virtual ~KernelReaderHelper() {}
 
-  Fragment BuildStatementAt(intptr_t kernel_offset);
-  RawObject* BuildParameterDescriptor(intptr_t kernel_offset);
-  RawObject* EvaluateMetadata(intptr_t kernel_offset);
-  void CollectTokenPositionsFor(
-      intptr_t script_index,
-      intptr_t initial_script_index,
-      intptr_t kernel_offset,
-      GrowableArray<intptr_t>* record_token_positions_in,
-      GrowableArray<intptr_t>* record_yield_positions_in);
-  intptr_t SourceTableSize();
-  String& SourceTableUriFor(intptr_t index);
-  String& GetSourceFor(intptr_t index);
-  RawTypedData* GetLineStartsFor(intptr_t index);
   void SetOffset(intptr_t offset);
 
-  // If a 'ParsedFunction' is provided for 'set_forwarding_stub', this method
-  // will attach the forwarding stub target reference to the parsed function if
-  // it crosses a procedure node for a concrete forwarding stub.
-  void ReadUntilFunctionNode(ParsedFunction* set_forwarding_stub = NULL);
   intptr_t ReadListLength();
+  virtual void ReportUnexpectedTag(const char* variant, Tag tag);
 
-  void ReportUnexpectedTag(const char* variant, Tag tag);
+ protected:
+  const Script& script() const { return script_; }
 
- private:
-  void LoadAndSetupTypeParameters(ActiveClass* active_class,
-                                  const Object& set_on,
-                                  intptr_t type_parameter_count,
-                                  const Function& parameterized_function);
+  virtual void set_current_script_id(intptr_t id) {
+    // Do nothing by default. This is overridden in StreamingFlowGraphBuilder.
+    USE(id);
+  }
 
-  void DiscoverEnclosingElements(Zone* zone,
-                                 const Function& function,
-                                 Function* outermost_function);
+  virtual void RecordYieldPosition(TokenPosition position) {
+    // Do nothing by default. This is overridden in StreamingFlowGraphBuilder.
+    USE(position);
+  }
 
-  StringIndex GetNameFromVariableDeclaration(intptr_t kernel_offset,
-                                             const Function& function);
+  virtual void RecordTokenPosition(TokenPosition position) {
+    // Do nothing by default. This is overridden in StreamingFlowGraphBuilder.
+    USE(position);
+  }
 
-  bool optimizing();
-
-  FlowGraph* BuildGraphOfFieldInitializer();
-  FlowGraph* BuildGraphOfFieldAccessor(LocalVariable* setter_value);
-  void SetupDefaultParameterValues();
-  Fragment BuildFieldInitializer(NameIndex canonical_name);
-  Fragment BuildInitializers(const Class& parent_class);
-  FlowGraph* BuildGraphOfImplicitClosureFunction(const Function& function);
-  FlowGraph* BuildGraphOfFunction(bool constructor);
-  FlowGraph* BuildGraphOfNoSuchMethodForwarder(
-      const Function& function,
-      bool is_implicit_closure_function,
-      bool throw_no_such_method_error = false);
-
-  intptr_t GetOffsetForSourceInfo(intptr_t index);
-
-  Fragment BuildExpression(TokenPosition* position = NULL);
-  Fragment BuildStatement();
-
-  intptr_t ReaderOffset();
+  intptr_t ReaderOffset() const;
   void SkipBytes(intptr_t skip);
   bool ReadBool();
   uint8_t ReadByte();
@@ -1168,12 +1083,222 @@
   void SkipLibraryPart();
   void SkipLibraryTypedef();
   TokenPosition ReadPosition(bool record = true);
-  void record_token_position(TokenPosition position);
-  void record_yield_position(TokenPosition position);
   Tag ReadTag(uint8_t* payload = NULL);
   Tag PeekTag(uint8_t* payload = NULL);
   uint8_t ReadFlags() { return reader_.ReadFlags(); }
 
+  Zone* zone_;
+  TranslationHelper& translation_helper_;
+  Reader reader_;
+  const Script& script_;
+  // Some items like variables are specified in the kernel binary as
+  // absolute offsets (as in, offsets within the whole kernel program)
+  // of their declaration nodes. Hence, to cache and/or access them
+  // uniquely from within a function's kernel data, we need to
+  // add/subtract the offset of the kernel data in the over all
+  // kernel program.
+  intptr_t data_program_offset_;
+
+  friend class ClassHelper;
+  friend class ConstantHelper;
+  friend class ConstructorHelper;
+  friend class DirectCallMetadataHelper;
+  friend class ProcedureAttributesMetadataHelper;
+  friend class FieldHelper;
+  friend class FunctionNodeHelper;
+  friend class InferredTypeMetadataHelper;
+  friend class KernelLoader;
+  friend class LibraryDependencyHelper;
+  friend class LibraryHelper;
+  friend class MetadataHelper;
+  friend class ProcedureHelper;
+  friend class SimpleExpressionConverter;
+  friend class StreamingConstantEvaluator;
+  friend class StreamingDartTypeTranslator;
+  friend class StreamingScopeBuilder;
+  friend class VariableDeclarationHelper;
+  friend class TypeParameterHelper;
+};
+
+class KernelFingerprintHelper : public KernelReaderHelper {
+ public:
+  KernelFingerprintHelper(Zone* zone,
+                          TranslationHelper* translation_helper,
+                          const Script& script,
+                          const TypedData& data,
+                          intptr_t data_program_offset)
+      : KernelReaderHelper(zone,
+                           translation_helper,
+                           script,
+                           data,
+                           data_program_offset),
+        hash_(0) {}
+
+  virtual ~KernelFingerprintHelper() {}
+  uint32_t CalculateFieldFingerprint();
+  uint32_t CalculateFunctionFingerprint();
+
+  static uint32_t CalculateHash(uint32_t current, uint32_t val) {
+    return current * 31 + val;
+  }
+
+ private:
+  void BuildHash(uint32_t val);
+  void CalculateConstructorFingerprint();
+  void CalculateArgumentsFingerprint();
+  void CalculateVariableDeclarationFingerprint();
+  void CalculateStatementListFingerprint();
+  void CalculateListOfExpressionsFingerprint();
+  void CalculateListOfDartTypesFingerprint();
+  void CalculateListOfVariableDeclarationsFingerprint();
+  void CalculateStringReferenceFingerprint();
+  void CalculateListOfStringsFingerprint();
+  void CalculateTypeParameterFingerprint();
+  void CalculateTypeParametersListFingerprint();
+  void CalculateCanonicalNameFingerprint();
+  void CalculateInitializerFingerprint();
+  void CalculateDartTypeFingerprint();
+  void CalculateOptionalDartTypeFingerprint();
+  void CalculateInterfaceTypeFingerprint(bool simple);
+  void CalculateFunctionTypeFingerprint(bool simple);
+  void CalculateGetterNameFingerprint();
+  void CalculateSetterNameFingerprint();
+  void CalculateMethodNameFingerprint();
+  void CalculateExpressionFingerprint();
+  void CalculateStatementFingerprint();
+  void CalculateFunctionNodeFingerprint();
+
+  uint32_t hash_;
+};
+
+class StreamingFlowGraphBuilder : public KernelReaderHelper {
+ public:
+  StreamingFlowGraphBuilder(FlowGraphBuilder* flow_graph_builder,
+                            const TypedData& data,
+                            intptr_t data_program_offset)
+      : KernelReaderHelper(
+            flow_graph_builder->zone_,
+            &flow_graph_builder->translation_helper_,
+            Script::Handle(
+                flow_graph_builder->zone_,
+                flow_graph_builder->parsed_function_->function().script()),
+            data,
+            data_program_offset),
+        flow_graph_builder_(flow_graph_builder),
+        constant_evaluator_(this),
+        type_translator_(this, /* finalize= */ true),
+        current_script_id_(-1),
+        record_for_script_id_(-1),
+        record_token_positions_into_(NULL),
+        record_yield_positions_into_(NULL),
+        direct_call_metadata_helper_(this),
+        inferred_type_metadata_helper_(this),
+        procedure_attributes_metadata_helper_(this),
+        metadata_scanned_(false) {}
+
+  StreamingFlowGraphBuilder(TranslationHelper* translation_helper,
+                            Zone* zone,
+                            const uint8_t* data_buffer,
+                            intptr_t buffer_length,
+                            intptr_t data_program_offset)
+      : KernelReaderHelper(zone,
+                           translation_helper,
+                           data_buffer,
+                           buffer_length,
+                           data_program_offset),
+        flow_graph_builder_(NULL),
+        constant_evaluator_(this),
+        type_translator_(this, /* finalize= */ true),
+        current_script_id_(-1),
+        record_for_script_id_(-1),
+        record_token_positions_into_(NULL),
+        record_yield_positions_into_(NULL),
+        direct_call_metadata_helper_(this),
+        inferred_type_metadata_helper_(this),
+        procedure_attributes_metadata_helper_(this),
+        metadata_scanned_(false) {}
+
+  StreamingFlowGraphBuilder(TranslationHelper* translation_helper,
+                            const Script& script,
+                            Zone* zone,
+                            const TypedData& data,
+                            intptr_t data_program_offset)
+      : KernelReaderHelper(zone,
+                           translation_helper,
+                           script,
+                           data,
+                           data_program_offset),
+        flow_graph_builder_(NULL),
+        constant_evaluator_(this),
+        type_translator_(this, /* finalize= */ true),
+        current_script_id_(-1),
+        record_for_script_id_(-1),
+        record_token_positions_into_(NULL),
+        record_yield_positions_into_(NULL),
+        direct_call_metadata_helper_(this),
+        inferred_type_metadata_helper_(this),
+        procedure_attributes_metadata_helper_(this),
+        metadata_scanned_(false) {}
+
+  virtual ~StreamingFlowGraphBuilder() {}
+
+  FlowGraph* BuildGraph(intptr_t kernel_offset);
+
+  void ReportUnexpectedTag(const char* variant, Tag tag) override;
+
+  Fragment BuildStatementAt(intptr_t kernel_offset);
+  RawObject* BuildParameterDescriptor(intptr_t kernel_offset);
+  RawObject* EvaluateMetadata(intptr_t kernel_offset);
+  void CollectTokenPositionsFor(
+      intptr_t script_index,
+      intptr_t initial_script_index,
+      intptr_t kernel_offset,
+      GrowableArray<intptr_t>* record_token_positions_in,
+      GrowableArray<intptr_t>* record_yield_positions_in);
+  intptr_t SourceTableSize();
+  String& SourceTableUriFor(intptr_t index);
+  String& GetSourceFor(intptr_t index);
+  RawTypedData* GetLineStartsFor(intptr_t index);
+
+  // If a 'ParsedFunction' is provided for 'set_forwarding_stub', this method
+  // will attach the forwarding stub target reference to the parsed function if
+  // it crosses a procedure node for a concrete forwarding stub.
+  void ReadUntilFunctionNode(ParsedFunction* set_forwarding_stub = NULL);
+
+  enum DispatchCategory { Interface, ViaThis, Closure, DynamicDispatch };
+
+ private:
+  void LoadAndSetupTypeParameters(ActiveClass* active_class,
+                                  const Object& set_on,
+                                  intptr_t type_parameter_count,
+                                  const Function& parameterized_function);
+
+  void DiscoverEnclosingElements(Zone* zone,
+                                 const Function& function,
+                                 Function* outermost_function);
+
+  StringIndex GetNameFromVariableDeclaration(intptr_t kernel_offset,
+                                             const Function& function);
+
+  bool optimizing();
+
+  FlowGraph* BuildGraphOfFieldInitializer();
+  FlowGraph* BuildGraphOfFieldAccessor(LocalVariable* setter_value);
+  void SetupDefaultParameterValues();
+  Fragment BuildFieldInitializer(NameIndex canonical_name);
+  Fragment BuildInitializers(const Class& parent_class);
+  FlowGraph* BuildGraphOfImplicitClosureFunction(const Function& function);
+  FlowGraph* BuildGraphOfFunction(bool constructor);
+  FlowGraph* BuildGraphOfNoSuchMethodForwarder(
+      const Function& function,
+      bool is_implicit_closure_function,
+      bool throw_no_such_method_error = false);
+
+  intptr_t GetOffsetForSourceInfo(intptr_t index);
+
+  Fragment BuildExpression(TokenPosition* position = NULL);
+  Fragment BuildStatement();
+
   void loop_depth_inc();
   void loop_depth_dec();
   intptr_t for_in_depth();
@@ -1425,26 +1550,18 @@
                                bool is_closure,
                                FunctionNodeHelper* function_node_helper);
 
-  const Script& script() { return script_; }
+  void set_current_script_id(intptr_t id) override { current_script_id_ = id; }
+
+  void RecordTokenPosition(TokenPosition position) override;
+  void RecordYieldPosition(TokenPosition position) override;
 
   // Scan through metadata mappings section and cache offsets for recognized
   // metadata kinds.
   void EnsureMetadataIsScanned();
 
   FlowGraphBuilder* flow_graph_builder_;
-  TranslationHelper& translation_helper_;
-  Zone* zone_;
-  Reader reader_;
-  const Script& script_;
   StreamingConstantEvaluator constant_evaluator_;
   StreamingDartTypeTranslator type_translator_;
-  // Some items like variables are specified in the kernel binary as
-  // absolute offsets (as in, offsets within the whole kernel program)
-  // of their declaration nodes. Hence, to cache and/or access them
-  // uniquely from within a function's kernel data, we need to
-  // add/subtract the offset of the kernel data in the over all
-  // kernel program.
-  intptr_t data_program_offset_;
   intptr_t current_script_id_;
   intptr_t record_for_script_id_;
   GrowableArray<intptr_t>* record_token_positions_into_;
@@ -1463,7 +1580,7 @@
   friend class FunctionNodeHelper;
   friend class InferredTypeMetadataHelper;
   friend class KernelLoader;
-  friend class KernelReader;
+  friend class KernelReaderHelper;
   friend class LibraryDependencyHelper;
   friend class LibraryHelper;
   friend class MetadataHelper;
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 5cb1b88..5d91b40 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -111,6 +111,15 @@
   return *this;
 }
 
+void Fragment::Prepend(Instruction* start) {
+  if (entry == NULL) {
+    entry = current = start;
+  } else {
+    start->LinkTo(entry);
+    entry = start;
+  }
+}
+
 Fragment Fragment::closed() {
   ASSERT(entry != NULL);
   return Fragment(entry, NULL);
@@ -547,6 +556,10 @@
   return name;
 }
 
+const String& TranslationHelper::DartFieldName(NameIndex field) {
+  return DartFieldName(CanonicalNameParent(field), CanonicalNameString(field));
+}
+
 const String& TranslationHelper::DartFieldName(NameIndex parent,
                                                StringIndex field) {
   String& name = DartString(field);
@@ -1001,17 +1014,9 @@
 
   const Function& function = parsed_function_->function();
 
-  if (function.IsClosureFunction() && !function.IsGeneric()) {
-    LocalScope* scope = parsed_function_->node_sequence()->scope();
-    LocalVariable* closure = scope->VariableAt(0);
-    ASSERT(closure != NULL);
-    instructions += LoadLocal(closure);
-    instructions += LoadField(Closure::function_type_arguments_offset());
-
-  } else if (function.IsGeneric()) {
+  if (function.IsGeneric() || function.HasGenericParent()) {
     ASSERT(parsed_function_->function_type_arguments() != NULL);
     instructions += LoadLocal(parsed_function_->function_type_arguments());
-
   } else {
     instructions += NullConstant();
   }
@@ -1333,6 +1338,52 @@
   return Fragment(new (Z) TailCallInstr(code, arg_desc));
 }
 
+Fragment BaseFlowGraphBuilder::TestTypeArgsLen(Fragment eq_branch,
+                                               Fragment neq_branch,
+                                               intptr_t num_type_args) {
+  Fragment test;
+
+  TargetEntryInstr* eq_entry;
+  TargetEntryInstr* neq_entry;
+
+  test += LoadArgDescriptor();
+  test += LoadField(ArgumentsDescriptor::type_args_len_offset());
+  test += IntConstant(num_type_args);
+  test += BranchIfEqual(&eq_entry, &neq_entry);
+
+  eq_branch.Prepend(eq_entry);
+  neq_branch.Prepend(neq_entry);
+
+  JoinEntryInstr* join = BuildJoinEntry();
+  eq_branch += Goto(join);
+  neq_branch += Goto(join);
+
+  return Fragment(test.entry, join);
+}
+
+Fragment BaseFlowGraphBuilder::TestDelayedTypeArgs(LocalVariable* closure,
+                                                   Fragment present,
+                                                   Fragment absent) {
+  Fragment test;
+
+  TargetEntryInstr* absent_entry;
+  TargetEntryInstr* present_entry;
+
+  test += LoadLocal(closure);
+  test += LoadField(Closure::delayed_type_arguments_offset());
+  test += Constant(Object::empty_type_arguments());
+  test += BranchIfEqual(&absent_entry, &present_entry);
+
+  present.Prepend(present_entry);
+  absent.Prepend(absent_entry);
+
+  JoinEntryInstr* join = BuildJoinEntry();
+  absent += Goto(join);
+  present += Goto(join);
+
+  return Fragment(test.entry, join);
+}
+
 Fragment FlowGraphBuilder::RethrowException(TokenPosition position,
                                             int catch_try_index) {
   Fragment instructions;
@@ -2156,6 +2207,11 @@
   fragment +=
       StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset());
 
+  fragment += LoadLocal(closure);
+  fragment += Constant(Object::empty_type_arguments());
+  fragment += StoreInstanceField(TokenPosition::kNoSource,
+                                 Closure::delayed_type_arguments_offset());
+
   // 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.
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index eacb8c0..abdf092 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -7,6 +7,8 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 
+#include <initializer_list>
+
 #include "vm/growable_array.h"
 #include "vm/hash_map.h"
 
@@ -169,6 +171,12 @@
 
   Fragment() : entry(NULL), current(NULL) {}
 
+  Fragment(std::initializer_list<Fragment> list) : entry(NULL), current(NULL) {
+    for (Fragment i : list) {
+      *this += i;
+    }
+  }
+
   explicit Fragment(Instruction* instruction)
       : entry(instruction), current(instruction) {}
 
@@ -178,6 +186,8 @@
   bool is_open() { return entry == NULL || current != NULL; }
   bool is_closed() { return !is_open(); }
 
+  void Prepend(Instruction* start);
+
   Fragment& operator+=(const Fragment& other);
   Fragment& operator<<=(Instruction* next);
 
@@ -396,6 +406,7 @@
   const String& DartGetterName(NameIndex getter);
   const String& DartGetterName(NameIndex parent, StringIndex getter);
 
+  const String& DartFieldName(NameIndex field);
   const String& DartFieldName(NameIndex parent, StringIndex field);
 
   const String& DartMethodName(NameIndex method);
@@ -630,6 +641,13 @@
     return LoadLocal(parsed_function_->arg_desc_var());
   }
 
+  Fragment TestTypeArgsLen(Fragment eq_branch,
+                           Fragment neq_branch,
+                           intptr_t num_type_args);
+  Fragment TestDelayedTypeArgs(LocalVariable* closure,
+                               Fragment present,
+                               Fragment absent);
+
   JoinEntryInstr* BuildThrowNoSuchMethod();
 
  protected:
@@ -655,6 +673,7 @@
   intptr_t pending_argument_count_;
 
   friend class TryCatchBlock;
+  friend class KernelReaderHelper;
   friend class StreamingFlowGraphBuilder;
   friend class FlowGraphBuilder;
   friend class PrologueBuilder;
@@ -874,6 +893,7 @@
   friend class BreakableBlock;
   friend class CatchBlock;
   friend class ConstantEvaluator;
+  friend class KernelReaderHelper;
   friend class StreamingFlowGraphBuilder;
   friend class ScopeBuilder;
   friend class SwitchBlock;
diff --git a/runtime/vm/compiler/frontend/prologue_builder.cc b/runtime/vm/compiler/frontend/prologue_builder.cc
index 66a82c9..902b5b0 100644
--- a/runtime/vm/compiler/frontend/prologue_builder.cc
+++ b/runtime/vm/compiler/frontend/prologue_builder.cc
@@ -58,7 +58,7 @@
     if (!compiling_for_osr_) prologue += f;
   }
   if (expect_type_args) {
-    Fragment f = BuildTypeArgumentsHandling(strong);
+    Fragment f = BuildTypeArgumentsHandling(nsm);
     if (link) prologue += f;
   }
 
@@ -391,36 +391,49 @@
   return populate_context;
 }
 
-Fragment PrologueBuilder::BuildTypeArgumentsHandling(bool strong) {
-  Fragment populate_args_desc;
-
+Fragment PrologueBuilder::BuildTypeArgumentsHandling(JoinEntryInstr* nsm) {
   LocalVariable* type_args_var = parsed_function_->RawTypeArgumentsVariable();
 
-  TargetEntryInstr *passed, *not_passed;
-  populate_args_desc += LoadArgDescriptor();
-  populate_args_desc += LoadField(ArgumentsDescriptor::type_args_len_offset());
-  populate_args_desc += IntConstant(0);
-  populate_args_desc += BranchIfEqual(&not_passed, &passed);
+  Fragment handling;
 
-  JoinEntryInstr* join = BuildJoinEntry();
-
-  Fragment store_type_args(passed);
+  Fragment store_type_args;
   store_type_args += LoadArgDescriptor();
   store_type_args += LoadField(ArgumentsDescriptor::count_offset());
   store_type_args += LoadFpRelativeSlot(kWordSize * (1 + kParamEndSlotFromFp));
   store_type_args += StoreLocal(TokenPosition::kNoSource, type_args_var);
   store_type_args += Drop();
-  store_type_args += Goto(join);
 
-  Fragment store_null(not_passed);
+  Fragment store_null;
   store_null += NullConstant();
   store_null += StoreLocal(TokenPosition::kNoSource, type_args_var);
   store_null += Drop();
-  store_null += Goto(join);
 
-  populate_args_desc = Fragment(populate_args_desc.entry, join);
+  handling += TestTypeArgsLen(store_null, store_type_args, 0);
 
-  return populate_args_desc;
+  if (parsed_function_->function().IsClosureFunction()) {
+    LocalVariable* closure =
+        parsed_function_->node_sequence()->scope()->VariableAt(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
+    // correct in number and bound.
+    // clang-format off
+    Fragment use_delayed_type_args = {
+      LoadLocal(closure),
+      LoadField(Closure::delayed_type_arguments_offset()),
+      StoreLocal(TokenPosition::kNoSource, type_args_var),
+      Drop()
+    };
+
+    handling += TestDelayedTypeArgs(
+        closure,
+        /*present=*/TestTypeArgsLen(
+            use_delayed_type_args, Goto(nsm), 0),
+        /*absent=*/Fragment());
+    // clang-format on
+  }
+
+  return handling;
 }
 
 void PrologueBuilder::SortOptionalNamedParametersInto(LocalVariable** opt_param,
diff --git a/runtime/vm/compiler/frontend/prologue_builder.h b/runtime/vm/compiler/frontend/prologue_builder.h
index 5e89638..2e1026f 100644
--- a/runtime/vm/compiler/frontend/prologue_builder.h
+++ b/runtime/vm/compiler/frontend/prologue_builder.h
@@ -60,7 +60,7 @@
 
   Fragment BuildClosureContextHandling();
 
-  Fragment BuildTypeArgumentsHandling(bool strong);
+  Fragment BuildTypeArgumentsHandling(JoinEntryInstr* nsm);
 
   LocalVariable* ParameterVariable(intptr_t index) {
     return parsed_function_->RawParameterVariable(index);
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index 48cc6c3..9fc7a63 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -65,7 +65,7 @@
   R3 = 3,
   R4 = 4,
   R5 = 5,  // PP
-  R6 = 6,  // CTX
+  R6 = 6,
   R7 = 7,  // iOS FP
   R8 = 8,
   R9 = 9,
@@ -264,7 +264,6 @@
 // Register aliases.
 const Register TMP = IP;            // Used as scratch register by assembler.
 const Register TMP2 = kNoRegister;  // There is no second assembler temporary.
-const Register CTX = R6;    // Location of current context at method entry.
 const Register PP = R5;     // Caches object pool pointer in generated code.
 const Register SPREG = SP;  // Stack pointer register.
 const Register FPREG = FP;  // Frame pointer register.
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index 594baf4..95b3f87 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -38,7 +38,7 @@
   R25 = 25,
   R26 = 26,  // THR
   R27 = 27,  // PP
-  R28 = 28,  // CTX
+  R28 = 28,
   R29 = 29,  // FP
   R30 = 30,  // LR
   R31 = 31,  // ZR, CSP
@@ -107,7 +107,6 @@
 // Register aliases.
 const Register TMP = R16;  // Used as scratch register by assembler.
 const Register TMP2 = R17;
-const Register CTX = R28;  // Location of current context at method entry.
 const Register PP = R27;   // Caches object pool pointer in generated code.
 const Register CODE_REG = R24;
 const Register FPREG = FP;          // Frame pointer register.
@@ -151,12 +150,12 @@
 const VRegister kAbiLastPreservedFpuReg = V15;
 const int kAbiPreservedFpuRegCount = 8;
 
-const intptr_t kReservedCpuRegisters =
-    (1 << SPREG) |  // Dart SP
-    (1 << FPREG) | (1 << TMP) | (1 << TMP2) | (1 << PP) | (1 << THR) |
-    (1 << LR) | (1 << R31) |  // C++ SP
-    (1 << CTX) | (1 << R18);  // iOS platform register.
-                              // TODO(rmacnak): Only reserve on Mac & iOS.
+const intptr_t kReservedCpuRegisters = (1 << SPREG) |  // Dart SP
+                                       (1 << FPREG) | (1 << TMP) | (1 << TMP2) |
+                                       (1 << PP) | (1 << THR) | (1 << LR) |
+                                       (1 << R31) |  // C++ SP
+                                       (1 << R18);   // iOS platform register.
+// TODO(rmacnak): Only reserve on Mac & iOS.
 // CPU registers available to Dart allocator.
 const RegList kDartAvailableCpuRegs =
     kAllCpuRegistersList & ~kReservedCpuRegisters;
diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h
index b86780e..b30f42c 100644
--- a/runtime/vm/constants_dbc.h
+++ b/runtime/vm/constants_dbc.h
@@ -310,7 +310,7 @@
 //    this instruction does so, and skips the following instruction. Otherwise,
 //    the following instruction is not skipped.
 //
-//  - StoreStaticT`OS D
+//  - StoreStaticTOS D
 //
 //    Stores TOS into the static field PP[D].
 //
@@ -908,7 +908,7 @@
   V(Entry,                                 D, num, ___, ___) \
   V(EntryOptimized,                      A_D, num, num, ___) \
   V(Frame,                                 D, num, ___, ___) \
-  V(SetFrame,                              A, num, ___, num) \
+  V(SetFrame,                              A, num, ___, ___) \
   V(AllocateContext,                       D, num, ___, ___) \
   V(AllocateUninitializedContext,        A_D, reg, num, ___) \
   V(CloneContext,                          0, ___, ___, ___) \
@@ -1080,7 +1080,6 @@
 const intptr_t CODE_REG = 0;
 const intptr_t kExceptionObjectReg = 0;
 const intptr_t kStackTraceObjectReg = 0;
-const intptr_t CTX = 0;
 
 enum FpuRegister {
   kNoFpuRegister = -1,
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index 7b4dd5c..1f4e449 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -56,7 +56,6 @@
 // Register aliases.
 const Register TMP = kNoRegister;   // No scratch register used by assembler.
 const Register TMP2 = kNoRegister;  // No second assembler scratch register.
-const Register CTX = EDI;  // Location of current context at method entry.
 const Register CODE_REG = EDI;
 const Register PP = kNoRegister;     // No object pool pointer.
 const Register SPREG = ESP;          // Stack pointer register.
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 9f9168f..3032fcf 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -99,7 +99,6 @@
 // Register aliases.
 const Register TMP = R11;  // Used as scratch register by the assembler.
 const Register TMP2 = kNoRegister;  // No second assembler scratch register.
-const Register CTX = R12;  // Location of current context at method entry.
 // Caches object pool pointer in generated code.
 const Register PP = R15;
 const Register SPREG = RSP;          // Stack pointer register.
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index eff8af8..43db729 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1511,6 +1511,9 @@
   Isolate* I = T->isolate();
   CHECK_NULL(script_snapshot_buffer);
   CHECK_NULL(script_snapshot_size);
+  if (I->strong()) {
+    return Api::NewError("Script snapshots are not supported in Dart 2");
+  }
   // Finalize all classes if needed.
   Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
   if (::Dart_IsError(state)) {
@@ -5202,6 +5205,9 @@
   if (buffer == NULL) {
     RETURN_NULL_ERROR(buffer);
   }
+  if (I->strong()) {
+    return Api::NewError("Script snapshots are not supported in Dart 2");
+  }
   NoHeapGrowthControlScope no_growth_control;
 
   const Snapshot* snapshot = Snapshot::SetupFromBuffer(buffer);
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index fc532c3..a7d2eb9 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -1927,14 +1927,14 @@
       "  var a = createExternalByteData();"
       "  Expect.equals(length, a.lengthInBytes);"
       "  for (int i = 0; i < length; i+=2) {"
-      "    Expect.equals(0x4241, a.getInt16(i, Endianness.LITTLE_ENDIAN));"
+      "    Expect.equals(0x4241, a.getInt16(i, Endian.little));"
       "  }"
       "  for (int i = 0; i < length; i+=2) {"
       "    a.setInt8(i, 0x24);"
       "    a.setInt8(i + 1, 0x28);"
       "  }"
       "  for (int i = 0; i < length; i+=2) {"
-      "    Expect.equals(0x2824, a.getInt16(i, Endianness.LITTLE_ENDIAN));"
+      "    Expect.equals(0x2824, a.getInt16(i, Endian.little));"
       "  }"
       "  return a;"
       "}\n";
@@ -1995,10 +1995,10 @@
       "}\n"
       "ByteData createExternalByteData() native 'CreateExternalByteData';"
       "access(ByteData a) {"
-      "  Expect.equals(0x04030201, a.getUint32(0, Endianness.LITTLE_ENDIAN));"
-      "  Expect.equals(0x08070605, a.getUint32(4, Endianness.LITTLE_ENDIAN));"
-      "  Expect.equals(0x0c0b0a09, a.getUint32(8, Endianness.LITTLE_ENDIAN));"
-      "  Expect.equals(0x100f0e0d, a.getUint32(12, Endianness.LITTLE_ENDIAN));"
+      "  Expect.equals(0x04030201, a.getUint32(0, Endian.little));"
+      "  Expect.equals(0x08070605, a.getUint32(4, Endian.little));"
+      "  Expect.equals(0x0c0b0a09, a.getUint32(8, Endian.little));"
+      "  Expect.equals(0x100f0e0d, a.getUint32(12, Endian.little));"
       "}"
       "ByteData main() {"
       "  var length = 16;"
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index de94a29..eb78a50 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -1280,6 +1280,11 @@
 static void RecordChanges(const GrowableObjectArray& changed_in_last_reload,
                           const Class& old_cls,
                           const Class& new_cls) {
+  // All members of enum classes are synthetic, so nothing to report here.
+  if (new_cls.is_enum_class()) {
+    return;
+  }
+
   // Don't report synthetic classes like the superclass of
   // `class MA extends S with M {}` or `class MA = S with M'. The relevant
   // changes with be reported as changes in M.
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index f65c9e4..20edba6 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -2254,7 +2254,7 @@
   intptr_t saved_subclass_count = subclasses.Length();
 
   const char* kScript =
-      "class AIterator extends Iterator {\n"
+      "abstract class AIterator extends Iterator {\n"
       "}\n"
       "main() {\n"
       "  return 1;\n"
@@ -2275,7 +2275,7 @@
   const char* kReloadScript =
       "class AIterator {\n"
       "}\n"
-      "class BIterator extends Iterator {\n"
+      "abstract class BIterator extends Iterator {\n"
       "}\n"
       "main() {\n"
       "  return 2;\n"
@@ -2310,7 +2310,7 @@
   intptr_t saved_subclass_count = subclasses.Length();
 
   const char* kScript =
-      "class AIterator extends Iterator {\n"
+      "abstract class AIterator extends Iterator {\n"
       "}\n"
       "main() {\n"
       "  return 1;\n"
@@ -2329,7 +2329,7 @@
   EXPECT_STREQ("AIterator", name.ToCString());
 
   const char* kReloadScript =
-      "class BIterator extends Iterator {\n"
+      "abstract class BIterator extends Iterator {\n"
       "}\n"
       "main() {\n"
       "  return 2;\n"
@@ -2369,7 +2369,7 @@
   intptr_t saved_subclass_count = subclasses.Length();
 
   const char* kScript =
-      "class AIterator extends Iterator {\n"
+      "abstract class AIterator extends Iterator {\n"
       "}\n"
       "class Foo {\n"
       "  final a;\n"
@@ -2394,7 +2394,7 @@
 
   // Attempt to reload with a bogus script.
   const char* kReloadScript =
-      "class BIterator extends Iterator {\n"
+      "abstract class BIterator extends Iterator {\n"
       "}\n"
       "class Foo {\n"
       "  final a kjsdf ksjdf ;\n"  // When we refinalize, we get an error.
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index 8cbc078..5394e53 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -29,6 +29,95 @@
   return field_helper.FieldHasFunctionLiteralInitializer(start, end);
 }
 
+uint32_t KernelSourceFingerprintHelper::CalculateClassFingerprint(
+    const Class& klass) {
+  Zone* zone = Thread::Current()->zone();
+
+  // Handle typedefs.
+  if (klass.IsTypedefClass()) {
+    const Function& func = Function::Handle(zone, klass.signature_function());
+    return CalculateFunctionFingerprint(func);
+  }
+
+  String& name = String::Handle(zone, klass.Name());
+  const Array& fields = Array::Handle(zone, klass.fields());
+  const Array& functions = Array::Handle(zone, klass.functions());
+  const Array& interfaces = Array::Handle(zone, klass.interfaces());
+  AbstractType& type = AbstractType::Handle(zone);
+
+  uint32_t hash = 0;
+  hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash());
+
+  type ^= klass.super_type();
+  if (!type.IsNull()) {
+    name ^= type.Name();
+    hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash());
+  }
+
+  type ^= klass.mixin();
+  if (!type.IsNull()) {
+    name ^= type.Name();
+    hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash());
+  }
+
+  Field& field = Field::Handle(zone);
+  // Calculate fingerprint for the class fields.
+  for (intptr_t i = 0; i < fields.Length(); ++i) {
+    field ^= fields.At(i);
+    uint32_t fingerprint = CalculateFieldFingerprint(field);
+    hash = KernelFingerprintHelper::CalculateHash(hash, fingerprint);
+  }
+
+  // Calculate fingerprint for the class functions.
+  Function& func = Function::Handle(zone);
+  for (intptr_t i = 0; i < functions.Length(); ++i) {
+    func ^= functions.At(i);
+    uint32_t fingerprint = CalculateFunctionFingerprint(func);
+    hash = KernelFingerprintHelper::CalculateHash(hash, fingerprint);
+  }
+
+  // Calculate fingerprint for the interfaces.
+  for (intptr_t i = 0; i < interfaces.Length(); ++i) {
+    type ^= interfaces.At(i);
+    name ^= type.Name();
+    hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash());
+  }
+
+  return hash;
+}
+
+uint32_t KernelSourceFingerprintHelper::CalculateFieldFingerprint(
+    const Field& field) {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  const Script& script = Script::Handle(zone, field.Script());
+
+  TranslationHelper translation_helper(thread);
+  translation_helper.InitFromScript(script);
+
+  KernelFingerprintHelper helper(zone, &translation_helper, script,
+                                 TypedData::Handle(zone, field.KernelData()),
+                                 field.KernelDataProgramOffset());
+  helper.SetOffset(field.kernel_offset());
+  return helper.CalculateFieldFingerprint();
+}
+
+uint32_t KernelSourceFingerprintHelper::CalculateFunctionFingerprint(
+    const Function& func) {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  const Script& script = Script::Handle(zone, func.script());
+
+  TranslationHelper translation_helper(thread);
+  translation_helper.InitFromScript(script);
+
+  KernelFingerprintHelper helper(zone, &translation_helper, script,
+                                 TypedData::Handle(zone, func.KernelData()),
+                                 func.KernelDataProgramOffset());
+  helper.SetOffset(func.kernel_offset());
+  return helper.CalculateFunctionFingerprint();
+}
+
 KernelLineStartsReader::KernelLineStartsReader(
     const dart::TypedData& line_starts_data,
     dart::Zone* zone)
diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h
index deb900d..8568139 100644
--- a/runtime/vm/kernel.h
+++ b/runtime/vm/kernel.h
@@ -123,6 +123,13 @@
   DISALLOW_COPY_AND_ASSIGN(Program);
 };
 
+class KernelSourceFingerprintHelper {
+ public:
+  static uint32_t CalculateClassFingerprint(const Class& klass);
+  static uint32_t CalculateFieldFingerprint(const Field& field);
+  static uint32_t CalculateFunctionFingerprint(const Function& func);
+};
+
 class KernelLineStartsReader {
  public:
   KernelLineStartsReader(const dart::TypedData& line_starts_data,
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index bf28e59..a5521fc 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -315,16 +315,16 @@
   // the root name as in the canonical name table.
   NameIndex ReadCanonicalNameReference() { return NameIndex(ReadUInt() - 1); }
 
-  intptr_t offset() { return offset_; }
+  intptr_t offset() const { return offset_; }
   void set_offset(intptr_t offset) { offset_ = offset; }
 
-  intptr_t size() { return size_; }
+  intptr_t size() const { return size_; }
   void set_size(intptr_t size) { size_ = size; }
 
-  const TypedData* typed_data() { return typed_data_; }
+  const TypedData* typed_data() const { return typed_data_; }
   void set_typed_data(const TypedData* typed_data) { typed_data_ = typed_data; }
 
-  const uint8_t* raw_buffer() { return raw_buffer_; }
+  const uint8_t* raw_buffer() const { return raw_buffer_; }
   void set_raw_buffer(const uint8_t* raw_buffer) { raw_buffer_ = raw_buffer; }
 
   void CopyDataToVMHeap(const TypedData& typed_data,
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index a297180..c856133 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -110,9 +110,9 @@
 Instance* Object::null_instance_ = NULL;
 Function* Object::null_function_ = NULL;
 TypeArguments* Object::null_type_arguments_ = NULL;
+TypeArguments* Object::empty_type_arguments_ = NULL;
 Array* Object::empty_array_ = NULL;
 Array* Object::zero_array_ = NULL;
-Context* Object::empty_context_ = NULL;
 ContextScope* Object::empty_context_scope_ = NULL;
 ObjectPool* Object::empty_object_pool_ = NULL;
 PcDescriptors* Object::empty_descriptors_ = NULL;
@@ -506,9 +506,9 @@
   null_instance_ = Instance::ReadOnlyHandle();
   null_function_ = Function::ReadOnlyHandle();
   null_type_arguments_ = TypeArguments::ReadOnlyHandle();
+  empty_type_arguments_ = TypeArguments::ReadOnlyHandle();
   empty_array_ = Array::ReadOnlyHandle();
   zero_array_ = Array::ReadOnlyHandle();
-  empty_context_ = Context::ReadOnlyHandle();
   empty_context_scope_ = ContextScope::ReadOnlyHandle();
   empty_object_pool_ = ObjectPool::ReadOnlyHandle();
   empty_descriptors_ = PcDescriptors::ReadOnlyHandle();
@@ -538,6 +538,7 @@
   *null_instance_ = Instance::null();
   *null_function_ = Function::null();
   *null_type_arguments_ = TypeArguments::null();
+  *empty_type_arguments_ = TypeArguments::null();
 
   // Initialize the empty and zero array handles to null_ in order to be able to
   // check if the empty and zero arrays were allocated (RAW_NULL is not
@@ -775,17 +776,6 @@
     zero_array_->SetCanonical();
   }
 
-  // Allocate and initialize the empty context object.
-  {
-    uword address = heap->Allocate(Context::InstanceSize(0), Heap::kOld);
-    InitializeObject(address, kContextCid, Context::InstanceSize(0), true);
-    Context::initializeHandle(empty_context_, reinterpret_cast<RawContext*>(
-                                                  address + kHeapObjectTag));
-    empty_context_->StoreNonPointer(&empty_context_->raw_ptr()->num_variables_,
-                                    0);
-    empty_context_->SetCanonical();
-  }
-
   // Allocate and initialize the canonical empty context scope object.
   {
     uword address = heap->Allocate(ContextScope::InstanceSize(0), Heap::kOld);
@@ -857,6 +847,21 @@
     empty_exception_handlers_->SetCanonical();
   }
 
+  // Allocate and initialize the canonical empty type arguments object.
+  {
+    uword address = heap->Allocate(TypeArguments::InstanceSize(0), Heap::kOld);
+    InitializeObject(address, kTypeArgumentsCid, TypeArguments::InstanceSize(0),
+                     true);
+    TypeArguments::initializeHandle(
+        empty_type_arguments_,
+        reinterpret_cast<RawTypeArguments*>(address + kHeapObjectTag));
+    empty_type_arguments_->StoreSmi(&empty_type_arguments_->raw_ptr()->length_,
+                                    Smi::New(0));
+    empty_type_arguments_->StoreSmi(&empty_type_arguments_->raw_ptr()->hash_,
+                                    Smi::New(0));
+    empty_type_arguments_->SetCanonical();
+  }
+
   // The VM isolate snapshot object table is initialized to an empty array
   // as we do not have any VM isolate snapshot at this time.
   *vm_isolate_snapshot_object_table_ = Object::empty_array().raw();
@@ -962,8 +967,6 @@
   ASSERT(empty_array_->IsArray());
   ASSERT(!zero_array_->IsSmi());
   ASSERT(zero_array_->IsArray());
-  ASSERT(!empty_context_->IsSmi());
-  ASSERT(empty_context_->IsContext());
   ASSERT(!empty_context_scope_->IsSmi());
   ASSERT(empty_context_scope_->IsContextScope());
   ASSERT(!empty_descriptors_->IsSmi());
@@ -3715,8 +3718,16 @@
 }
 
 int32_t Class::SourceFingerprint() const {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  if (kernel_offset() > 0) {
+    return kernel::KernelSourceFingerprintHelper::CalculateClassFingerprint(
+        *this);
+  }
   return Script::Handle(script()).SourceFingerprint(token_pos(),
                                                     ComputeEndTokenPos());
+#else
+  return 0;
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
 
 void Class::set_is_implemented() const {
@@ -4855,6 +4866,28 @@
   return result;
 }
 
+RawTypeArguments* TypeArguments::Prepend(Zone* zone,
+                                         const TypeArguments& other,
+                                         intptr_t total_length) const {
+  if (IsNull() && other.IsNull()) {
+    return Object::null_type_arguments().raw();
+  }
+  const TypeArguments& result =
+      TypeArguments::Handle(zone, TypeArguments::New(total_length, Heap::kNew));
+  AbstractType& type = AbstractType::Handle(zone);
+  const intptr_t split =
+      other.IsNull() ? total_length - Length() : other.Length();
+  for (intptr_t i = 0; i < split; i++) {
+    type = other.IsNull() ? Type::DynamicType() : other.TypeAt(i);
+    result.SetTypeAt(i, type);
+  }
+  for (intptr_t i = split; i < total_length; i++) {
+    type = IsNull() ? Type::DynamicType() : TypeAt(i - split);
+    result.SetTypeAt(i, type);
+  }
+  return result.Canonicalize();
+}
+
 RawString* TypeArguments::SubvectorName(intptr_t from_index,
                                         intptr_t len,
                                         NameVisibility name_visibility) const {
@@ -5805,6 +5838,8 @@
     // The parent function of an implicit closure function is not the enclosing
     // function we are asking about here.
     return false;
+  } else if (IsConvertedClosureFunction()) {
+    return NumParentTypeParameters() > 0;
   }
   Function& parent = Function::Handle(parent_function());
   while (!parent.IsNull()) {
@@ -6212,6 +6247,8 @@
 intptr_t Function::NumParentTypeParameters() const {
   if (IsImplicitClosureFunction()) {
     return 0;
+  } else if (IsConvertedClosureFunction()) {
+    return num_parent_type_parameters();
   }
   Thread* thread = Thread::Current();
   Function& parent = Function::Handle(parent_function());
@@ -6738,21 +6775,10 @@
     }
   }
 
-  Function& sig = Function::Handle(zone, Function::null());
-  if (IsConvertedClosureFunction() && !delete_type_parameters) {
-    sig = Function::NewConvertedClosureFunction(
-        String::Handle(zone, name()), parent, TokenPosition::kNoSource);
-    // TODO(30455): Kernel generic methods undone. Handle type parameters
-    // correctly when generic closures are supported. Until then, all type
-    // parameters to this target are used for captured type variables, so they
-    // aren't relevant to the type of the function.
-    sig.set_type_parameters(TypeArguments::Handle(zone, TypeArguments::null()));
-  } else {
-    sig = Function::NewSignatureFunction(owner, parent,
-                                         TokenPosition::kNoSource, space);
-    if (!delete_type_parameters) {
-      sig.set_type_parameters(TypeArguments::Handle(zone, type_parameters()));
-    }
+  Function& sig = Function::Handle(Function::NewSignatureFunction(
+      owner, parent, TokenPosition::kNoSource, space));
+  if (!delete_type_parameters) {
+    sig.set_type_parameters(TypeArguments::Handle(zone, type_parameters()));
   }
 
   AbstractType& type = AbstractType::Handle(zone, result_type());
@@ -7425,7 +7451,8 @@
 //
 // Function::ConvertedClosureFunction method follows the logic of
 // Function::ImplicitClosureFunction method.
-RawFunction* Function::ConvertedClosureFunction() const {
+RawFunction* Function::ConvertedClosureFunction(
+    intptr_t num_parent_type_parameters) const {
   // Return the existing converted closure function if any.
   if (converted_closure_function() != Function::null()) {
     return converted_closure_function();
@@ -7443,8 +7470,28 @@
   closure_function.set_context_scope(Object::empty_context_scope());
 
   // Set closure function's type parameters.
-  closure_function.set_type_parameters(
-      TypeArguments::Handle(zone, type_parameters()));
+  {
+    TypeArguments& total_type_parameters =
+        TypeArguments::Handle(type_parameters());
+
+    intptr_t num_type_parameters =
+        total_type_parameters.Length() - num_parent_type_parameters;
+    if (num_type_parameters == 0) {
+      closure_function.set_type_parameters(Object::null_type_arguments());
+    } else {
+      ASSERT(num_type_parameters > 0);
+      TypeArguments& new_type_parameters =
+          TypeArguments::Handle(TypeArguments::New(num_type_parameters));
+
+      for (intptr_t i = 0; i < num_type_parameters; ++i) {
+        new_type_parameters.SetTypeAt(
+            i, AbstractType::Handle(total_type_parameters.TypeAt(
+                   i + num_parent_type_parameters)));
+      }
+      closure_function.set_type_parameters(new_type_parameters);
+    }
+    closure_function.set_num_parent_type_parameters(num_parent_type_parameters);
+  }
 
   // Set closure function's result type to this result type.
   closure_function.set_result_type(AbstractType::Handle(zone, result_type()));
@@ -7507,6 +7554,26 @@
   }
 }
 
+void Function::set_num_parent_type_parameters(intptr_t num) const {
+  if (IsConvertedClosureFunction()) {
+    const Object& obj = Object::Handle(raw_ptr()->data_);
+    ASSERT(!obj.IsNull());
+    ClosureData::Cast(obj).set_num_parent_type_parameters(num);
+    return;
+  }
+  UNREACHABLE();
+}
+
+intptr_t Function::num_parent_type_parameters() const {
+  if (IsConvertedClosureFunction()) {
+    const Object& obj = Object::Handle(raw_ptr()->data_);
+    ASSERT(!obj.IsNull());
+    return ClosureData::Cast(obj).num_parent_type_parameters();
+  }
+  UNREACHABLE();
+  return 0;
+}
+
 void Function::BuildSignatureParameters(
     Thread* thread,
     Zone* zone,
@@ -7569,7 +7636,7 @@
   ASSERT(IsImplicitStaticClosureFunction());
   if (implicit_static_closure() == Instance::null()) {
     Zone* zone = Thread::Current()->zone();
-    const Context& context = Object::empty_context();
+    const Context& context = Context::Handle(zone);
     Instance& closure =
         Instance::Handle(zone, Closure::New(Object::null_type_arguments(),
                                             Object::null_type_arguments(),
@@ -7645,35 +7712,6 @@
 bool Function::HasInstantiatedSignature(Genericity genericity,
                                         intptr_t num_free_fun_type_params,
                                         TrailPtr trail) const {
-  // This function works differently for converted closures.
-  //
-  // Unlike regular closures, it's not possible to know which type parameters
-  // are supposed to come from parent functions or classes and which are
-  // actually parameters to the closure it represents. For example, consider:
-  //
-  //     class C<T> {
-  //       getf() => (T x) { return x; }
-  //     }
-  //
-  //     class D {
-  //       getf() {
-  //         dynamic fn<T>(T x) { return x; }
-  //         return fn;
-  //       }
-  //     }
-  //
-  // The signature of `fn` as a converted closure will in both cases look like
-  // `<T>(T) => dynamic`, because the signature of the converted closure
-  // function is the same as its top-level target function. However, in the
-  // first case the closure's type is instantiated, and in the second case
-  // it's not.
-  //
-  // Since we can never assume a converted closure is instantiated if it has any
-  // type parameters, we always return true in these cases.
-  if (IsConvertedClosureFunction()) {
-    return genericity == kCurrentClass || NumTypeParameters() == 0;
-  }
-
   if (num_free_fun_type_params == kCurrentAndEnclosingFree) {
     num_free_fun_type_params = kAllFree;
   } else if (genericity != kCurrentClass) {
@@ -7896,8 +7934,16 @@
 // Construct fingerprint from token stream. The token stream contains also
 // arguments.
 int32_t Function::SourceFingerprint() const {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  if (kernel_offset() > 0) {
+    return kernel::KernelSourceFingerprintHelper::CalculateFunctionFingerprint(
+        *this);
+  }
   return Script::Handle(script()).SourceFingerprint(token_pos(),
                                                     end_token_pos());
+#else
+  return 0;
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
 
 void Function::SaveICDataMap(
@@ -8073,6 +8119,14 @@
                      const_str);
 }
 
+intptr_t ClosureData::num_parent_type_parameters() const {
+  return Smi::Value(raw_ptr()->num_parent_type_parameters_);
+}
+
+void ClosureData::set_num_parent_type_parameters(intptr_t value) const {
+  StorePointer(&raw_ptr()->num_parent_type_parameters_, Smi::New(value));
+}
+
 void ClosureData::set_context_scope(const ContextScope& value) const {
   StorePointer(&raw_ptr()->context_scope_, value.raw());
 }
@@ -8440,8 +8494,16 @@
 }
 
 int32_t Field::SourceFingerprint() const {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  if (kernel_offset() > 0) {
+    return kernel::KernelSourceFingerprintHelper::CalculateFieldFingerprint(
+        *this);
+  }
   return Script::Handle(Script()).SourceFingerprint(token_pos(),
                                                     end_token_pos());
+#else
+  return 0;
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
 
 RawString* Field::InitializingExpression() const {
@@ -17603,7 +17665,6 @@
 RawAbstractType* Type::CloneUninstantiated(const Class& new_owner,
                                            TrailPtr trail) const {
   ASSERT(IsFinalized());
-  ASSERT(IsCanonical());
   ASSERT(!IsMalformed());
   if (IsInstantiated()) {
     return raw();
@@ -22714,6 +22775,8 @@
                         instantiator_type_arguments.raw());
     result.StorePointer(&result.raw_ptr()->function_type_arguments_,
                         function_type_arguments.raw());
+    result.StorePointer(&result.raw_ptr()->delayed_type_arguments_,
+                        Object::empty_type_arguments().raw());
     result.StorePointer(&result.raw_ptr()->function_, function.raw());
     result.StorePointer(&result.raw_ptr()->context_, context.raw());
   }
@@ -22728,16 +22791,24 @@
 
 RawFunction* Closure::GetInstantiatedSignature(Zone* zone) const {
   Function& sig_fun = Function::Handle(zone, function());
-  const TypeArguments& fn_type_args =
+  TypeArguments& fn_type_args =
       TypeArguments::Handle(zone, function_type_arguments());
+  const TypeArguments& delayed_type_args =
+      TypeArguments::Handle(zone, delayed_type_arguments());
   const TypeArguments& inst_type_args =
       TypeArguments::Handle(zone, instantiator_type_arguments());
+
   // We detect the case of a partial tearoff type application and substitute the
   // type arguments for the type parameters of the function.
-  intptr_t num_free_params =
-      sig_fun.IsImplicitClosureFunction() && !fn_type_args.IsNull()
-          ? kCurrentAndEnclosingFree
-          : kAllFree;
+  intptr_t num_free_params;
+  if (delayed_type_args.raw() != Object::empty_type_arguments().raw()) {
+    num_free_params = kCurrentAndEnclosingFree;
+    fn_type_args = delayed_type_args.Prepend(
+        zone, fn_type_args,
+        sig_fun.NumTypeParameters() + sig_fun.NumParentTypeParameters());
+  } else {
+    num_free_params = kAllFree;
+  }
   if (num_free_params == kCurrentAndEnclosingFree ||
       !sig_fun.HasInstantiatedSignature(kAny)) {
     return sig_fun.InstantiateSignatureFrom(inst_type_args, fn_type_args,
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index de0a01a..ea2c4d5 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -370,6 +370,10 @@
     ASSERT(null_type_arguments_ != NULL);
     return *null_type_arguments_;
   }
+  static const TypeArguments& empty_type_arguments() {
+    ASSERT(empty_type_arguments_ != NULL);
+    return *empty_type_arguments_;
+  }
 
   static const Array& empty_array() {
     ASSERT(empty_array_ != NULL);
@@ -380,11 +384,6 @@
     return *zero_array_;
   }
 
-  static const Context& empty_context() {
-    ASSERT(empty_context_ != NULL);
-    return *empty_context_;
-  }
-
   static const ContextScope& empty_context_scope() {
     ASSERT(empty_context_scope_ != NULL);
     return *empty_context_scope_;
@@ -817,9 +816,9 @@
   static Instance* null_instance_;
   static Function* null_function_;
   static TypeArguments* null_type_arguments_;
+  static TypeArguments* empty_type_arguments_;
   static Array* empty_array_;
   static Array* zero_array_;
-  static Context* empty_context_;
   static ContextScope* empty_context_scope_;
   static ObjectPool* empty_object_pool_;
   static PcDescriptors* empty_descriptors_;
@@ -2163,6 +2162,11 @@
   RawArray* parameter_names() const { return raw_ptr()->parameter_names_; }
   void set_parameter_names(const Array& value) const;
 
+  // For converted closure functions: indicate how many type parameters on the
+  // target are actually captured.
+  void set_num_parent_type_parameters(intptr_t num) const;
+  intptr_t num_parent_type_parameters() const;
+
   // The type parameters (and their bounds) are specified as an array of
   // TypeParameter.
   RawTypeArguments* type_parameters() const {
@@ -2300,7 +2304,8 @@
   // If none exists yet, create one and remember it.  See the comment on
   // ConvertedClosureFunction definition in runtime/vm/object.cc for elaborate
   // explanation.
-  RawFunction* ConvertedClosureFunction() const;
+  RawFunction* ConvertedClosureFunction(
+      intptr_t num_parent_type_parameters) const;
   void DropUncompiledConvertedClosureFunction() const;
 
   // Return the closure implicitly created for this function.
@@ -2983,6 +2988,9 @@
   RawInstance* implicit_static_closure() const { return raw_ptr()->closure_; }
   void set_implicit_static_closure(const Instance& closure) const;
 
+  intptr_t num_parent_type_parameters() const;
+  void set_num_parent_type_parameters(intptr_t value) const;
+
   static RawClosureData* New();
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(ClosureData, Object);
@@ -5741,6 +5749,10 @@
     return IsDynamicTypes(true, 0, len);
   }
 
+  RawTypeArguments* Prepend(Zone* zone,
+                            const TypeArguments& other,
+                            intptr_t total_length) const;
+
   // Check if the subvector of length 'len' starting at 'from_index' of this
   // type argument vector consists solely of DynamicType, ObjectType, or
   // VoidType.
@@ -8744,6 +8756,13 @@
     return OFFSET_OF(RawClosure, function_type_arguments_);
   }
 
+  RawTypeArguments* delayed_type_arguments() const {
+    return raw_ptr()->delayed_type_arguments_;
+  }
+  static intptr_t delayed_type_arguments_offset() {
+    return OFFSET_OF(RawClosure, delayed_type_arguments_);
+  }
+
   RawFunction* function() const { return raw_ptr()->function_; }
   static intptr_t function_offset() { return OFFSET_OF(RawClosure, function_); }
 
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index de84a19..5d52cbd 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -983,7 +983,8 @@
   RawFunction* parent_function_;  // Enclosing function of this local function.
   RawType* signature_type_;
   RawInstance* closure_;  // Closure object for static implicit closures.
-  VISIT_TO(RawObject*, closure_);
+  RawSmi* num_parent_type_parameters_;  // For converted closures only
+  VISIT_TO(RawObject*, num_parent_type_parameters_);
 
   friend class Function;
 };
@@ -1894,17 +1895,21 @@
   VISIT_FROM(RawCompressed, instantiator_type_arguments_)
   RawTypeArguments* instantiator_type_arguments_;
   RawTypeArguments* function_type_arguments_;
+  RawTypeArguments* delayed_type_arguments_;
   RawFunction* function_;
   RawContext* context_;
   RawSmi* hash_;
+
   VISIT_TO(RawCompressed, hash_)
 
-  // Note that instantiator_type_arguments_ and function_type_arguments_ are
-  // used to instantiate the signature of function_ when this closure is
-  // involved in a type test. In other words, these fields define the function
-  // type of this closure instance, but they are not used when invoking it.
-  // Whereas the source frontend will save a copy of the function's type
-  // arguments in the closure's context and only use the
+  // Note that instantiator_type_arguments_, function_type_arguments_ and
+  // delayed_type_arguments_ are used to instantiate the signature of function_
+  // when this closure is involved in a type test. In other words, these fields
+  // define the function type of this closure instance.
+  //
+  // function_type_arguments_ and delayed_type_arguments_ may also be used when
+  // invoking the closure. Whereas the source frontend will save a copy of the
+  // function's type arguments in the closure's context and only use the
   // function_type_arguments_ field for type tests, the kernel frontend will use
   // the function_type_arguments_ vector here directly.
   //
@@ -1913,6 +1918,12 @@
   // if the generic closure function_ has a generic parent function, the
   // passed-in function type arguments get concatenated to the function type
   // arguments of the parent that are found in the context_.
+  //
+  // delayed_type_arguments_ is used to support the parital instantiation
+  // feature. When this field is set to any value other than
+  // Object::empty_type_arguments(), the types in this vector will be passed as
+  // type arguments to the closure when invoked. In this case there may not be
+  // any type arguments passed directly (or NSM will be invoked instead).
 };
 
 class RawNumber : public RawInstance {
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index dd41cf1..bac281c 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1478,9 +1478,7 @@
   int32_t num_vars = reader->Read<int32_t>();
   Context& context = Context::ZoneHandle(reader->zone());
   reader->AddBackRef(object_id, &context, kIsDeserialized);
-  if (num_vars == 0) {
-    context ^= Object::empty_context().raw();
-  } else {
+  if (num_vars != 0) {
     context ^= Context::New(num_vars);
 
     // Set all the object fields.
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc
index 4dbb6b6..e07e393 100644
--- a/runtime/vm/scopes.cc
+++ b/runtime/vm/scopes.cc
@@ -643,7 +643,8 @@
           (variable->name().raw() == Symbols::StackTraceVar().raw()) ||
           (variable->name().raw() == Symbols::ExceptionVar().raw()) ||
           (variable->name().raw() == Symbols::SavedTryContextVar().raw()) ||
-          (variable->name().raw() == Symbols::ArgDescVar().raw())) {
+          (variable->name().raw() == Symbols::ArgDescVar().raw()) ||
+          (variable->name().raw() == Symbols::FunctionTypeArgumentsVar().raw())) {
         // Don't capture those variables because the VM expects them to be on
         // the stack.
         continue;
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index ca885ea..1efbaa8 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -133,7 +133,7 @@
                                  "sp",  "ip",  "fp",  "pp",  "ctx"};
   static const Register kRegisters[] = {R0, R1, R2,  R3,  R4,  R5,  R6,  R7,
                                         R8, R9, R10, R11, R12, R13, R14, R15,
-                                        PC, LR, SP,  IP,  FP,  PP,  CTX};
+                                        PC, LR, SP,  IP,  FP,  PP};
   ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters));
   for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) {
     if (strcmp(kNames[i], name) == 0) {
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index c115b7c..3db2d65 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -133,14 +133,14 @@
       "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
       "r24", "r25", "r26", "r27", "r28", "r29", "r30",
 
-      "ip0", "ip1", "pp",  "ctx", "fp",  "lr",  "sp",  "zr",
+      "ip0", "ip1", "pp",  "fp",  "lr",  "sp",  "zr",
   };
   static const Register kRegisters[] = {
       R0,  R1,  R2,  R3,  R4,  R5,  R6,  R7,  R8,  R9,  R10,
       R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21,
       R22, R23, R24, R25, R26, R27, R28, R29, R30,
 
-      IP0, IP1, PP,  CTX, FP,  LR,  R31, ZR,
+      IP0, IP1, PP,  FP,  LR,  R31, ZR,
   };
   ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters));
   for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) {
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 447fbf4..d3667ce 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -751,13 +751,14 @@
   READ_VM_SINGLETON_OBJ(kZeroArrayObject, Object::zero_array().raw());
   READ_VM_SINGLETON_OBJ(kDynamicType, Object::dynamic_type().raw());
   READ_VM_SINGLETON_OBJ(kVoidType, Object::void_type().raw());
+  READ_VM_SINGLETON_OBJ(kEmptyTypeArguments,
+                        Object::empty_type_arguments().raw());
   READ_VM_SINGLETON_OBJ(kTrueValue, Bool::True().raw());
   READ_VM_SINGLETON_OBJ(kFalseValue, Bool::False().raw());
   READ_VM_SINGLETON_OBJ(kExtractorParameterTypes,
                         Object::extractor_parameter_types().raw());
   READ_VM_SINGLETON_OBJ(kExtractorParameterNames,
                         Object::extractor_parameter_names().raw());
-  READ_VM_SINGLETON_OBJ(kEmptyContextObject, Object::empty_context().raw());
   READ_VM_SINGLETON_OBJ(kEmptyContextScopeObject,
                         Object::empty_context_scope().raw());
   READ_VM_SINGLETON_OBJ(kEmptyObjectPool, Object::empty_object_pool().raw());
@@ -1018,13 +1019,14 @@
   WRITE_VM_SINGLETON_OBJ(Object::zero_array().raw(), kZeroArrayObject);
   WRITE_VM_SINGLETON_OBJ(Object::dynamic_type().raw(), kDynamicType);
   WRITE_VM_SINGLETON_OBJ(Object::void_type().raw(), kVoidType);
+  WRITE_VM_SINGLETON_OBJ(Object::empty_type_arguments().raw(),
+                         kEmptyTypeArguments);
   WRITE_VM_SINGLETON_OBJ(Bool::True().raw(), kTrueValue);
   WRITE_VM_SINGLETON_OBJ(Bool::False().raw(), kFalseValue);
   WRITE_VM_SINGLETON_OBJ(Object::extractor_parameter_types().raw(),
                          kExtractorParameterTypes);
   WRITE_VM_SINGLETON_OBJ(Object::extractor_parameter_names().raw(),
                          kExtractorParameterNames);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_context().raw(), kEmptyContextObject);
   WRITE_VM_SINGLETON_OBJ(Object::empty_context_scope().raw(),
                          kEmptyContextScopeObject);
   WRITE_VM_SINGLETON_OBJ(Object::empty_object_pool().raw(), kEmptyObjectPool);
diff --git a/runtime/vm/snapshot_ids.h b/runtime/vm/snapshot_ids.h
index 3f2464a..d767648 100644
--- a/runtime/vm/snapshot_ids.h
+++ b/runtime/vm/snapshot_ids.h
@@ -42,10 +42,10 @@
   kBoolType,
   kStringType,
   kArrayType,
+  kEmptyTypeArguments,
 
   kExtractorParameterTypes,
   kExtractorParameterNames,
-  kEmptyContextObject,
   kEmptyContextScopeObject,
   kImplicitClosureScopeObject,
   kEmptyObjectPool,
@@ -53,9 +53,9 @@
   kEmptyVarDescriptors,
   kEmptyExceptionHandlers,
   kCachedArgumentsDescriptor0,
-  kCachedArgumentsDescriptorN = (kCachedArgumentsDescriptor0 +
-                                 ArgumentsDescriptor::kCachedDescriptorCount -
-                                 1),
+  kCachedArgumentsDescriptorN =
+      (kCachedArgumentsDescriptor0 +
+       ArgumentsDescriptor::kCachedDescriptorCount - 1),
   kCachedICDataArray0,
   kCachedICDataArrayN =
       (kCachedICDataArray0 + ICData::kCachedICDataArrayCount - 1),
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index c22d567..4d58c04 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -429,24 +429,24 @@
 # This is the main target for copying scripts in _platform_sdk_scripts to bin/
 group("copy_platform_sdk_scripts") {
   visibility = [ ":create_platform_sdk" ]
-  deps = []
+  public_deps = []
   foreach(sdk_script, _platform_sdk_scripts) {
-    deps += [ ":copy_${sdk_script}_script" ]
+    public_deps += [ ":copy_${sdk_script}_script" ]
   }
   foreach(script, _scripts) {
-    deps += [ ":copy_${script}_script" ]
+    public_deps += [ ":copy_${script}_script" ]
   }
 }
 
 # This is the main target for copying scripts in _full_sdk_scripts to bin/
 group("copy_full_sdk_scripts") {
   visibility = [ ":create_full_sdk" ]
-  deps = []
+  public_deps = []
   foreach(sdk_script, _full_sdk_scripts) {
-    deps += [ ":copy_${sdk_script}_script" ]
+    public_deps += [ ":copy_${sdk_script}_script" ]
   }
   foreach(script, _scripts) {
-    deps += [ ":copy_${script}_script" ]
+    public_deps += [ ":copy_${script}_script" ]
   }
 }
 
@@ -473,9 +473,9 @@
 # bin/snapshots
 group("copy_platform_sdk_snapshots") {
   visibility = [ ":create_platform_sdk" ]
-  deps = []
+  public_deps = []
   foreach(snapshot, _platform_sdk_snapshots) {
-    deps += [ ":copy_${snapshot[0]}_snapshot" ]
+    public_deps += [ ":copy_${snapshot[0]}_snapshot" ]
   }
 }
 
@@ -483,18 +483,18 @@
 # bin/snapshots
 group("copy_full_sdk_snapshots") {
   visibility = [ ":create_full_sdk" ]
-  deps = []
+  public_deps = []
   foreach(snapshot, _full_sdk_snapshots) {
-    deps += [ ":copy_${snapshot[0]}_snapshot" ]
+    public_deps += [ ":copy_${snapshot[0]}_snapshot" ]
   }
 }
 
 # This is the main rule for copying analyzer sources to lib/
 group("copy_analyzer_sources") {
   visibility = [ ":create_common_sdk" ]
-  deps = []
+  public_deps = []
   foreach(analyzer_source_dir, _analyzer_source_dirs) {
-    deps += [ ":copy_${analyzer_source_dir}_source_dir" ]
+    public_deps += [ ":copy_${analyzer_source_dir}_source_dir" ]
   }
 }
 
@@ -505,7 +505,7 @@
 # This is the main rule for copying the files that dartdoc needs.
 group("copy_dartdoc_files") {
   visibility = [ ":create_common_sdk" ]
-  deps = [
+  public_deps = [
     ":copy_dartdoc_resources",
     ":copy_dartdoc_templates",
   ]
@@ -732,7 +732,7 @@
     ":copy_dev_compiler_sdk",
     ":copy_dev_compiler_tools",
   ]
-  deps = [
+  public_deps = [
     ":copy_dev_compiler_js_amd",
     ":copy_dev_compiler_js_amd_kernel",
     ":copy_dev_compiler_js_common",
@@ -765,7 +765,7 @@
 # This is the main rule for copying ddc's dependencies to lib/
 group("copy_dev_compiler_sdk") {
   visibility = [ ":create_full_sdk" ]
-  deps = [
+  public_deps = [
     ":copy_dev_compiler_js",
     ":copy_dev_compiler_summary",
     ":copy_dev_compiler_tools",
@@ -819,9 +819,9 @@
     ":create_platform_sdk",
     ":copy_libraries",
   ]
-  deps = []
+  public_deps = []
   foreach(library, _platform_sdk_libraries) {
-    deps += [ ":copy_${library}_library" ]
+    public_deps += [ ":copy_${library}_library" ]
   }
 }
 
@@ -831,19 +831,19 @@
     ":create_full_sdk",
     ":copy_libraries",
   ]
-  deps = []
+  public_deps = []
   foreach(library, _full_sdk_libraries) {
-    deps += [ ":copy_${library}_library" ]
+    public_deps += [ ":copy_${library}_library" ]
   }
 }
 
 group("copy_libraries") {
   if (dart_platform_sdk) {
-    deps = [
+    public_deps = [
       ":copy_platform_sdk_libraries",
     ]
   } else {
-    deps = [
+    public_deps = [
       ":copy_full_sdk_libraries",
     ]
   }
@@ -947,7 +947,7 @@
 # Parts common to both platform and full SDKs.
 group("create_common_sdk") {
   visibility = [ ":create_sdk" ]
-  deps = [
+  public_deps = [
     ":copy_analysis_summaries",
     ":copy_analyzer_sources",
     ":copy_api_readme",
@@ -966,14 +966,14 @@
     ":write_version_file",
   ]
   if (is_win) {
-    deps += [ ":copy_7zip" ]
+    public_deps += [ ":copy_7zip" ]
   }
 }
 
 # Parts specific to the platform SDK.
 group("create_platform_sdk") {
   visibility = [ ":create_sdk" ]
-  deps = [
+  public_deps = [
     ":copy_platform_sdk_libraries",
     ":copy_platform_sdk_scripts",
     ":copy_platform_sdk_snapshots",
@@ -984,7 +984,7 @@
 group("create_full_sdk") {
   visibility = [ ":create_sdk" ]
 
-  deps = [
+  public_deps = [
     ":copy_dart2js_dill_files",
     ":copy_dev_compiler_sdk",
     ":copy_full_sdk_libraries",
@@ -995,12 +995,12 @@
 
 # The main target to depend on from ../BUILD.gn
 group("create_sdk") {
-  deps = [
+  public_deps = [
     ":create_common_sdk",
   ]
   if (dart_platform_sdk) {
-    deps += [ ":create_platform_sdk" ]
+    public_deps += [ ":create_platform_sdk" ]
   } else {
-    deps += [ ":create_full_sdk" ]
+    public_deps += [ ":create_full_sdk" ]
   }
 }
diff --git a/sdk/lib/_internal/js_runtime/lib/async_patch.dart b/sdk/lib/_internal/js_runtime/lib/async_patch.dart
index bec28e9..5f04f0b 100644
--- a/sdk/lib/_internal/js_runtime/lib/async_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/async_patch.dart
@@ -17,7 +17,7 @@
 import 'dart:_isolate_helper'
     show IsolateNatives, TimerImpl, leaveJsAsync, enterJsAsync, isWorker;
 
-import 'dart:_foreign_helper' show JS;
+import 'dart:_foreign_helper' show JS, JS_GET_FLAG;
 
 import 'dart:_async_await_error_codes' as async_error_codes;
 
@@ -53,8 +53,6 @@
         f();
       }
 
-      ;
-
       var observer = JS('', 'new self.MutationObserver(#)',
           convertDartClosureToJS(internalCallback, 1));
       JS('', '#.observe(#, { childList: true })', observer, div);
@@ -403,8 +401,8 @@
 ///
 /// If yielding while the subscription is paused it will become suspended. And
 /// only resume after the subscription is resumed or canceled.
-class _AsyncStarStreamController {
-  StreamController controller;
+class _AsyncStarStreamController<T> {
+  StreamController<T> controller;
   Stream get stream => controller.stream;
 
   /// True when the async* function has yielded while being paused.
@@ -424,7 +422,7 @@
 
   add(event) => controller.add(event);
 
-  addStream(Stream stream) {
+  addStream(Stream<T> stream) {
     return controller.addStream(stream, cancelOnError: false);
   }
 
@@ -439,7 +437,7 @@
       });
     }
 
-    controller = new StreamController(onListen: () {
+    controller = new StreamController<T>(onListen: () {
       _resumeBody();
     }, onResume: () {
       // Only schedule again if the async* function actually is suspended.
@@ -466,9 +464,9 @@
   }
 }
 
-_makeAsyncStarController(body) {
-  return new _AsyncStarStreamController(body);
-}
+//_makeAsyncStarController(body) {
+//  return new _AsyncStarStreamController(body);
+//}
 
 class _IterationMarker {
   static const YIELD_SINGLE = 0;
@@ -500,7 +498,7 @@
   toString() => "IterationMarker($state, $value)";
 }
 
-class _SyncStarIterator implements Iterator {
+class _SyncStarIterator<T> implements Iterator<T> {
   // _SyncStarIterator handles stepping a sync* generator body state machine.
   //
   // It also handles the stepping over 'nested' iterators to flatten yield*
@@ -515,9 +513,11 @@
   dynamic _body;
 
   // The current value, unless iterating a non-sync* nested iterator.
-  dynamic _current = null;
+  T _current = null;
 
   // This is the nested iterator when iterating a yield* of a non-sync iterator.
+  // TODO(32956): In strong-mode, yield* takes an Iterable<T> (possibly checked
+  // with an implicit downcast), so change type to Iterator<T>.
   Iterator _nestedIterator = null;
 
   // Stack of suspended state machines when iterating a yield* of a sync*
@@ -526,7 +526,10 @@
 
   _SyncStarIterator(this._body);
 
-  get current => _nestedIterator == null ? _current : _nestedIterator.current;
+  T get current {
+    if (_nestedIterator == null) return _current;
+    return _nestedIterator.current;
+  }
 
   _runBody() {
     // TODO(sra): Find a way to hard-wire SUCCESS and ERROR codes.
@@ -594,11 +597,20 @@
             continue;
           } else {
             _nestedIterator = inner;
+            // TODO(32956): Change to the following when strong-mode is the only
+            // option:
+            //
+            //     _nestedIterator = JS<Iterator<T>>('','#', inner);
             continue;
           }
         }
       } else {
-        _current = value;
+        // TODO(32956): Remove this test.
+        if (JS_GET_FLAG('STRONG_MODE')) {
+          _current = JS<T>('', '#', value);
+        } else {
+          _current = value;
+        }
         return true;
       }
     }
@@ -609,7 +621,7 @@
 /// An Iterable corresponding to a sync* method.
 ///
 /// Each invocation of a sync* method will return a new instance of this class.
-class _SyncStarIterable extends IterableBase {
+class _SyncStarIterable<T> extends IterableBase<T> {
   // This is a function that will return a helper function that does the
   // iteration of the sync*.
   //
@@ -618,7 +630,8 @@
 
   _SyncStarIterable(this._outerHelper);
 
-  Iterator get iterator => new _SyncStarIterator(JS('', '#()', _outerHelper));
+  Iterator<T> get iterator =>
+      new _SyncStarIterator<T>(JS('', '#()', _outerHelper));
 }
 
 @patch
diff --git a/sdk/lib/_internal/js_runtime/lib/js_rti.dart b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
index 5a18016..427a1b0 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
@@ -1030,11 +1030,9 @@
     var field = '${JS_GET_NAME(JsGetName.OPERATOR_AS_PREFIX)}${typeOfTString}';
     substitution = getField(typeOfSPrototype, field);
   }
-  // The class of [s] is a subclass of the class of [t].  If [s] has no type
-  // arguments and no substitution, it is used as raw type.  If [t] has no
-  // type arguments, it used as a raw type.  In both cases, [s] is a subtype
-  // of [t].
-  if ((!isJsArray(s) && substitution == null) || !isJsArray(t)) {
+  // The class of [s] is a subclass of the class of [t]. If [t] has no
+  // type arguments, it used as a raw type and [s] is a subtype of [t].
+  if (!isJsArray(t)) {
     return true;
   }
   // Recursively check the type arguments.
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index 8de4156..bcd1f22 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -148,12 +148,10 @@
  */
 abstract class Future<T> {
   /// A `Future<Null>` completed with `null`.
-  static final _Future<Null> _nullFuture =
-      new _Future<Null>.zoneValue(null, Zone.root);
+  static final _Future<Null> _nullFuture = new _Future<Null>.value(null);
 
   /// A `Future<bool>` completed with `false`.
-  static final _Future<bool> _falseFuture =
-      new _Future<bool>.zoneValue(false, Zone.root);
+  static final _Future<bool> _falseFuture = new _Future<bool>.value(false);
 
   /**
    * Creates a future containing the result of calling [computation]
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index 2b56f9d..6eeaa08 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -184,7 +184,7 @@
    * Until the future is completed, the field may hold the zone that
    * listener callbacks used to create this future should be run in.
    */
-  final Zone _zone;
+  final Zone _zone = Zone.current;
 
   /**
    * Either the result, a list of listeners or another future.
@@ -204,24 +204,20 @@
   var _resultOrListeners;
 
   // This constructor is used by async/await.
-  _Future() : _zone = Zone.current;
+  _Future();
 
-  _Future.immediate(FutureOr<T> result) : _zone = Zone.current {
+  _Future.immediate(FutureOr<T> result) {
     _asyncComplete(result);
   }
 
-  /** Creates a future with the value and the specified zone. */
-  _Future.zoneValue(T value, this._zone) {
-    _setValue(value);
-  }
-
-  _Future.immediateError(var error, [StackTrace stackTrace])
-      : _zone = Zone.current {
+  _Future.immediateError(var error, [StackTrace stackTrace]) {
     _asyncCompleteError(error, stackTrace);
   }
 
   /** Creates a future that is already completed with the value. */
-  _Future.value(T value) : this.zoneValue(value, Zone.current);
+  _Future.value(T value) {
+    _setValue(value);
+  }
 
   bool get _mayComplete => _state == _stateIncomplete;
   bool get _isPendingComplete => _state == _statePendingComplete;
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 971f9a5..b2b328e 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -6925,8 +6925,12 @@
 Language/Statements/Assert/execution_t03: RuntimeError # Please triage this failure
 Language/Statements/Assert/execution_t11: RuntimeError # Please triage this failure
 Language/Statements/Return/runtime_type_t04: RuntimeError # Issue 26584
+Language/Statements/Return/type_t03: RuntimeError # Would pass if FutureOr checked
+Language/Statements/Return/type_t04: RuntimeError # Would pass if FutureOr checked
 Language/Statements/Switch/execution_t01: Fail # Missing type check in switch expression
 Language/Statements/Switch/type_t01: RuntimeError # Issue 16089
+Language/Statements/Yield_and_Yield_Each/Yield/static_type_t01: RuntimeError
+Language/Statements/Yield_and_Yield_Each/Yield/static_type_t02: RuntimeError
 Language/Types/Dynamic_Type_System/malbounded_type_error_t01: RuntimeError # Issue 21088
 Language/Types/Parameterized_Types/malbounded_t06: RuntimeError # Issue 21088
 Language/Types/Static_Types/malformed_type_t01: RuntimeError # Issue 21089
@@ -7155,8 +7159,6 @@
 Language/Expressions/Function_Invocation/Unqualified_Invocation/instance_context_invocation_t04: Crash
 Language/Expressions/Method_Invocation/Super_Invocation/accessible_instance_member_t02: Crash
 Language/Expressions/Method_Invocation/Super_Invocation/evaluation_t05: Crash
-Language/Expressions/Method_Invocation/Super_Invocation/getter_lookup_failed_t03: Crash
-Language/Expressions/Method_Invocation/Super_Invocation/getter_lookup_failed_t04: Crash
 Language/Expressions/Method_Invocation/Super_Invocation/invocation_t02: Crash
 Language/Expressions/This/placement_t04: Crash
 Language/Functions/setter_modifier_t01: Crash
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index 582da56..5d636c5 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -110,6 +110,16 @@
 Language/Mixins/Mixin_Application/error_t02: MissingCompileTimeError
 
 [ $fasta && $strong ]
+Language/Classes/Abstract_Instance_Members/inherited_t01: CompileTimeError
+Language/Classes/Abstract_Instance_Members/inherited_t02: CompileTimeError
+Language/Classes/Abstract_Instance_Members/inherited_t03: CompileTimeError
+Language/Classes/Abstract_Instance_Members/inherited_t04: CompileTimeError
+Language/Classes/Abstract_Instance_Members/inherited_t05: CompileTimeError
+Language/Classes/Abstract_Instance_Members/inherited_t06: CompileTimeError
+Language/Classes/Abstract_Instance_Members/invocation_t01: CompileTimeError
+Language/Classes/Abstract_Instance_Members/invocation_t02: CompileTimeError
+Language/Classes/Abstract_Instance_Members/no_implementation_t01: CompileTimeError
+Language/Classes/Abstract_Instance_Members/override_default_value_t06: CompileTimeError
 Language/Classes/Abstract_Instance_Members/override_less_positional_parameters_t01: CompileTimeError
 Language/Classes/Abstract_Instance_Members/override_less_positional_parameters_t02: CompileTimeError
 Language/Classes/Abstract_Instance_Members/override_more_required_parameters_t01: CompileTimeError
@@ -185,6 +195,8 @@
 Language/Classes/Instance_Methods/override_subtype_t06: CompileTimeError
 Language/Classes/Instance_Variables/constant_t01: MissingCompileTimeError
 Language/Classes/Instance_Variables/definition_t03: CompileTimeError
+Language/Classes/Setters/name_t01: CompileTimeError
+Language/Classes/Setters/name_t05: CompileTimeError
 Language/Classes/Setters/override_t01: CompileTimeError
 Language/Classes/Setters/override_t03: CompileTimeError
 Language/Classes/Setters/same_name_getter_different_type_t02: CompileTimeError
@@ -194,15 +206,23 @@
 Language/Classes/Static_Methods/type_object_t01: CompileTimeError
 Language/Classes/Static_Methods/type_object_t02: CompileTimeError
 Language/Classes/Static_Variables/inheritance_t01: CompileTimeError
+Language/Classes/Superclasses/Inheritance_and_Overriding/abstract_method_t01/01: CompileTimeError
 Language/Classes/Superclasses/Inheritance_and_Overriding/inheritance_t03: CompileTimeError
 Language/Classes/Superclasses/Inheritance_and_Overriding/inheritance_t05: CompileTimeError
 Language/Classes/Superclasses/Inheritance_and_Overriding/inheritance_t06: CompileTimeError
 Language/Classes/Superclasses/wrong_superclass_t08: MissingCompileTimeError
 Language/Classes/Superinterfaces/implicit_interface_t01: CompileTimeError
 Language/Classes/Superinterfaces/implicit_interface_t02: CompileTimeError
+Language/Classes/Superinterfaces/no_member_t01: CompileTimeError
 Language/Classes/Superinterfaces/no_member_t02: CompileTimeError
+Language/Classes/Superinterfaces/no_member_t05: CompileTimeError
 Language/Classes/Superinterfaces/wrong_type_t05: MissingCompileTimeError
 Language/Classes/definition_t24: MissingCompileTimeError
+Language/Classes/method_definition_t03: CompileTimeError
+Language/Classes/method_definition_t04: CompileTimeError
+Language/Classes/method_definition_t05: CompileTimeError
+Language/Classes/same_name_instance_and_static_members_t02: Pass
+Language/Classes/same_name_instance_and_static_members_t04: Pass
 Language/Classes/same_name_type_variable_t04: MissingCompileTimeError
 Language/Classes/same_name_type_variable_t07: MissingCompileTimeError
 Language/Enums/declaration_equivalent_t03: CompileTimeError
@@ -498,6 +518,8 @@
 Language/Expressions/Identifier_Reference/undeclared_identifier_t08: CompileTimeError
 Language/Expressions/If_null_Expressions/static_type_t01: CompileTimeError
 Language/Expressions/If_null_Expressions/static_type_t02: CompileTimeError
+Language/Expressions/Instance_Creation/Const/abstract_class_t02: CompileTimeError
+Language/Expressions/Instance_Creation/Const/abstract_class_t04: CompileTimeError
 Language/Expressions/Instance_Creation/New/abstract_class_t01/01: CompileTimeError
 Language/Expressions/Instance_Creation/New/abstract_class_t02/01: CompileTimeError
 Language/Expressions/Instance_Creation/New/argument_static_type_t01: CompileTimeError
@@ -573,6 +595,7 @@
 Language/Expressions/Lookup/Getter_and_Setter_Lookup/definition_t03: CompileTimeError
 Language/Expressions/Lookup/Getter_and_Setter_Lookup/definition_t09: CompileTimeError
 Language/Expressions/Lookup/Getter_and_Setter_Lookup/definition_t10: CompileTimeError
+Language/Expressions/Lookup/Method_Lookup/method_lookup_t03: CompileTimeError
 Language/Expressions/Lookup/Method_Lookup/superclass_t07: CompileTimeError
 Language/Expressions/Lookup/Method_Lookup/superclass_t08: CompileTimeError
 Language/Expressions/Maps/key_value_equals_operator_t01: MissingCompileTimeError
@@ -929,9 +952,16 @@
 Language/Libraries_and_Scripts/private_access_t01: CompileTimeError
 Language/Libraries_and_Scripts/private_access_t03: CompileTimeError
 Language/Libraries_and_Scripts/private_access_t04: CompileTimeError
+Language/Mixins/Mixin_Application/abstract_t05: CompileTimeError
+Language/Mixins/Mixin_Application/abstract_t06: CompileTimeError
 Language/Mixins/Mixin_Application/abstract_t07: CompileTimeError
 Language/Mixins/Mixin_Application/abstract_t08: CompileTimeError
 Language/Mixins/Mixin_Application/deferred_t01: MissingCompileTimeError
+Language/Mixins/Mixin_Application/interfaces_t05: CompileTimeError
+Language/Mixins/Mixin_Application/superinterfaces_t01: CompileTimeError
+Language/Mixins/Mixin_Application/superinterfaces_t02: CompileTimeError
+Language/Mixins/Mixin_Application/superinterfaces_t06: CompileTimeError
+Language/Mixins/Mixin_Application/superinterfaces_t08: CompileTimeError
 Language/Mixins/Mixin_Application/syntax_t20: CompileTimeError
 Language/Mixins/declaring_constructor_t05: MissingCompileTimeError
 Language/Mixins/declaring_constructor_t06: MissingCompileTimeError
@@ -943,6 +973,7 @@
 Language/Overview/Privacy/private_and_public_t09: CompileTimeError
 Language/Overview/Privacy/private_and_public_t10: CompileTimeError
 Language/Overview/Privacy/private_and_public_t11: CompileTimeError
+Language/Overview/Privacy/private_and_public_t18: CompileTimeError
 Language/Overview/Privacy/private_and_public_t19: CompileTimeError
 Language/Overview/Privacy/private_and_public_t20: CompileTimeError
 Language/Overview/Scoping/hiding_declaration_t05: CompileTimeError
@@ -989,6 +1020,7 @@
 Language/Statements/For/Asynchronous_For_in/execution_t03: CompileTimeError
 Language/Statements/For/For_Loop/execution_t07: CompileTimeError
 Language/Statements/For/For_Loop/execution_t08: CompileTimeError
+Language/Statements/For/For_in/execution_t05: CompileTimeError
 Language/Statements/For/syntax_t07: CompileTimeError
 Language/Statements/If/condition_evaluation_t01: CompileTimeError
 Language/Statements/If/condition_evaluation_t02: CompileTimeError
@@ -1169,7 +1201,9 @@
 LibTest/collection/DoubleLinkedQueue/takeWhile_A02_t01: CompileTimeError
 LibTest/collection/HashMap/HashMap_class_A01_t01: CompileTimeError
 LibTest/collection/HashSet/HashSet_class_A01_t01: CompileTimeError
+LibTest/collection/IterableBase/IterableBase_class_A01_t01: CompileTimeError
 LibTest/collection/IterableBase/IterableBase_class_A01_t02: CompileTimeError
+LibTest/collection/IterableMixin/IterableMixin_class_A01_t01: CompileTimeError
 LibTest/collection/IterableMixin/IterableMixin_class_A02_t01: CompileTimeError
 LibTest/collection/LinkedHashMap/LinkedHashMap_A03_t01: CompileTimeError
 LibTest/collection/LinkedHashMap/LinkedHashMap_A04_t01: CompileTimeError
diff --git a/tests/compiler/dart2js/async_await/async_await_js_transform_test.dart b/tests/compiler/dart2js/async_await/async_await_js_transform_test.dart
index 31dda4f..adefec8 100644
--- a/tests/compiler/dart2js/async_await/async_await_js_transform_test.dart
+++ b/tests/compiler/dart2js/async_await/async_await_js_transform_test.dart
@@ -31,6 +31,7 @@
           asyncReturn: new VariableUse("returnHelper"),
           asyncRethrow: new VariableUse("rethrowHelper"),
           completerFactory: new VariableUse("NewCompleter"),
+          completerFactoryTypeArgument: new VariableUse("CompleterType"),
           wrapBody: new VariableUse("_wrapJsFunctionForAsync"),
           safeVariableName: (String name) => "__$name",
           bodyName: new StringBackedName("body")));
@@ -43,6 +44,7 @@
       new SyncStarRewriter(null, null,
           endOfIteration: new VariableUse("endOfIteration"),
           iterableFactory: new VariableUse("NewIterable"),
+          iterableFactoryTypeArgument: new VariableUse("IterableType"),
           yieldStarExpression: new VariableUse("yieldStar"),
           uncaughtErrorExpression: new VariableUse("uncaughtError"),
           safeVariableName: (String name) => "__$name",
@@ -64,7 +66,7 @@
 
           /// 01: ok
           r"""function() {
-  var __goto = 0, __completer = NewCompleter(), closures, v0, v1, v2, v3;
+  var __goto = 0, __completer = NewCompleter(CompleterType), closures, v0, v1, v2, v3;
   var body = _wrapJsFunctionForAsync(function(__errorCode, __result) {
     if (__errorCode === 1)
       return rethrowHelper(__result, __completer);
@@ -100,7 +102,7 @@
   await foo();
 }""", """
 function(a) {
-  var __goto = 0, __completer = NewCompleter(), __self = this;
+  var __goto = 0, __completer = NewCompleter(CompleterType), __self = this;
   var body = _wrapJsFunctionForAsync(function(__errorCode, __result) {
     if (__errorCode === 1)
       return rethrowHelper(__result, __completer);
@@ -145,7 +147,7 @@
     return 4;
   }""", """
 function(b) {
-  var __goto = 0, __completer = NewCompleter(), __returnValue, __handler = 2, __currentError, __next = [], __helper;
+  var __goto = 0, __completer = NewCompleter(CompleterType), __returnValue, __handler = 2, __currentError, __next = [], __helper;
   var body = _wrapJsFunctionForAsync(function(__errorCode, __result) {
     if (__errorCode === 1) {
       __currentError = __result;
@@ -255,7 +257,7 @@
   f = --foo1()[await foo2()];
 }""", """
 function(c) {
-  var __goto = 0, __completer = NewCompleter(), a, b, c, d, e, f, __temp1;
+  var __goto = 0, __completer = NewCompleter(CompleterType), a, b, c, d, e, f, __temp1;
   var body = _wrapJsFunctionForAsync(function(__errorCode, __result) {
     if (__errorCode === 1)
       return rethrowHelper(__result, __completer);
@@ -307,7 +309,7 @@
     h = foo1() && foo2();
   }""", """
 function(d2) {
-  var __goto = 0, __completer = NewCompleter(), a, b, c, d, e, f, g, h, __temp1;
+  var __goto = 0, __completer = NewCompleter(CompleterType), a, b, c, d, e, f, g, h, __temp1;
   var body = _wrapJsFunctionForAsync(function(__errorCode, __result) {
     if (__errorCode === 1)
       return rethrowHelper(__result, __completer);
@@ -439,7 +441,7 @@
   }
 }""", """
 function(x, y) {
-  var __goto = 0, __completer = NewCompleter();
+  var __goto = 0, __completer = NewCompleter(CompleterType);
   var body = _wrapJsFunctionForAsync(function(__errorCode, __result) {
     if (__errorCode === 1)
       return rethrowHelper(__result, __completer);
@@ -523,7 +525,7 @@
   }
   """, """
 function(f) {
-  var __goto = 0, __completer = NewCompleter(), a;
+  var __goto = 0, __completer = NewCompleter(CompleterType), a;
   var body = _wrapJsFunctionForAsync(function(__errorCode, __result) {
     if (__errorCode === 1)
       return rethrowHelper(__result, __completer);
@@ -583,7 +585,7 @@
 }
 """, """
 function(g) {
-  var __goto = 0, __completer = NewCompleter(), __returnValue, i, __temp1;
+  var __goto = 0, __completer = NewCompleter(CompleterType), __returnValue, i, __temp1;
   var body = _wrapJsFunctionForAsync(function(__errorCode, __result) {
     if (__errorCode === 1)
       return rethrowHelper(__result, __completer);
@@ -663,7 +665,7 @@
   }
   """, """
 function(a, h) {
-  var __goto = 0, __completer = NewCompleter(), x, __temp1, __temp2;
+  var __goto = 0, __completer = NewCompleter(CompleterType), x, __temp1, __temp2;
   var body = _wrapJsFunctionForAsync(function(__errorCode, __result) {
     if (__errorCode === 1)
       return rethrowHelper(__result, __completer);
@@ -739,7 +741,7 @@
 }
 """, """
 function(c, i) {
-  var __goto = 0, __completer = NewCompleter(), __handler = 1, __currentError, __next = [], x, y, __error, __error1;
+  var __goto = 0, __completer = NewCompleter(CompleterType), __handler = 1, __currentError, __next = [], x, y, __error, __error1;
   var body = _wrapJsFunctionForAsync(function(__errorCode, __result) {
     if (__errorCode === 1) {
       __currentError = __result;
@@ -849,7 +851,7 @@
   }
   """, """
 function(x, y, j) {
-  var __goto = 0, __completer = NewCompleter(), __temp1, __temp2, __temp3;
+  var __goto = 0, __completer = NewCompleter(CompleterType), __temp1, __temp2, __temp3;
   var body = _wrapJsFunctionForAsync(function(__errorCode, __result) {
     if (__errorCode === 1)
       return rethrowHelper(__result, __completer);
@@ -927,7 +929,7 @@
   }
 }""", """
 function(x, y, k) {
-  var __goto = 0, __completer = NewCompleter(), __returnValue, __temp1;
+  var __goto = 0, __completer = NewCompleter(CompleterType), __returnValue, __temp1;
   var body = _wrapJsFunctionForAsync(function(__errorCode, __result) {
     if (__errorCode === 1)
       return rethrowHelper(__result, __completer);
@@ -1050,7 +1052,7 @@
     }
   }""", """
 function(l) {
-  var __goto = 0, __completer = NewCompleter();
+  var __goto = 0, __completer = NewCompleter(CompleterType);
   var body = _wrapJsFunctionForAsync(function(__errorCode, __result) {
     if (__errorCode === 1)
       return rethrowHelper(__result, __completer);
@@ -1097,7 +1099,7 @@
     print(exception);
   }""", """
 function(m) {
-  var __goto = 0, __completer = NewCompleter(), __handler = 1, __currentError, __next = [], exception, __exception;
+  var __goto = 0, __completer = NewCompleter(CompleterType), __handler = 1, __currentError, __next = [], exception, __exception;
   var body = _wrapJsFunctionForAsync(function(__errorCode, __result) {
     if (__errorCode === 1) {
       __currentError = __result;
@@ -1189,6 +1191,6 @@
             return uncaughtError(__currentError);
         }
     };
-  });
+  }, IterableType);
 }""");
 }
diff --git a/tests/compiler/dart2js/closure/data/list_literal_strong_trust.dart b/tests/compiler/dart2js/closure/data/list_literal_strong_trust.dart
new file mode 100644
index 0000000..754fe55
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/list_literal_strong_trust.dart
@@ -0,0 +1,19 @@
+// 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:expect/expect.dart';
+
+@NoInline()
+method<T>() {
+  /*fields=[T],free=[T]*/ dynamic local() => <T>[];
+  return local;
+}
+
+@NoInline()
+test(o) => o is List<int>;
+
+main() {
+  Expect.isTrue(test(method<int>().call()));
+  Expect.isFalse(test(method<String>().call()));
+}
diff --git a/tests/compiler/dart2js/closure/data/list_literal_trust.dart b/tests/compiler/dart2js/closure/data/list_literal_trust.dart
new file mode 100644
index 0000000..433ef26
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/list_literal_trust.dart
@@ -0,0 +1,23 @@
+// 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:expect/expect.dart';
+
+/*element: A.:hasThis*/
+class A<T> {
+  /*element: A.method:hasThis*/
+  @NoInline()
+  method() {
+    /*fields=[this],free=[this],hasThis*/ dynamic local() => <T>[];
+    return local;
+  }
+}
+
+@NoInline()
+test(o) => o is List<int>;
+
+main() {
+  Expect.isTrue(test(new A<int>().method().call()));
+  Expect.isFalse(test(new A<String>().method().call()));
+}
diff --git a/tests/compiler/dart2js/closure/data/list_literal_untested_strong_trust.dart b/tests/compiler/dart2js/closure/data/list_literal_untested_strong_trust.dart
new file mode 100644
index 0000000..55e709a
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/list_literal_untested_strong_trust.dart
@@ -0,0 +1,20 @@
+// 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:expect/expect.dart';
+
+@NoInline()
+method<T>() {
+  /**/ dynamic local() => <T>[];
+  return local;
+}
+
+@NoInline()
+test(o) => o == null;
+
+main() {
+  Expect.isTrue(test(method<int>().call()));
+  Expect.isTrue(test(method<String>().call()));
+  Expect.isFalse(test(null));
+}
diff --git a/tests/compiler/dart2js/closure/data/list_literal_untested_trust.dart b/tests/compiler/dart2js/closure/data/list_literal_untested_trust.dart
new file mode 100644
index 0000000..92b057e
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/list_literal_untested_trust.dart
@@ -0,0 +1,24 @@
+// 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:expect/expect.dart';
+
+/*element: A.:hasThis*/
+class A<T> {
+  /*element: A.method:hasThis*/
+  @NoInline()
+  method() {
+    /*hasThis*/ dynamic local() => <T>[];
+    return local;
+  }
+}
+
+@NoInline()
+test(o) => o == null;
+
+main() {
+  Expect.isTrue(test(new A<int>().method().call()));
+  Expect.isTrue(test(new A<String>().method().call()));
+  Expect.isFalse(test(null));
+}
diff --git a/tests/compiler/dart2js/closure/data/map_literal_strong_trust.dart b/tests/compiler/dart2js/closure/data/map_literal_strong_trust.dart
new file mode 100644
index 0000000..0347de4
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/map_literal_strong_trust.dart
@@ -0,0 +1,19 @@
+// 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:expect/expect.dart';
+
+@NoInline()
+method<T>() {
+  /*fields=[T],free=[T]*/ dynamic local() => <T, int>{};
+  return local;
+}
+
+@NoInline()
+test(o) => o is Map<int, int>;
+
+main() {
+  Expect.isTrue(test(method<int>().call()));
+  Expect.isFalse(test(method<String>().call()));
+}
diff --git a/tests/compiler/dart2js/closure/data/map_literal_trust.dart b/tests/compiler/dart2js/closure/data/map_literal_trust.dart
new file mode 100644
index 0000000..08cfea6
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/map_literal_trust.dart
@@ -0,0 +1,23 @@
+// 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:expect/expect.dart';
+
+/*element: A.:hasThis*/
+class A<T> {
+  /*element: A.method:hasThis*/
+  @NoInline()
+  method() {
+    /*fields=[this],free=[this],hasThis*/ dynamic local() => <T, int>{};
+    return local;
+  }
+}
+
+@NoInline()
+test(o) => o is Map<int, int>;
+
+main() {
+  Expect.isTrue(test(new A<int>().method().call()));
+  Expect.isFalse(test(new A<String>().method().call()));
+}
diff --git a/tests/compiler/dart2js/closure/data/map_literal_untested_strong_trust.dart b/tests/compiler/dart2js/closure/data/map_literal_untested_strong_trust.dart
new file mode 100644
index 0000000..8793b90
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/map_literal_untested_strong_trust.dart
@@ -0,0 +1,20 @@
+// 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:expect/expect.dart';
+
+@NoInline()
+method<T>() {
+  /**/ dynamic local() => <T, int>{};
+  return local;
+}
+
+@NoInline()
+test(o) => o == null;
+
+main() {
+  Expect.isTrue(test(method<int>().call()));
+  Expect.isTrue(test(method<String>().call()));
+  Expect.isFalse(test(null));
+}
diff --git a/tests/compiler/dart2js/closure/data/map_literal_untested_trust.dart b/tests/compiler/dart2js/closure/data/map_literal_untested_trust.dart
new file mode 100644
index 0000000..958da83
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/map_literal_untested_trust.dart
@@ -0,0 +1,24 @@
+// 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:expect/expect.dart';
+
+/*element: A.:hasThis*/
+class A<T> {
+  /*element: A.method:hasThis*/
+  @NoInline()
+  method() {
+    /*hasThis*/ dynamic local() => <T, int>{};
+    return local;
+  }
+}
+
+@NoInline()
+test(o) => o == null;
+
+main() {
+  Expect.isTrue(test(new A<int>().method().call()));
+  Expect.isTrue(test(new A<String>().method().call()));
+  Expect.isFalse(test(null));
+}
diff --git a/tests/compiler/dart2js/closure/data/test_type.dart b/tests/compiler/dart2js/closure/data/test_type.dart
new file mode 100644
index 0000000..c74d190
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/test_type.dart
@@ -0,0 +1,53 @@
+// 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.
+
+////////////////////////////////////////////////////////////////////////////////
+/// Explicit is-test is always required.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class1.:hasThis*/
+class Class1<T> {
+  /*element: Class1.method1:hasThis*/
+  method1(dynamic o) {
+    /*fields=[o,this],free=[o,this],hasThis*/
+    dynamic local() => o is T;
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Explicit as-cast is always required.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class2.:hasThis*/
+class Class2<T> {
+  /*element: Class2.method2:hasThis*/
+  method2(dynamic o) {
+    /*fields=[o,this],free=[o,this],hasThis*/
+    dynamic local() => o as T;
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Implicit as-cast is only required in strong mode.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class3.:hasThis*/
+class Class3<T> {
+  /*element: Class3.method3:hasThis*/
+  method3(dynamic o) {
+    /*ast.fields=[o],free=[o],hasThis*/
+    /*kernel.fields=[o],free=[o],hasThis*/
+    /*strong.fields=[o,this],free=[o,this],hasThis*/
+    T local() => o;
+    return local;
+  }
+}
+
+main() {
+  new Class1<int>().method1(0).call();
+  new Class2<int>().method2(0).call();
+  new Class3<int>().method3(0).call();
+}
diff --git a/tests/compiler/dart2js/closure/data/test_type_strong.dart b/tests/compiler/dart2js/closure/data/test_type_strong.dart
new file mode 100644
index 0000000..93dcec0
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/test_type_strong.dart
@@ -0,0 +1,42 @@
+// 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.
+
+////////////////////////////////////////////////////////////////////////////////
+/// Explicit is-test is always required.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: method1:*/
+method1<T>(dynamic o) {
+  /*fields=[T,o],free=[T,o]*/
+  dynamic local() => o is T;
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Explicit as-cast is always required.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: method2:*/
+method2<T>(dynamic o) {
+  /*fields=[T,o],free=[T,o]*/
+  dynamic local() => o as T;
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Implicit as-cast is only required in strong mode.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: method3:*/
+method3<T>(dynamic o) {
+  /*fields=[T,o],free=[T,o]*/
+  T local() => o;
+  return local;
+}
+
+main() {
+  method1<int>(0).call();
+  method2<int>(0).call();
+  method3<int>(0).call();
+}
diff --git a/tests/compiler/dart2js/closure/data/test_type_strong_trust.dart b/tests/compiler/dart2js/closure/data/test_type_strong_trust.dart
new file mode 100644
index 0000000..abb909b
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/test_type_strong_trust.dart
@@ -0,0 +1,42 @@
+// 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.
+
+////////////////////////////////////////////////////////////////////////////////
+/// Explicit is-test is required even with --omit-implicit-checks.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: method1:*/
+method1<T>(dynamic o) {
+  /*fields=[T,o],free=[T,o]*/
+  dynamic local() => o is T;
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Explicit as-cast is required even with --omit-implicit-checks.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: method2:*/
+method2<T>(dynamic o) {
+  /*fields=[T,o],free=[T,o]*/
+  dynamic local() => o as T;
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Implicit as-cast is not required with --omit-implicit-checks.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: method3:*/
+method3<T>(dynamic o) {
+  /*fields=[o],free=[o]*/
+  T local() => o;
+  return local;
+}
+
+main() {
+  method1<int>(0).call();
+  method2<int>(0).call();
+  method3<int>(0).call();
+}
diff --git a/tests/compiler/dart2js/closure/data/test_type_trust.dart b/tests/compiler/dart2js/closure/data/test_type_trust.dart
new file mode 100644
index 0000000..7ed8dc1
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/test_type_trust.dart
@@ -0,0 +1,51 @@
+// 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.
+
+////////////////////////////////////////////////////////////////////////////////
+/// Explicit is-test is required even with --omit-implicit-checks.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class1.:hasThis*/
+class Class1<T> {
+  /*element: Class1.method1:hasThis*/
+  method1(dynamic o) {
+    /*fields=[o,this],free=[o,this],hasThis*/
+    dynamic local() => o is T;
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Explicit as-cast is required even with --omit-implicit-checks.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class2.:hasThis*/
+class Class2<T> {
+  /*element: Class2.method2:hasThis*/
+  method2(dynamic o) {
+    /*fields=[o,this],free=[o,this],hasThis*/
+    dynamic local() => o as T;
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Implicit as-cast is not required with --omit-implicit-checks.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class3.:hasThis*/
+class Class3<T> {
+  /*element: Class3.method3:hasThis*/
+  method3(dynamic o) {
+    /*fields=[o],free=[o],hasThis*/
+    T local() => o;
+    return local;
+  }
+}
+
+main() {
+  new Class1<int>().method1(0).call();
+  new Class2<int>().method2(0).call();
+  new Class3<int>().method3(0).call();
+}
diff --git a/tests/compiler/dart2js/closure/data/two_local_functions.dart b/tests/compiler/dart2js/closure/data/two_local_functions.dart
new file mode 100644
index 0000000..a7ecf9c
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/two_local_functions.dart
@@ -0,0 +1,9 @@
+// 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.
+
+main() {
+  /**/ local1() {}
+  /*fields=[local1],free=[local1]*/ local2() => local1();
+  return local2;
+}
diff --git a/tests/compiler/dart2js/closure/data/type_annotations.dart b/tests/compiler/dart2js/closure/data/type_annotations.dart
new file mode 100644
index 0000000..329252f
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/type_annotations.dart
@@ -0,0 +1,167 @@
+// 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.
+
+////////////////////////////////////////////////////////////////////////////////
+/// A sound initialization of a local variable doesn't capture the type
+/// variable.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class1.:hasThis*/
+class Class1<T> {
+  /*element: Class1.method1:hasThis*/
+  method1(T o) {
+    /*fields=[o],free=[o],hasThis*/
+    dynamic local() {
+      T t = o;
+      return t;
+    }
+
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A sound assignment to a local variable doesn't capture the type variable.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class1b.:hasThis*/
+class Class1b<T> {
+  /*element: Class1b.method1b:hasThis*/
+  method1b(T o) {
+    /*fields=[o],free=[o],hasThis*/
+    dynamic local() {
+      T t = null;
+      t = o;
+      return t;
+    }
+
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A local function parameter type is only captured in strong mode.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class2.:hasThis*/
+class Class2<T> {
+  /*element: Class2.method2:hasThis*/
+  method2() {
+    /*ast.hasThis*/
+    /*kernel.hasThis*/
+    /*strong.fields=[this],free=[this],hasThis*/
+    dynamic local(T t) => t;
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A local function return type is only captured in strong mode.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class3.:hasThis*/
+class Class3<T> {
+  /*element: Class3.method3:hasThis*/
+  method3(dynamic o) {
+    /*ast.fields=[o],free=[o],hasThis*/
+    /*kernel.fields=[o],free=[o],hasThis*/
+    /*strong.fields=[o,this],free=[o,this],hasThis*/
+    T local() => o;
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A member parameter type is not captured.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class4.:hasThis*/
+class Class4<T> {
+  /*element: Class4.method4:hasThis*/
+  method4(T o) {
+    /*fields=[o],free=[o],hasThis*/
+    dynamic local() => o;
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A member return type is not captured.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class5.:hasThis*/
+class Class5<T> {
+  /*element: Class5.method5:hasThis*/
+  T method5(dynamic o) {
+    /*fields=[o],free=[o],hasThis*/
+    dynamic local() => o;
+    return local();
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A local function parameter type is not captured by an inner local function.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class6.:hasThis*/
+class Class6<T> {
+  /*element: Class6.method6:hasThis*/
+  method6() {
+    /*ast.hasThis*/
+    /*kernel.hasThis*/
+    /*strong.fields=[this],free=[this],hasThis*/
+    dynamic local(T t) {
+      /*fields=[t],free=[t],hasThis*/
+      dynamic inner() => t;
+      return inner;
+    }
+
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A local function return type is not captured by an inner local function.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class7.:hasThis*/
+class Class7<T> {
+  /*element: Class7.method7:hasThis*/
+  method7(dynamic o) {
+    /*ast.fields=[o],free=[o],hasThis*/
+    /*kernel.fields=[o],free=[o],hasThis*/
+    /*strong.fields=[o,this],free=[o,this],hasThis*/
+    T local() {
+      /*fields=[o],free=[o],hasThis*/
+      dynamic inner() => o;
+      return inner();
+    }
+
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A field type is not captured.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class8.:hasThis*/
+class Class8<T> {
+  /*element: Class8.field8:hasThis*/
+  T field8 = /*hasThis*/ () {
+    return null;
+  }();
+}
+
+main() {
+  new Class1<int>().method1(0).call();
+  new Class1b<int>().method1b(0).call();
+  new Class2<int>().method2().call(0);
+  new Class3<int>().method3(0).call();
+  new Class4<int>().method4(0).call();
+  new Class5<int>().method5(0);
+  new Class6<int>().method6().call(0).call();
+  new Class7<int>().method7(0).call().call();
+  new Class8<int>().field8;
+}
diff --git a/tests/compiler/dart2js/closure/data/type_annotations_strong.dart b/tests/compiler/dart2js/closure/data/type_annotations_strong.dart
new file mode 100644
index 0000000..3b4c2a6
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/type_annotations_strong.dart
@@ -0,0 +1,97 @@
+// 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.
+
+////////////////////////////////////////////////////////////////////////////////
+/// A sound assignment to a local variable doesn't capture the type variable.
+////////////////////////////////////////////////////////////////////////////////
+
+method1<T>(T o) {
+  /*fields=[o],free=[o]*/
+  dynamic local() {
+    T t = o;
+    return t;
+  }
+
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A local function parameter type is captured in strong mode.
+////////////////////////////////////////////////////////////////////////////////
+
+method2<T>() {
+  /*fields=[T],free=[T]*/
+  dynamic local(T t) => t;
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A local function return type is captured in strong mode.
+////////////////////////////////////////////////////////////////////////////////
+
+method3<T>(dynamic o) {
+  /*fields=[T,o],free=[T,o]*/
+  T local() => o;
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A member parameter type is not captured.
+////////////////////////////////////////////////////////////////////////////////
+
+method4<T>(T o) {
+  /*fields=[o],free=[o]*/
+  dynamic local() => o;
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A member return type is not captured.
+////////////////////////////////////////////////////////////////////////////////
+
+T method5<T>(dynamic o) {
+  /*fields=[o],free=[o]*/
+  dynamic local() => o;
+  return local();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A local function parameter type is not captured by an inner local function.
+////////////////////////////////////////////////////////////////////////////////
+
+method6<T>() {
+  /*fields=[T],free=[T]*/
+  dynamic local(T t) {
+    /*fields=[t],free=[t]*/
+    dynamic inner() => t;
+    return inner;
+  }
+
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A local function return type is not captured by an inner local function.
+////////////////////////////////////////////////////////////////////////////////
+
+method7<T>(dynamic o) {
+  /*fields=[T,o],free=[T,o]*/
+  T local() {
+    /*fields=[o],free=[o]*/
+    dynamic inner() => o;
+    return inner();
+  }
+
+  return local;
+}
+
+main() {
+  method1<int>(0).call();
+  method2<int>().call(0);
+  method3<int>(0).call();
+  method4<int>(0).call();
+  method5<int>(0);
+  method6<int>().call(0).call();
+  method7<int>(0).call().call();
+}
diff --git a/tests/compiler/dart2js/closure/data/type_annotations_strong_trust.dart b/tests/compiler/dart2js/closure/data/type_annotations_strong_trust.dart
new file mode 100644
index 0000000..1ec0bf1
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/type_annotations_strong_trust.dart
@@ -0,0 +1,97 @@
+// 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.
+
+////////////////////////////////////////////////////////////////////////////////
+/// A sound assignment to a local variable doesn't capture the type variable.
+////////////////////////////////////////////////////////////////////////////////
+
+method1<T>(T o) {
+  /*fields=[o],free=[o]*/
+  dynamic local() {
+    T t = o;
+    return t;
+  }
+
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A local function parameter type is with --omit-type-checks.
+////////////////////////////////////////////////////////////////////////////////
+
+method2<T>() {
+  /**/
+  dynamic local(T t) => t;
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A local function return type is not captured with --omit-type-checks.
+////////////////////////////////////////////////////////////////////////////////
+
+method3<T>(dynamic o) {
+  /*fields=[o],free=[o]*/
+  T local() => o;
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A member parameter type is not captured.
+////////////////////////////////////////////////////////////////////////////////
+
+method4<T>(T o) {
+  /*fields=[o],free=[o]*/
+  dynamic local() => o;
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A member return type is not captured.
+////////////////////////////////////////////////////////////////////////////////
+
+T method5<T>(dynamic o) {
+  /*fields=[o],free=[o]*/
+  dynamic local() => o;
+  return local();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A local function parameter type is not captured by an inner local function.
+////////////////////////////////////////////////////////////////////////////////
+
+method6<T>() {
+  /**/
+  dynamic local(T t) {
+    /*fields=[t],free=[t]*/
+    dynamic inner() => t;
+    return inner;
+  }
+
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A local function return type is not captured by an inner local function.
+////////////////////////////////////////////////////////////////////////////////
+
+method7<T>(dynamic o) {
+  /*fields=[o],free=[o]*/
+  T local() {
+    /*fields=[o],free=[o]*/
+    dynamic inner() => o;
+    return inner();
+  }
+
+  return local;
+}
+
+main() {
+  method1<int>(0).call();
+  method2<int>().call(0);
+  method3<int>(0).call();
+  method4<int>(0).call();
+  method5<int>(0);
+  method6<int>().call(0).call();
+  method7<int>(0).call().call();
+}
diff --git a/tests/compiler/dart2js/closure/data/type_annotations_trust.dart b/tests/compiler/dart2js/closure/data/type_annotations_trust.dart
new file mode 100644
index 0000000..ff0ee55
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/type_annotations_trust.dart
@@ -0,0 +1,125 @@
+// 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.
+
+////////////////////////////////////////////////////////////////////////////////
+/// A sound assignment to a local variable doesn't capture the type variable.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class1.:hasThis*/
+class Class1<T> {
+  /*element: Class1.method1:hasThis*/
+  method1(T o) {
+    /*fields=[o],free=[o],hasThis*/
+    dynamic local() {
+      T t = o;
+      return t;
+    }
+
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A local function parameter type is with --omit-type-checks.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class2.:hasThis*/
+class Class2<T> {
+  /*element: Class2.method2:hasThis*/
+  method2() {
+    /*hasThis*/
+    dynamic local(T t) => t;
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A local function return type is not captured with --omit-type-checks.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class3.:hasThis*/
+class Class3<T> {
+  /*element: Class3.method3:hasThis*/
+  method3(dynamic o) {
+    /*fields=[o],free=[o],hasThis*/
+    T local() => o;
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A member parameter type is not captured.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class4.:hasThis*/
+class Class4<T> {
+  /*element: Class4.method4:hasThis*/
+  method4(T o) {
+    /*fields=[o],free=[o],hasThis*/
+    dynamic local() => o;
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A member return type is not captured.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class5.:hasThis*/
+class Class5<T> {
+  /*element: Class5.method5:hasThis*/
+  T method5(dynamic o) {
+    /*fields=[o],free=[o],hasThis*/
+    dynamic local() => o;
+    return local();
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A local function parameter type is not captured by an inner local function.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class6.:hasThis*/
+class Class6<T> {
+  /*element: Class6.method6:hasThis*/
+  method6() {
+    /*hasThis*/
+    dynamic local(T t) {
+      /*fields=[t],free=[t],hasThis*/
+      dynamic inner() => t;
+      return inner;
+    }
+
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A local function return type is not captured by an inner local function.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class7.:hasThis*/
+class Class7<T> {
+  /*element: Class7.method7:hasThis*/
+  method7(dynamic o) {
+    /*fields=[o],free=[o],hasThis*/
+    T local() {
+      /*fields=[o],free=[o],hasThis*/
+      dynamic inner() => o;
+      return inner();
+    }
+
+    return local;
+  }
+}
+
+main() {
+  new Class1<int>().method1(0).call();
+  new Class2<int>().method2().call(0);
+  new Class3<int>().method3(0).call();
+  new Class4<int>().method4(0).call();
+  new Class5<int>().method5(0);
+  new Class6<int>().method6().call(0).call();
+  new Class7<int>().method7(0).call().call();
+}
diff --git a/tests/compiler/dart2js/closure/data/type_arguments.dart b/tests/compiler/dart2js/closure/data/type_arguments.dart
new file mode 100644
index 0000000..8061663
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/type_arguments.dart
@@ -0,0 +1,44 @@
+// 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.
+
+////////////////////////////////////////////////////////////////////////////////
+/// A constructor invocation to a class that needs type arguments captures the
+/// type variables.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class1a.:hasThis*/
+class Class1a<T> {}
+
+/*element: Class1b.:hasThis*/
+class Class1b<T> {
+  /*element: Class1b.method1:hasThis*/
+  method1() {
+    /*fields=[this],free=[this],hasThis*/
+    dynamic local() => new Class1a<T>();
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A constructor invocation to a class that _doesn't_ needs type arguments does
+/// _not_ capture the type variables.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class2a.:hasThis*/
+class Class2a<T> {}
+
+/*element: Class2b.:hasThis*/
+class Class2b<T> {
+  /*element: Class2b.method2:hasThis*/
+  method2() {
+    /*hasThis*/
+    dynamic local() => new Class2a<T>();
+    return local;
+  }
+}
+
+main() {
+  new Class1b<int>().method1().call() is Class1a<int>;
+  new Class2b<int>().method2().call();
+}
diff --git a/tests/compiler/dart2js/closure/data/type_arguments_strong.dart b/tests/compiler/dart2js/closure/data/type_arguments_strong.dart
new file mode 100644
index 0000000..99733a8
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/type_arguments_strong.dart
@@ -0,0 +1,138 @@
+// 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.
+
+////////////////////////////////////////////////////////////////////////////////
+/// A constructor invocation for a class that needs type arguments captures the
+/// type variables.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class1a.:hasThis*/
+class Class1a<T> {}
+
+/*element: Class1b.:hasThis*/
+class Class1b<T> {
+  /*element: Class1b.method1:hasThis*/
+  method1() {
+    /*fields=[this],free=[this],hasThis*/
+    dynamic local() => new Class1a<T>();
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A constructor invocation for a class that _doesn't_ needs type arguments
+/// does _not_ capture the type variables.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class2a.:hasThis*/
+class Class2a<T> {}
+
+/*element: Class2b.:hasThis*/
+class Class2b<T> {
+  /*element: Class2b.method2:hasThis*/
+  method2() {
+    /*hasThis*/
+    dynamic local() => new Class2a<T>();
+    return local;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A static invocation of a method that needs type arguments captures the type
+/// variables.
+////////////////////////////////////////////////////////////////////////////////
+
+method3a<T>(o) => o is T;
+
+method3b<T>(o) {
+  /*fields=[T,o],free=[T,o]*/
+  dynamic local() => method3a<T>(o);
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// A static invocation of a method that _doesn't_ needs type arguments does
+/// _not_ capture the type variables.
+////////////////////////////////////////////////////////////////////////////////
+
+method4a<T>(o) => o;
+
+method4b<T>(o) {
+  /*fields=[o],free=[o]*/
+  dynamic local() => method4a<T>(o);
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// An instance member invocation of a method that needs type arguments captures
+/// the type variables.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class5a.:hasThis*/
+class Class5a {
+  /*element: Class5a.method5a:hasThis*/
+  method5a<T>(o) => o is T;
+}
+
+method5b<T>(o) {
+  /*fields=[T,o],free=[T,o]*/
+  dynamic local() => new Class5a().method5a<T>(o);
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// An instance member invocation of a method that _doesn't_ needs type
+/// arguments does _not_ capture the type variables.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: Class6a.:hasThis*/
+class Class6a {
+  /*element: Class6a.method6a:hasThis*/
+  method6a<T>(o) => o;
+}
+
+method6b<T>(o) {
+  /*fields=[o],free=[o]*/
+  dynamic local() => new Class6a().method6a<T>(o);
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// An invocation of a local function that needs type arguments captures the
+/// type variables.
+////////////////////////////////////////////////////////////////////////////////
+
+method7b<T>(o) {
+  /**/
+  method7a<S>(p) => p is S;
+
+  /*fields=[T,method7a,o],free=[T,method7a,o]*/
+  dynamic local() => method7a<T>(o);
+  return local;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// An invocation if a local function that _doesn't_ needs type arguments does
+/// _not_ capture the type variables.
+////////////////////////////////////////////////////////////////////////////////
+
+method8b<T>(o) {
+  /**/
+  method8a<S>(p) => p;
+
+  /*fields=[T,method8a,o],free=[T,method8a,o]*/
+  dynamic local() => method8a<T>(o);
+  return local;
+}
+
+main() {
+  new Class1b<int>().method1().call() is Class1a<int>;
+  new Class2b<int>().method2().call();
+  method3b<int>(0).call();
+  method4b<int>(0).call();
+  method5b<int>(0).call();
+  method6b<int>(0).call();
+  method7b<int>(0).call();
+  method8b<int>(0).call();
+}
diff --git a/tests/compiler/dart2js/codegen/jsarray_indexof_test.dart b/tests/compiler/dart2js/codegen/jsarray_indexof_test.dart
new file mode 100644
index 0000000..5d224e8
--- /dev/null
+++ b/tests/compiler/dart2js/codegen/jsarray_indexof_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that `length` access in JSArray.indexOf is encoding using `.length` and
+// not `.get$length()`.
+
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/elements/names.dart';
+import 'package:compiler/src/world.dart';
+import 'package:compiler/src/js_emitter/model.dart';
+import 'package:compiler/src/js/js.dart' as js;
+import 'package:compiler/src/universe/selector.dart';
+import 'package:expect/expect.dart';
+import '../memory_compiler.dart';
+import '../helpers/element_lookup.dart';
+import '../helpers/program_lookup.dart';
+
+const String source = '''
+import 'package:expect/expect.dart';
+
+@NoInline()
+test(o, a) => o.indexOf(a);
+main() {
+  test([1, 2, 3], 2);
+  test(['1', '2', '3'], '2');
+}
+''';
+
+main() {
+  asyncTest(() async {
+    print('--test from ast---------------------------------------------------');
+    await runTest([Flags.useOldFrontend]);
+    print('--test from ast (trust-type-annotations)--------------------------');
+    await runTest([Flags.useOldFrontend, Flags.trustTypeAnnotations]);
+    print('--test from kernel------------------------------------------------');
+    await runTest([]);
+    print('--test from kernel (trust-type-annotations)-----------------------');
+    await runTest([Flags.trustTypeAnnotations]);
+    print('--test from kernel (strong mode)----------------------------------');
+    await runTest([Flags.strongMode]);
+    print('--test from kernel (strong mode, omit-implicit.checks)------------');
+    await runTest([Flags.strongMode, Flags.omitImplicitChecks]);
+  });
+}
+
+runTest(List<String> options) async {
+  CompilationResult result = await runCompiler(
+      memorySourceFiles: {'main.dart': source}, options: options);
+  Expect.isTrue(result.isSuccess);
+  Compiler compiler = result.compiler;
+  ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+  MemberEntity jsArrayIndexOf =
+      findClassMember(closedWorld, 'JSArray', 'indexOf');
+  ProgramLookup programLookup = new ProgramLookup(result.compiler);
+
+  Selector getLengthSelector = new Selector.getter(const PublicName('length'));
+  js.Name getLengthName =
+      compiler.backend.namer.invocationName(getLengthSelector);
+
+  Method method = programLookup.getMethod(jsArrayIndexOf);
+  int lengthCount = 0;
+  forEachNode(method.code, onCall: (js.Call node) {
+    js.Node target = node.target;
+    Expect.isFalse(
+        target is js.PropertyAccess && target.selector == getLengthName,
+        "Unexpected .get\$length access ${js.nodeToString(node)} in\n"
+        "${js.nodeToString(method.code, pretty: true)}");
+  }, onPropertyAccess: (js.PropertyAccess node) {
+    js.Node selector = node.selector;
+    if (selector is js.LiteralString && selector.value == '"length"') {
+      lengthCount++;
+    }
+  });
+  Expect.equals(
+      2,
+      lengthCount,
+      "Unexpected .length access in\n"
+      "${js.nodeToString(method.code, pretty: true)}");
+}
diff --git a/tests/compiler/dart2js/codegen/negation_shift_regression_test.dart b/tests/compiler/dart2js/codegen/negation_shift_regression_test.dart
new file mode 100644
index 0000000..ec028c8
--- /dev/null
+++ b/tests/compiler/dart2js/codegen/negation_shift_regression_test.dart
@@ -0,0 +1,47 @@
+// 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:async_helper/async_helper.dart';
+import '../compiler_helper.dart';
+
+// A bug in UnaryNegateSpecializer left '-a' labelled as 'positive', allowing
+// misoptimization of '<<'.
+const String TEST1 = r"""
+foo(param) {
+  var a = param ? 0xFFFFFFFF : 1;
+  return 1 << -a;
+  // present: '$shl'
+  // absent: '_shlPositive'
+}
+""";
+
+const String TEST2 = r"""
+foo(param) {
+  var a = param ? 0xFFFFFFFF : 1;
+  return 1 << a;
+  // present: '_shlPositive'
+  // absent: '$shl'
+}
+""";
+
+main() {
+  runTests({bool useKernel}) async {
+    check(String test) async {
+      await compile(test,
+          entry: 'foo',
+          useKernel: useKernel,
+          check: checkerForAbsentPresent(test));
+    }
+
+    await check(TEST1);
+    await check(TEST2);
+  }
+
+  asyncTest(() async {
+    print('--test from ast---------------------------------------------------');
+    await runTests(useKernel: false);
+    print('--test from kernel------------------------------------------------');
+    await runTests(useKernel: true);
+  });
+}
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index d15d999..52efe99 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -5,6 +5,7 @@
 analyze_test: Slow, Pass
 async_await_syntax_test: Pass # DON'T CHANGE THIS LINE -- Don't mark these tests as failing. Instead, fix the errors/warnings that they report or update the whitelist in the test-files to temporarily allow digression.
 boolified_operator_test: Fail # Issue 8001
+closure/closure_test: Pass, Slow
 codegen/gvn_dynamic_field_get_test: Fail # Issue 18519
 codegen/load_elimination_test: Pass, Slow
 codegen/logical_expression_test: Fail # Issue 17027
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
index 1ab3749..02b0d5e 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
@@ -480,14 +480,17 @@
     bool trustTypeAnnotations = false;
     if (name.endsWith('_ea.dart')) {
       testOptions.add(Flags.enableAsserts);
-    } else if (name.endsWith('_strong.dart')) {
+    }
+    if (name.contains('_strong')) {
       strongModeOnlyTest = true;
       if (!testStrongMode) {
         testOptions.add(Flags.strongMode);
       }
-    } else if (name.endsWith('_checked.dart')) {
+    }
+    if (name.endsWith('_checked.dart')) {
       testOptions.add(Flags.enableCheckedMode);
-    } else if (name.endsWith('_trust.dart')) {
+    }
+    if (name.contains('_trust')) {
       trustTypeAnnotations = true;
     }
 
diff --git a/tests/compiler/dart2js/generic_methods/function_type_variable_test.dart b/tests/compiler/dart2js/generic_methods/function_type_variable_test.dart
index 5c22fee..0c4ed18 100644
--- a/tests/compiler/dart2js/generic_methods/function_type_variable_test.dart
+++ b/tests/compiler/dart2js/generic_methods/function_type_variable_test.dart
@@ -18,6 +18,8 @@
   const FunctionTypeData('void', 'F6', '<X extends int>(X x)'),
   const FunctionTypeData('void', 'F7', '<Y extends num>(Y y, [int i])'),
   const FunctionTypeData('Z', 'F8', '<Z extends num>(Z z)'),
+  const FunctionTypeData('T', 'F13', '<T>(T t1, T t2)'),
+  const FunctionTypeData('S', 'F14', '<S>(S s1, S s2)'),
 ];
 
 main() {
@@ -74,6 +76,10 @@
           env.isSubtype(a, b),
           "Expected `$a` ${isSubtype ? '' : 'not '}to be a subtype of `$b`, "
           "but it is${isSubtype ? ' not' : ''}.");
+      if (isSubtype) {
+        Expect.isTrue(env.isPotentialSubtype(a, b),
+            '$a <: $b but not a potential subtype.');
+      }
     }
 
     InterfaceType Object_ = env['Object'];
@@ -95,6 +101,8 @@
     FunctionType F10 = env.getClosureType('F10');
     FunctionType F11 = env.getMemberType('F11');
     FunctionType F12 = env.getMemberType('F12');
+    FunctionType F13 = env.getFieldType('F13');
+    FunctionType F14 = env.getFieldType('F14');
 
     List<FunctionType> all = <FunctionType>[
       F1,
@@ -109,6 +117,8 @@
       F10,
       F11,
       F12,
+      F13,
+      F14,
     ];
 
     testToString(F1, 'void Function<#A>(#A)');
@@ -123,6 +133,8 @@
     testToString(F10, 'void Function<#A extends #B,#B>(#A,#B)');
     testToString(F11, 'void Function<#A extends C3<#A>>(#A)');
     testToString(F12, 'void Function<#A extends C3<#A>>(#A)');
+    testToString(F13, '#A Function<#A>(#A,#A)');
+    testToString(F14, '#A Function<#A>(#A,#A)');
 
     testBounds(F1, [Object_]);
     testBounds(F2, [Object_]);
@@ -140,6 +152,8 @@
     testBounds(F12, [
       instantiate(C3, [F12.typeVariables.last])
     ]);
+    testBounds(F13, [Object_]);
+    testBounds(F14, [Object_]);
 
     testInstantiate(F1, [C1], 'void Function(C1)');
     testInstantiate(F2, [C2], 'void Function(C2)');
@@ -153,6 +167,8 @@
     testInstantiate(F10, [int_, num_], 'void Function(int,num)');
     testInstantiate(F11, [C4], 'void Function(C4)');
     testInstantiate(F12, [C4], 'void Function(C4)');
+    testInstantiate(F13, [C1], 'C1 Function(C1,C1)');
+    testInstantiate(F14, [C2], 'C2 Function(C2,C2)');
 
     Map<FunctionType, List<FunctionType>> expectedEquals =
         <FunctionType, List<FunctionType>>{
@@ -162,6 +178,8 @@
       F10: [F9],
       F11: [F12],
       F12: [F11],
+      F13: [F14],
+      F14: [F13],
     };
 
     Map<FunctionType, List<FunctionType>> expectedSubtype =
diff --git a/tests/compiler/dart2js/helpers/element_lookup.dart b/tests/compiler/dart2js/helpers/element_lookup.dart
index 670e45f..4ebe13a 100644
--- a/tests/compiler/dart2js/helpers/element_lookup.dart
+++ b/tests/compiler/dart2js/helpers/element_lookup.dart
@@ -13,6 +13,10 @@
       elementEnvironment.lookupClass(elementEnvironment.mainLibrary, name);
   cls ??= elementEnvironment.lookupClass(
       closedWorld.commonElements.coreLibrary, name);
+  cls ??= elementEnvironment.lookupClass(
+      closedWorld.commonElements.interceptorsLibrary, name);
+  cls ??= elementEnvironment.lookupClass(
+      closedWorld.commonElements.jsHelperLibrary, name);
   assert(cls != null, "Class '$name' not found.");
   return cls;
 }
diff --git a/tests/compiler/dart2js/helpers/program_lookup.dart b/tests/compiler/dart2js/helpers/program_lookup.dart
index b73b5fc..7ac0fed 100644
--- a/tests/compiler/dart2js/helpers/program_lookup.dart
+++ b/tests/compiler/dart2js/helpers/program_lookup.dart
@@ -6,6 +6,7 @@
 import 'package:compiler/src/common_elements.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/js_backend/namer.dart';
 import 'package:compiler/src/js_emitter/model.dart';
 import 'package:compiler/src/js/js.dart' as js;
 
@@ -31,9 +32,11 @@
 
 class ProgramLookup {
   final Program program;
+  final Namer namer;
 
   ProgramLookup(Compiler compiler)
-      : this.program = compiler.backend.emitter.emitter.programForTesting;
+      : this.program = compiler.backend.emitter.emitter.programForTesting,
+        this.namer = compiler.backend.namer;
 
   Map<LibraryEntity, LibraryData> libraryMap;
 
@@ -123,19 +126,29 @@
   }
 }
 
-void forEachCall(js.Node root, void f(js.Call node)) {
-  CallVisitor visitor = new CallVisitor(f);
+void forEachNode(js.Node root,
+    {void Function(js.Call) onCall,
+    void Function(js.PropertyAccess) onPropertyAccess}) {
+  CallbackVisitor visitor =
+      new CallbackVisitor(onCall: onCall, onPropertyAccess: onPropertyAccess);
   root.accept(visitor);
 }
 
-class CallVisitor extends js.BaseVisitor {
-  final void Function(js.Call) callback;
+class CallbackVisitor extends js.BaseVisitor {
+  final void Function(js.Call) onCall;
+  final void Function(js.PropertyAccess) onPropertyAccess;
 
-  CallVisitor(this.callback);
+  CallbackVisitor({this.onCall, this.onPropertyAccess});
 
   @override
   visitCall(js.Call node) {
-    callback(node);
+    if (onCall != null) onCall(node);
     super.visitCall(node);
   }
+
+  @override
+  visitAccess(js.PropertyAccess node) {
+    if (onPropertyAccess != null) onPropertyAccess(node);
+    super.visitAccess(node);
+  }
 }
diff --git a/tests/compiler/dart2js/inference/data/expose_this.dart b/tests/compiler/dart2js/inference/data/expose_this.dart
index 8bc8934..e888229 100644
--- a/tests/compiler/dart2js/inference/data/expose_this.dart
+++ b/tests/compiler/dart2js/inference/data/expose_this.dart
@@ -70,9 +70,6 @@
     this;
     /*update: [exact=Class3]*/ field = 42;
   }
-
-  /*element: Class3.method:[null]*/
-  method() {}
 }
 
 /*element: exposeThis3:[exact=Class3]*/
diff --git a/tests/compiler/dart2js/inference/data/expose_this_mask.dart b/tests/compiler/dart2js/inference/data/expose_this_mask.dart
index 1447e11..b1033c6 100644
--- a/tests/compiler/dart2js/inference/data/expose_this_mask.dart
+++ b/tests/compiler/dart2js/inference/data/expose_this_mask.dart
@@ -42,7 +42,7 @@
 
 /*element: otherGetter:[null]*/
 otherGetter() {
-  new OtherClass1();
+  new OtherClass1(). /*[exact=OtherClass1]*/ field1a;
   new Class1();
 }
 
@@ -70,7 +70,7 @@
 
 /*element: otherMethod:[null]*/
 otherMethod() {
-  new OtherClass2();
+  new OtherClass2(). /*[exact=OtherClass2]*/ field2a;
   new Class2();
 }
 
diff --git a/tests/compiler/dart2js/inference/inference_test_helper.dart b/tests/compiler/dart2js/inference/inference_test_helper.dart
index ed2bc4a..2b9c68f 100644
--- a/tests/compiler/dart2js/inference/inference_test_helper.dart
+++ b/tests/compiler/dart2js/inference/inference_test_helper.dart
@@ -48,7 +48,6 @@
     await checkTests(
         dataDir, computeMemberAstTypeMasks, computeMemberIrTypeMasks,
         libDirectory: new Directory.fromUri(Platform.script.resolve('libs')),
-        testStrongMode: true,
         forUserLibrariesOnly: true,
         args: args,
         options: [stopAfterTypeInference],
diff --git a/tests/compiler/dart2js/inference/side_effects/closure_call.dart b/tests/compiler/dart2js/inference/side_effects/closure_call.dart
index baa0e7c..7aaf687 100644
--- a/tests/compiler/dart2js/inference/side_effects/closure_call.dart
+++ b/tests/compiler/dart2js/inference/side_effects/closure_call.dart
@@ -2,8 +2,11 @@
 // 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.
 
+/*element: method:SideEffects(reads nothing; writes nothing)*/
+method() {}
+
 /*element: callExpression:SideEffects(reads anything; writes anything)*/
-callExpression() => (null)();
+callExpression() => (method)();
 
 /*element: Super.:SideEffects(reads nothing; writes nothing)*/
 class Super {
diff --git a/tests/compiler/dart2js/inference/side_effects_test.dart b/tests/compiler/dart2js/inference/side_effects_test.dart
index f0189f7..a92944e 100644
--- a/tests/compiler/dart2js/inference/side_effects_test.dart
+++ b/tests/compiler/dart2js/inference/side_effects_test.dart
@@ -26,8 +26,7 @@
         dataDir, computeMemberAstSideEffects, computeMemberIrSideEffects,
         args: args,
         options: [stopAfterTypeInference],
-        // TODO(johnniwinther): Run tests with strong mode.
-        testStrongMode: false);
+        skipForStrong: ['closure_call.dart']);
   });
 }
 
diff --git a/tests/compiler/dart2js/inlining/data/conditional.dart b/tests/compiler/dart2js/inlining/data/conditional.dart
index 5203943..2cb4977 100644
--- a/tests/compiler/dart2js/inlining/data/conditional.dart
+++ b/tests/compiler/dart2js/inlining/data/conditional.dart
@@ -22,7 +22,7 @@
 /*element: _method1:[_conditionalField]*/
 _method1() => 42;
 
-var _field1;
+bool _field1;
 
 /*element: _conditionalField:[]*/
 _conditionalField() {
@@ -49,7 +49,7 @@
 _method2() => 42;
 
 /*element: _conditionalParameter:[conditionalParameter]*/
-_conditionalParameter(o) {
+_conditionalParameter(bool o) {
   return o
       ? _method2() + _method2() + _method2()
       : _method2() + _method2() + _method2();
diff --git a/tests/compiler/dart2js/inlining/inlining_test.dart b/tests/compiler/dart2js/inlining/inlining_test.dart
index c14e939..36e7b3f 100644
--- a/tests/compiler/dart2js/inlining/inlining_test.dart
+++ b/tests/compiler/dart2js/inlining/inlining_test.dart
@@ -28,10 +28,7 @@
     Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
     await checkTests(
         dataDir, computeMemberAstInlinings, computeMemberIrInlinings,
-        args: args,
-        skipForAst: ['external.dart'],
-        // TODO(johnniwinther): Run tests with strong mode.
-        testStrongMode: false);
+        args: args, skipForAst: ['external.dart']);
   });
 }
 
diff --git a/tests/compiler/dart2js/jumps/data/complex_loops.dart b/tests/compiler/dart2js/jumps/data/complex_loops.dart
new file mode 100644
index 0000000..5495006
--- /dev/null
+++ b/tests/compiler/dart2js/jumps/data/complex_loops.dart
@@ -0,0 +1,101 @@
+// 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.
+
+simpleForInLoopWithContinue(list) {
+  /*0@continue*/ for (int i in list) {
+    if (i % 2 == 0) /*target=0*/ continue;
+    print(i);
+  }
+}
+
+complexForInLoopWithContinueLookalike1(list) {
+  for (int i in list) {
+    label:
+    /*0@break*/
+    {
+      if (i % 2 == 0) /*target=0*/ break label;
+      print(i);
+    }
+    print(i);
+  }
+}
+
+complexForInLoopWithContinueLookalike2(list) {
+  /*kernel.0@continue*/
+  /*strong.0@continue*/
+  for (int i in list) {
+    label:
+    /*ast.0@break*/
+    {
+      if (i % 2 == 0) /*target=0*/ break label;
+      print(i);
+    }
+  }
+}
+
+labelledBreakInNestedWhileLoop(bool condition()) {
+  int i = 111;
+  /*0@break*/ while (condition()) {
+    label:
+    /*1@break*/ {
+      while (condition()) {
+        /*target=1*/ break label;
+      }
+      i--;
+    }
+    /*target=0*/ break;
+  }
+  return i;
+}
+
+nestedLoopsWithInnerBreak(list) {
+  for (int i in list) {
+    /*0@break*/ for (int j in list) {
+      if (i % j == 0) /*target=0*/ break;
+      print(i);
+    }
+  }
+}
+
+nestedLoopsWithInnerContinue(list) {
+  for (int i in list) {
+    /*0@continue*/ for (int j in list) {
+      if (i % j == 0) /*target=0*/ continue;
+      print(i);
+    }
+  }
+}
+
+nestedLoopsWithLabelledBreak(list) {
+  outer:
+  /*0@break*/
+  for (int i in list) {
+    for (int j in list) {
+      if (i % j == 0) /*target=0*/ break outer;
+      print(i);
+    }
+  }
+}
+
+nestedLoopsWithLabelledContinue(list) {
+  outer:
+  /*0@continue*/
+  for (int i in list) {
+    for (int j in list) {
+      if (i % j == 0) /*target=0*/ continue outer;
+      print(i);
+    }
+  }
+}
+
+main() {
+  simpleForInLoopWithContinue([1, 2, 3, 4]);
+  complexForInLoopWithContinueLookalike1([1, 2, 3, 4]);
+  complexForInLoopWithContinueLookalike2([1, 2, 3, 4]);
+  labelledBreakInNestedWhileLoop(() => true);
+  nestedLoopsWithInnerBreak([1, 2, 3, 4]);
+  nestedLoopsWithInnerContinue([1, 2, 3, 4]);
+  nestedLoopsWithLabelledBreak([1, 2, 3, 4]);
+  nestedLoopsWithLabelledContinue([1, 2, 3, 4]);
+}
diff --git a/tests/compiler/dart2js/jumps/jump_test.dart b/tests/compiler/dart2js/jumps/jump_test.dart
index 2a911b4..b18da0e 100644
--- a/tests/compiler/dart2js/jumps/jump_test.dart
+++ b/tests/compiler/dart2js/jumps/jump_test.dart
@@ -24,9 +24,7 @@
     Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
     await checkTests(dataDir, computeJumpsData, computeKernelJumpsData,
         options: [Flags.disableTypeInference, stopAfterTypeInference],
-        args: args,
-        // TODO(johnniwinther): Run tests with strong mode.
-        testStrongMode: false);
+        args: args);
   });
 }
 
diff --git a/tests/compiler/dart2js/model/constant_expression_test.dart b/tests/compiler/dart2js/model/constant_expression_test.dart
index 44a1406..6babb67 100644
--- a/tests/compiler/dart2js/model/constant_expression_test.dart
+++ b/tests/compiler/dart2js/model/constant_expression_test.dart
@@ -57,7 +57,9 @@
     const ConstantData('1 + 2', ConstantExpressionKind.BINARY),
     const ConstantData('1 == 2', ConstantExpressionKind.BINARY),
     // TODO(sigmund): reenable (Issue 32511)
-    // const ConstantData('1 != 2', ConstantExpressionKind.BINARY),
+    const ConstantData('1 != 2', ConstantExpressionKind.UNARY,
+        // a != b is encoded as !(a == b) by CFE.
+        text: '!(1 == 2)'),
     const ConstantData('1 ?? 2', ConstantExpressionKind.BINARY),
     const ConstantData('-(1)', ConstantExpressionKind.UNARY, text: '-1'),
     const ConstantData('"foo".length', ConstantExpressionKind.STRING_LENGTH),
@@ -156,34 +158,44 @@
         'const A<int>(field1: 87)', ConstantExpressionKind.CONSTRUCTED,
         type: 'A<int>', fields: const {'field(A#field1)': '87'}),
     // TODO(sigmund): reenable (Issue 32511)
-    //const ConstantData('const B()', ConstantExpressionKind.CONSTRUCTED,
-    //    type: 'A<B<dynamic>>',
-    //    fields: const {
-    //      'field(A#field1)': '42',
-    //    }),
-    //const ConstantData('const B<int>()', ConstantExpressionKind.CONSTRUCTED,
-    //    type: 'A<B<int>>',
-    //    fields: const {
-    //      'field(A#field1)': '42',
-    //    }),
-    //const ConstantData(
-    //    'const B<int>(field1: 87)', ConstantExpressionKind.CONSTRUCTED,
-    //    type: 'A<B<int>>',
-    //    fields: const {
-    //      'field(A#field1)': '87',
-    //    }),
-    //const ConstantData(
-    //    'const C<int>(field1: 87)', ConstantExpressionKind.CONSTRUCTED,
-    //    type: 'A<B<double>>',
-    //    fields: const {
-    //      'field(A#field1)': '87',
-    //    }),
-    //const ConstantData(
-    //    'const B<int>.named()', ConstantExpressionKind.CONSTRUCTED,
-    //    type: 'A<int>',
-    //    fields: const {
-    //      'field(A#field1)': '42',
-    //    }),
+    const ConstantData('const B()', ConstantExpressionKind.CONSTRUCTED,
+        type: 'A<B<dynamic>>',
+        fields: const {
+          'field(A#field1)': '42',
+        },
+        // Redirecting factories are replaced by their effective targets by CFE.
+        text: 'const A<B<dynamic>>()'),
+    const ConstantData('const B<int>()', ConstantExpressionKind.CONSTRUCTED,
+        type: 'A<B<int>>',
+        fields: const {
+          'field(A#field1)': '42',
+        },
+        // Redirecting factories are replaced by their effective targets by CFE.
+        text: 'const A<B<int>>()'),
+    const ConstantData(
+        'const B<int>(field1: 87)', ConstantExpressionKind.CONSTRUCTED,
+        type: 'A<B<int>>',
+        fields: const {
+          'field(A#field1)': '87',
+        },
+        // Redirecting factories are replaced by their effective targets by CFE.
+        text: 'const A<B<int>>(field1: 87)'),
+    const ConstantData(
+        'const C<int>(field1: 87)', ConstantExpressionKind.CONSTRUCTED,
+        type: 'A<B<double>>',
+        fields: const {
+          'field(A#field1)': '87',
+        },
+        // Redirecting factories are replaced by their effective targets by CFE.
+        text: 'const A<B<double>>(field1: 87)'),
+    const ConstantData(
+        'const B<int>.named()', ConstantExpressionKind.CONSTRUCTED,
+        type: 'A<int>',
+        fields: const {
+          'field(A#field1)': '42',
+        },
+        // Redirecting factories are replaced by their effective targets by CFE.
+        text: 'const A<int>()'),
   ]),
 ];
 
diff --git a/tests/compiler/dart2js/model/enqueuer_test.dart b/tests/compiler/dart2js/model/enqueuer_test.dart
new file mode 100644
index 0000000..567a11f
--- /dev/null
+++ b/tests/compiler/dart2js/model/enqueuer_test.dart
@@ -0,0 +1,291 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that the enqueuers are not dependent upon in which order impacts are
+// applied.
+
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/common_elements.dart';
+import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/elements/names.dart';
+import 'package:compiler/src/elements/types.dart';
+import 'package:compiler/src/enqueue.dart';
+import 'package:compiler/src/types/types.dart';
+import 'package:compiler/src/universe/call_structure.dart';
+import 'package:compiler/src/universe/selector.dart';
+import 'package:compiler/src/universe/world_impact.dart';
+import 'package:compiler/src/universe/use.dart';
+import 'package:compiler/src/universe/world_builder.dart';
+import 'package:compiler/src/world.dart';
+import 'package:expect/expect.dart';
+import '../memory_compiler.dart';
+
+class Test {
+  final String name;
+  final String code;
+  final List<Impact> impacts;
+  final Map<String, List<String>> expectedLiveMap;
+
+  const Test({this.name, this.code, this.impacts, this.expectedLiveMap});
+
+  Map<String, List<String>> get expectedLiveResolutionMap {
+    Map<String, List<String>> map = {};
+    expectedLiveMap.forEach((String clsName, List<String> memberNames) {
+      for (String memberName in memberNames) {
+        if (memberName.startsWith('?')) {
+          memberName = memberName.substring(1);
+        }
+        map.putIfAbsent(clsName, () => []).add(memberName);
+      }
+    });
+    return map;
+  }
+
+  Map<String, List<String>> get expectedLiveCodegenMap {
+    Map<String, List<String>> map = {};
+    expectedLiveMap.forEach((String clsName, List<String> memberNames) {
+      for (String memberName in memberNames) {
+        if (memberName.startsWith('?')) {
+          // Skip for codegen
+          continue;
+        }
+        map.putIfAbsent(clsName, () => []).add(memberName);
+      }
+    });
+    return map;
+  }
+}
+
+enum ImpactKind { instantiate, invoke }
+
+class Impact {
+  final ImpactKind kind;
+  final String clsName;
+  final String memberName;
+
+  const Impact.instantiate(this.clsName, [this.memberName = ''])
+      : this.kind = ImpactKind.instantiate;
+  const Impact.invoke(this.clsName, this.memberName)
+      : this.kind = ImpactKind.invoke;
+
+  String toString() =>
+      'Impact(kind=$kind,clsName=$clsName,memberName=$memberName)';
+}
+
+const List<Test> tests = const <Test>[
+  const Test(name: 'Instantiate class', code: '''
+class A {
+  void method() {}
+}
+''', impacts: const [
+    const Impact.instantiate('A'),
+    const Impact.invoke('A', 'method'),
+  ], expectedLiveMap: const {
+    'A': const ['', 'method'],
+  }),
+  const Test(name: 'Instantiate subclass', code: '''
+class A {
+  void method() {}
+}
+class B extends A {
+}
+''', impacts: const [
+    const Impact.instantiate('B'),
+    const Impact.invoke('B', 'method'),
+  ], expectedLiveMap: const {
+    'A': const ['?', 'method'],
+    'B': const [''],
+  }),
+  const Test(name: 'Instantiate superclass/subclass', code: '''
+class A {
+  void method() {}
+}
+class B extends A {
+}
+''', impacts: const [
+    const Impact.instantiate('A'),
+    const Impact.instantiate('B'),
+    const Impact.invoke('B', 'method'),
+  ], expectedLiveMap: const {
+    'A': const ['', 'method'],
+    'B': const [''],
+  }),
+];
+
+main() {
+  asyncTest(() async {
+    for (Test test in tests) {
+      await runTest(test);
+    }
+  });
+}
+
+runTest(Test test) async {
+  print('====================================================================');
+  print('Running test ${test.name}');
+  for (List<Impact> permutation in permutations(test.impacts)) {
+    print('------------------------------------------------------------------');
+    print('Permutation: $permutation');
+    await runTestPermutation(test, permutation);
+  }
+}
+
+Iterable<List<Impact>> permutations(List<Impact> impacts) sync* {
+  int length = impacts.length;
+  if (length <= 1) {
+    yield impacts;
+  } else {
+    for (int index = 0; index < length; index++) {
+      Impact head = impacts[index];
+      List<Impact> tail = new List<Impact>.from(impacts)..removeAt(index);
+      for (List<Impact> permutation in permutations(tail)) {
+        yield [head]..addAll(permutation);
+      }
+    }
+  }
+}
+
+runTestPermutation(Test test, List<Impact> impacts) async {
+  Compiler compiler = compilerFor(memorySourceFiles: {
+    'main.dart': '''
+${test.code}
+main() {}
+'''
+  }, options: [
+    Flags.strongMode,
+    Flags.disableInlining,
+  ]);
+
+  void checkInvariant(
+      Enqueuer enqueuer, ElementEnvironment elementEnvironment) {
+    for (MemberEntity member
+        in compiler.enqueuer.resolution.processedEntities) {
+      Expect.isTrue(
+          member == elementEnvironment.mainFunction ||
+              member.library != elementEnvironment.mainLibrary,
+          "Unexpected member $member in ${enqueuer}.");
+    }
+  }
+
+  void instantiate(
+      Enqueuer enqueuer, ElementEnvironment elementEnvironment, String name) {
+    ClassEntity cls =
+        elementEnvironment.lookupClass(elementEnvironment.mainLibrary, name);
+    ConstructorEntity constructor =
+        elementEnvironment.lookupConstructor(cls, '');
+    InterfaceType type = elementEnvironment.getRawType(cls);
+    WorldImpact impact = new WorldImpactBuilderImpl()
+      ..registerStaticUse(new StaticUse.typedConstructorInvoke(
+          constructor, constructor.parameterStructure.callStructure, type));
+    enqueuer.applyImpact(impact);
+  }
+
+  void invoke(
+      Enqueuer enqueuer,
+      ElementEnvironment elementEnvironment,
+      String className,
+      String methodName,
+      ReceiverConstraint Function(ClassEntity cls) createConstraint) {
+    ClassEntity cls = elementEnvironment.lookupClass(
+        elementEnvironment.mainLibrary, className);
+    Selector selector = new Selector.call(
+        new Name(methodName, elementEnvironment.mainLibrary),
+        CallStructure.NO_ARGS);
+    WorldImpact impact = new WorldImpactBuilderImpl()
+      ..registerDynamicUse(new ConstrainedDynamicUse(
+          selector, createConstraint(cls), const <DartType>[]));
+    enqueuer.applyImpact(impact);
+  }
+
+  void applyImpact(
+      Enqueuer enqueuer,
+      ElementEnvironment elementEnvironment,
+      Impact impact,
+      ReceiverConstraint Function(ClassEntity cls) createConstraint) {
+    switch (impact.kind) {
+      case ImpactKind.instantiate:
+        instantiate(enqueuer, elementEnvironment, impact.clsName);
+        break;
+      case ImpactKind.invoke:
+        invoke(enqueuer, elementEnvironment, impact.clsName, impact.memberName,
+            createConstraint);
+        break;
+    }
+  }
+
+  void checkLiveMembers(
+      Enqueuer enqueuer,
+      ElementEnvironment elementEnvironment,
+      Map<String, List<String>> expectedLiveMap) {
+    Map<String, List<String>> actualLiveMap = {};
+    for (MemberEntity member in enqueuer.processedEntities) {
+      if (member != elementEnvironment.mainFunction &&
+          member.library == elementEnvironment.mainLibrary) {
+        actualLiveMap
+            .putIfAbsent(member.enclosingClass.name, () => [])
+            .add(member.name);
+      }
+    }
+
+    Expect.setEquals(
+        expectedLiveMap.keys,
+        actualLiveMap.keys,
+        "Unexpected live classes in $enqueuer\n "
+        "Expected: ${expectedLiveMap.keys}\n "
+        "Actual  : ${actualLiveMap.keys}");
+    expectedLiveMap.forEach((String clsName, List<String> expectedMembers) {
+      List<String> actualMembers = actualLiveMap[clsName];
+      Expect.setEquals(
+          expectedMembers,
+          actualMembers,
+          "Unexpected live members for $clsName in $enqueuer\n "
+          "Expected: $expectedMembers\n "
+          "Actual  : $actualMembers");
+    });
+  }
+
+  compiler.onResolutionQueueEmptyForTesting = () {
+    Enqueuer enqueuer = compiler.enqueuer.resolution;
+    ElementEnvironment elementEnvironment =
+        compiler.frontendStrategy.elementEnvironment;
+    checkInvariant(enqueuer, elementEnvironment);
+
+    ReceiverConstraint createConstraint(ClassEntity cls) {
+      return new StrongModeConstraint(cls);
+    }
+
+    for (Impact impact in impacts) {
+      applyImpact(enqueuer, elementEnvironment, impact, createConstraint);
+    }
+  };
+  compiler.onCodegenQueueEmptyForTesting = () {
+    Enqueuer enqueuer = compiler.enqueuer.codegenEnqueuerForTesting;
+    ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+    ElementEnvironment elementEnvironment =
+        compiler.backendClosedWorldForTesting.elementEnvironment;
+    checkInvariant(enqueuer, elementEnvironment);
+
+    ReceiverConstraint createConstraint(ClassEntity cls) {
+      return new TypeMask.subtype(cls, closedWorld);
+    }
+
+    for (Impact impact in impacts) {
+      applyImpact(enqueuer, elementEnvironment, impact, createConstraint);
+    }
+  };
+
+  await compiler.run(Uri.parse('memory:main.dart'));
+
+  checkLiveMembers(
+      compiler.enqueuer.resolution,
+      compiler.frontendStrategy.elementEnvironment,
+      test.expectedLiveResolutionMap);
+
+  checkLiveMembers(
+      compiler.enqueuer.codegenEnqueuerForTesting,
+      compiler.backendClosedWorldForTesting.elementEnvironment,
+      test.expectedLiveCodegenMap);
+}
diff --git a/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart b/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
new file mode 100644
index 0000000..fa652b4
--- /dev/null
+++ b/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
@@ -0,0 +1,194 @@
+// 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:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/common_elements.dart';
+import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/universe/world_builder.dart';
+import 'package:compiler/src/world.dart';
+import '../memory_compiler.dart';
+
+main() {
+  useStrongModeWorldStrategy = true;
+  asyncTest(() async {
+    print('--test from non-strong mode---------------------------------------');
+    await runTest(strongMode: false);
+    print('--test from strong mode-------------------------------------------');
+    await runTest(strongMode: true);
+  });
+}
+
+runTest({bool strongMode}) async {
+  CompilationResult result = await runCompiler(memorySourceFiles: {
+    'main.dart': '''
+class A {
+  method1() {}
+  method2() {}
+  get getter => 42;
+  set setter(_) {}
+}
+
+class B {
+  method1() {}
+  method2() {}
+  get getter => 42;
+  set setter(_) {}
+}
+
+class C extends A {
+  method1() {}
+  method2() {}
+  get getter => 42;
+  set setter(_) {}
+}
+
+class D implements B {
+  method1() {}
+  method2() {}
+  get getter => 42;
+  set setter(_) {}
+}
+
+class E implements A {
+  method1() {}
+  method2() {}
+  get getter => 42;
+  set setter(_) {}
+}
+
+class F extends B {
+  method1() {}
+  method2() {}
+  get getter => 42;
+  set setter(_) {}
+}
+
+class G {
+  method1() {}
+  method2() {}
+  get getter => 42;
+  set setter(_) {}
+}
+
+class H extends Object with G implements A {}
+
+class I {
+  method1() {}
+  method2() {}
+  get getter => 42;
+  set setter(_) {}
+}
+
+class J extends I implements A {}
+
+class K {
+  method1() {}
+  method2() {}
+  get getter => 42;
+  set setter(_) {}
+}
+
+class L = Object with K;
+class L2 = Object with L;
+class M extends L {}
+class M2 extends L2 {}
+
+class N {
+  method1() {}
+  get getter => 42;
+  set setter(_) {}
+}
+
+abstract class O extends N {}
+
+class P implements O {
+  method1() {}
+  get getter => 42;
+  set setter(_) {}
+}
+
+class Q {
+  method3() {}
+}
+
+class R extends Q {}
+
+main() {
+  A a = new A();
+  B b = new B();
+  a.method1();
+  a.getter;
+  b.method2();
+  b.setter = 42; 
+  new C();
+  new D();
+  new H();
+  new J();
+  new M().method1();
+  new M2().getter;
+  new N();
+  O o = new P();
+  o.method1(); 
+  o.getter;
+  o.setter = 42;
+  R r;
+  r.method3();
+  r = new R(); // Create R after call.
+}
+'''
+  }, options: strongMode ? [Flags.strongMode] : []);
+  Expect.isTrue(result.isSuccess);
+  Compiler compiler = result.compiler;
+
+  Map<String, List<String>> expectedLiveMembersMap = <String, List<String>>{
+    'A': strongMode
+        ? ['method1', 'getter']
+        : ['method1', 'method2', 'getter', 'setter'],
+    'B': strongMode
+        ? ['method2', 'setter']
+        : ['method1', 'method2', 'getter', 'setter'],
+    'C': strongMode
+        ? ['method1', 'getter']
+        : ['method1', 'method2', 'getter', 'setter'],
+    'D': strongMode
+        ? ['method2', 'setter']
+        : ['method1', 'method2', 'getter', 'setter'],
+    'G': strongMode
+        ? ['method1', 'getter']
+        : ['method1', 'method2', 'getter', 'setter'],
+    'I': strongMode
+        ? ['method1', 'getter']
+        : ['method1', 'method2', 'getter', 'setter'],
+    'K': strongMode
+        ? ['method1', 'getter']
+        : ['method1', 'method2', 'getter', 'setter'],
+    'N': strongMode ? [] : ['method1', 'getter', 'setter'],
+    'P': ['method1', 'getter', 'setter'],
+    'Q': ['method3'],
+  };
+
+  ClosedWorld closedWorld =
+      compiler.resolutionWorldBuilder.closedWorldForTesting;
+  ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
+
+  elementEnvironment.forEachClass(elementEnvironment.mainLibrary,
+      (ClassEntity cls) {
+    List<String> expectedLiveMembers =
+        expectedLiveMembersMap[cls.name] ?? const <String>[];
+    elementEnvironment.forEachLocalClassMember(cls, (MemberEntity member) {
+      if (member.enclosingClass != cls) return;
+      bool expected = expectedLiveMembers.contains(member.name);
+      bool live = closedWorld.processedMembers.contains(member);
+      Expect.equals(
+          expected,
+          live,
+          "Member $member ${expected ? '' : 'not '}expected to be live "
+          "in ${strongMode ? 'Dart 2' : 'Dart 1'}. "
+          "Expected members for ${cls.name}: $expectedLiveMembers");
+    });
+  });
+}
diff --git a/tests/compiler/dart2js/model/subtype_test.dart b/tests/compiler/dart2js/model/subtype_test.dart
index d54572c..48445e3 100644
--- a/tests/compiler/dart2js/model/subtype_test.dart
+++ b/tests/compiler/dart2js/model/subtype_test.dart
@@ -42,6 +42,10 @@
   if (expectMoreSpecific == null) expectMoreSpecific = expectSubtype;
   Expect.equals(expectSubtype, env.isSubtype(subtype, supertype),
       '$subtype <: $supertype');
+  if (expectSubtype) {
+    Expect.isTrue(env.isPotentialSubtype(subtype, supertype),
+        '$subtype <: $supertype (potential)');
+  }
   if (env.types is Types) {
     Expect.equals(expectMoreSpecific, env.isMoreSpecific(subtype, supertype),
         '$subtype << $supertype');
@@ -828,6 +832,9 @@
       options: strongMode ? [Flags.strongMode] : []).then((env) {
     void expect(bool expectSubtype, DartType T, DartType S) {
       Expect.equals(expectSubtype, env.isSubtype(T, S), '$T <: $S');
+      if (expectSubtype) {
+        Expect.isTrue(env.isPotentialSubtype(T, S), '$T <: $S (potential)');
+      }
     }
 
     InterfaceType ClassWithCall = env['ClassWithCall'];
diff --git a/tests/compiler/dart2js/model/subtypeset_test.dart b/tests/compiler/dart2js/model/subtypeset_test.dart
index 10cef63..cbaf315 100644
--- a/tests/compiler/dart2js/model/subtypeset_test.dart
+++ b/tests/compiler/dart2js/model/subtypeset_test.dart
@@ -42,8 +42,8 @@
       class E extends C implements B {}
       class F extends C {}
       class G extends C {}
-      class H implements C {}
-      class I implements H {}
+      abstract class H implements C {}
+      abstract class I implements H {}
       """,
       mainSource: r"""
       main() {
diff --git a/tests/compiler/dart2js/rti/data/closure_generic_unneeded_strong.dart b/tests/compiler/dart2js/rti/data/closure_generic_unneeded_strong.dart
index b3b1ef3..5e985bd 100644
--- a/tests/compiler/dart2js/rti/data/closure_generic_unneeded_strong.dart
+++ b/tests/compiler/dart2js/rti/data/closure_generic_unneeded_strong.dart
@@ -4,11 +4,11 @@
 
 import 'package:expect/expect.dart';
 
-/*class: A:needsArgs*/
+/*class: A:*/
 class A<T> {
   @NoInline()
   m() {
-    return /*needsSignature*/ (T t, String s) {};
+    return /**/ (T t, String s) {};
   }
 }
 
diff --git a/tests/compiler/dart2js/rti/data/closure_unneeded.dart b/tests/compiler/dart2js/rti/data/closure_unneeded.dart
index 5ba4637..5e985bd 100644
--- a/tests/compiler/dart2js/rti/data/closure_unneeded.dart
+++ b/tests/compiler/dart2js/rti/data/closure_unneeded.dart
@@ -4,14 +4,11 @@
 
 import 'package:expect/expect.dart';
 
-/*ast.class: A:*/
-/*kernel.class: A:*/
-/*strong.class: A:needsArgs*/
+/*class: A:*/
 class A<T> {
   @NoInline()
   m() {
-    // TODO(johnniwinther): Optimize local function type signature need.
-    return /*ast.*/ /*kernel.*/ /*strong.needsSignature*/ (T t, String s) {};
+    return /**/ (T t, String s) {};
   }
 }
 
diff --git a/tests/compiler/dart2js/rti/data/closure_unneeded_strong.dart b/tests/compiler/dart2js/rti/data/closure_unneeded_strong.dart
index 34d26df..ad98d37 100644
--- a/tests/compiler/dart2js/rti/data/closure_unneeded_strong.dart
+++ b/tests/compiler/dart2js/rti/data/closure_unneeded_strong.dart
@@ -8,7 +8,7 @@
 class A<T> {
   @NoInline()
   m() {
-    return /*needsSignature*/ (int i, String s) {};
+    return /**/ (int i, String s) {};
   }
 }
 
diff --git a/tests/compiler/dart2js/rti/data/local_function_generic_strong.dart b/tests/compiler/dart2js/rti/data/local_function_generic_strong.dart
new file mode 100644
index 0000000..71a9566
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/local_function_generic_strong.dart
@@ -0,0 +1,18 @@
+// 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:expect/expect.dart';
+
+method1() {
+  /*needsSignature*/
+  T local<T>(T t) => t;
+  return local;
+}
+
+@NoInline()
+test(o) => o is S Function<S>(S);
+
+main() {
+  Expect.isTrue(test(method1()));
+}
diff --git a/tests/compiler/dart2js/rti/data/local_function_list_literal_strong.dart b/tests/compiler/dart2js/rti/data/local_function_list_literal_strong.dart
new file mode 100644
index 0000000..40f4aa7
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/local_function_list_literal_strong.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+/*class: global#JSArray:deps=[EmptyIterable,List,ListIterable,SubListIterable],explicit=[JSArray],needsArgs*/
+
+/*element: method:needsArgs*/
+@NoInline()
+method<T>() {
+  return () => <T>[];
+}
+
+@NoInline()
+test(o) => o is List<int>;
+
+main() {
+  Expect.isTrue(test(method<int>().call()));
+  Expect.isFalse(test(method<String>().call()));
+}
diff --git a/tests/compiler/dart2js/rti/data/local_function_map_literal_strong.dart b/tests/compiler/dart2js/rti/data/local_function_map_literal_strong.dart
new file mode 100644
index 0000000..d0d805a
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/local_function_map_literal_strong.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+/*class: global#LinkedHashMap:deps=[Map],needsArgs*/
+
+/*element: method:needsArgs*/
+@NoInline()
+method<T>() {
+  return () => <T, int>{};
+}
+
+@NoInline()
+test(o) => o is Map<int, int>;
+
+main() {
+  Expect.isTrue(test(method<int>().call()));
+  Expect.isFalse(test(method<String>().call()));
+}
diff --git a/tests/compiler/dart2js/rti/data/local_function_signature2_strong.dart b/tests/compiler/dart2js/rti/data/local_function_signature2_strong.dart
new file mode 100644
index 0000000..a5dd390c
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/local_function_signature2_strong.dart
@@ -0,0 +1,109 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+class Class1 {
+  method1() {
+    /**/
+    num local<T>(num n) => null;
+    return local;
+  }
+
+  method2() {
+    /**/
+    num local<T>(int n) => null;
+    return local;
+  }
+
+  method3() {
+    /**/
+    int local<T>(num n) => null;
+    return local;
+  }
+}
+
+class Class2 {
+  /*element: Class2.method4:needsArgs,selectors=[Selector(call, method4, arity=0, types=1)]*/
+  method4<T>() {
+    /*needsSignature*/
+    num local(T n) => null;
+    return local;
+  }
+}
+
+class Class3 {
+  /*element: Class3.method5:needsArgs,selectors=[Selector(call, method5, arity=0, types=1)]*/
+  method5<T>() {
+    /*needsSignature*/
+    T local(num n) => null;
+    return local;
+  }
+}
+
+class Class4 {
+  /*element: Class4.method6:*/
+  method6<T>() {
+    /**/
+    num local(num n, T t) => null;
+    return local;
+  }
+}
+
+/*element: method7:needsArgs*/
+method7<T>() {
+  /*needsSignature*/
+  num local(T n) => null;
+  return local;
+}
+
+/*element: method8:needsArgs*/
+method8<T>() {
+  /*needsSignature*/
+  T local(num n) => null;
+  return local;
+}
+
+/*element: method9:*/
+method9<T>() {
+  /**/
+  num local(num n, T t) => null;
+  return local;
+}
+
+method10() {
+  /**/
+  num local<T>(T n) => null;
+  return local;
+}
+
+method11() {
+  /**/
+  T local<T>(num n) => null;
+  return local;
+}
+
+method12() {
+  /**/
+  num local<T>(num n, T t) => null;
+  return local;
+}
+
+@NoInline()
+test(o) => o is num Function(num);
+
+main() {
+  Expect.isFalse(test(new Class1().method1()));
+  Expect.isFalse(test(new Class1().method2()));
+  Expect.isFalse(test(new Class1().method3()));
+  Expect.isTrue(test(new Class2().method4<num>()));
+  Expect.isTrue(test(new Class3().method5<num>()));
+  Expect.isFalse(test(new Class4().method6<num>()));
+  Expect.isTrue(test(method7<num>()));
+  Expect.isTrue(test(method8<num>()));
+  Expect.isFalse(test(method9()));
+  Expect.isFalse(test(method10()));
+  Expect.isFalse(test(method11()));
+  Expect.isFalse(test(method12()));
+}
diff --git a/tests/compiler/dart2js/rti/data/local_function_signatures.dart b/tests/compiler/dart2js/rti/data/local_function_signatures.dart
new file mode 100644
index 0000000..cc7bc3d
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/local_function_signatures.dart
@@ -0,0 +1,64 @@
+// 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:expect/expect.dart';
+
+class Class1 {
+  method1() {
+    /*ast.*/
+    /*kernel.*/
+    /*strong.needsSignature*/
+    num local(num n) => null;
+    return local;
+  }
+
+  method2() {
+    num local(int n) => null;
+    return local;
+  }
+
+  method3() {
+    Object local(num n) => null;
+    return local;
+  }
+}
+
+/*class: Class2:needsArgs*/
+class Class2<T> {
+  method4() {
+    /*needsSignature*/
+    num local(T n) => null;
+    return local;
+  }
+}
+
+/*class: Class3:needsArgs*/
+class Class3<T> {
+  method5() {
+    /*needsSignature*/
+    T local(num n) => null;
+    return local;
+  }
+}
+
+/*class: Class4:*/
+class Class4<T> {
+  method6() {
+    /**/
+    num local(num n, T t) => null;
+    return local;
+  }
+}
+
+@NoInline()
+test(o) => o is num Function(num);
+
+main() {
+  Expect.isTrue(test(new Class1().method1()));
+  Expect.isFalse(test(new Class1().method2()));
+  Expect.isFalse(test(new Class1().method3()));
+  Expect.isTrue(test(new Class2<num>().method4()));
+  Expect.isTrue(test(new Class3<num>().method5()));
+  Expect.isFalse(test(new Class4<num>().method6()));
+}
diff --git a/tests/compiler/dart2js/rti/data/local_function_signatures_strong.dart b/tests/compiler/dart2js/rti/data/local_function_signatures_strong.dart
new file mode 100644
index 0000000..71f5374
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/local_function_signatures_strong.dart
@@ -0,0 +1,130 @@
+// 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:expect/expect.dart';
+
+class Class1 {
+  method1() {
+    /*needsSignature*/
+    num local<T>(num n) => null;
+    return local;
+  }
+
+  method2() {
+    /**/
+    num local<T>(int n) => null;
+    return local;
+  }
+
+  method3() {
+    /*needsSignature*/
+    int local<T>(num n) => null;
+    return local;
+  }
+}
+
+class Class2 {
+  /*element: Class2.method4:needsArgs,selectors=[Selector(call, method4, arity=0, types=1)]*/
+  method4<T>() {
+    /*needsSignature*/
+    num local(T n) => null;
+    return local;
+  }
+}
+
+class Class3 {
+  /*element: Class3.method5:needsArgs,selectors=[Selector(call, method5, arity=0, types=1)]*/
+  method5<T>() {
+    /*needsSignature*/
+    T local(num n) => null;
+    return local;
+  }
+}
+
+class Class4 {
+  /*element: Class4.method6:*/
+  method6<T>() {
+    /**/
+    num local(num n, T t) => null;
+    return local;
+  }
+}
+
+/*element: method7:needsArgs*/
+method7<T>() {
+  /*needsSignature*/
+  num local(T n) => null;
+  return local;
+}
+
+/*element: method8:needsArgs*/
+method8<T>() {
+  /*needsSignature*/
+  T local(num n) => null;
+  return local;
+}
+
+/*element: method9:*/
+method9<T>() {
+  /**/
+  num local(num n, T t) => null;
+  return local;
+}
+
+method10() {
+  /*needsSignature*/
+  num local<T>(T n) => null;
+  return local;
+}
+
+method11() {
+  /*needsSignature*/
+  T local<T>(num n) => null;
+  return local;
+}
+
+method12() {
+  /**/
+  num local<T>(num n, T t) => null;
+  return local;
+}
+
+num Function(num) method13() {
+  /*needsSignature*/
+  num local<T>(num n) => null;
+  return local;
+}
+
+num Function(num) method14() {
+  /*needsSignature*/
+  num local<T>(T n) => null;
+  return local;
+}
+
+num Function(num) method15() {
+  /*needsSignature*/
+  T local<T>(num n) => null;
+  return local;
+}
+
+@NoInline()
+test(o) => o is num Function(num);
+
+main() {
+  Expect.isFalse(test(new Class1().method1()));
+  Expect.isFalse(test(new Class1().method2()));
+  Expect.isFalse(test(new Class1().method3()));
+  Expect.isTrue(test(new Class2().method4<num>()));
+  Expect.isTrue(test(new Class3().method5<num>()));
+  Expect.isFalse(test(new Class4().method6<num>()));
+  Expect.isTrue(test(method7<num>()));
+  Expect.isTrue(test(method8<num>()));
+  Expect.isFalse(test(method9()));
+  Expect.isFalse(test(method10()));
+  Expect.isFalse(test(method11()));
+  Expect.isFalse(test(method12()));
+  Expect.isTrue(test(method13()));
+  Expect.isTrue(test(method14()));
+  Expect.isTrue(test(method15()));
+}
diff --git a/tests/compiler/dart2js/rti/data/method_signatures.dart b/tests/compiler/dart2js/rti/data/method_signatures.dart
new file mode 100644
index 0000000..4c4a161
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/method_signatures.dart
@@ -0,0 +1,58 @@
+// 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:expect/expect.dart';
+
+class Class1 {
+  /*element: Class1.method1:*/
+  num method1(num n) => null;
+
+  /*element: Class1.method2:*/
+  num method2(int n) => null;
+
+  /*element: Class1.method3:*/
+  Object method3(num n) => null;
+}
+
+/*class: Class2:needsArgs*/
+class Class2<T> {
+  /*element: Class2.method4:needsSignature*/
+  num method4(T n) => null;
+}
+
+/*class: Class3:needsArgs*/
+class Class3<T> {
+  /*element: Class3.method5:needsSignature*/
+  T method5(num n) => null;
+}
+
+/*class: Class4:*/
+class Class4<T> {
+  /*element: Class4.method6:*/
+  num method6(num n, T t) => null;
+}
+
+/*element: method7:*/
+num method7(num n) => null;
+
+/*element: method8:*/
+num method8(int n) => null;
+
+/*element: method9:*/
+Object method9(num n) => null;
+
+@NoInline()
+test(o) => o is num Function(num);
+
+main() {
+  Expect.isTrue(test(new Class1().method1));
+  Expect.isFalse(test(new Class1().method2));
+  Expect.isFalse(test(new Class1().method3));
+  Expect.isTrue(test(new Class2<num>().method4));
+  Expect.isTrue(test(new Class3<num>().method5));
+  Expect.isFalse(test(new Class4<num>().method6));
+  Expect.isTrue(test(method7));
+  Expect.isFalse(test(method8));
+  Expect.isFalse(test(method9));
+}
diff --git a/tests/compiler/dart2js/rti/data/method_signatures_strong.dart b/tests/compiler/dart2js/rti/data/method_signatures_strong.dart
new file mode 100644
index 0000000..811548f
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/method_signatures_strong.dart
@@ -0,0 +1,57 @@
+// 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:expect/expect.dart';
+
+class Class1 {
+  /*element: Class1.method1:*/
+  num method1<T>(num n) => null;
+
+  /*element: Class1.method2:*/
+  num method2<T>(int n) => null;
+
+  /*element: Class1.method3:*/
+  int method3<T>(num n) => null;
+}
+
+class Class2 {
+  /*element: Class2.method4:*/
+  num method4<T>(T n) => null;
+}
+
+class Class3 {
+  /*element: Class3.method5:*/
+  T method5<T>(num n) => null;
+}
+
+class Class4 {
+  /*element: Class4.method6:*/
+  num method6<T>(num n, T t) => null;
+}
+
+/*element: method7:*/
+num method7<T>(T n) => null;
+
+/*element: method8:*/
+T method8<T>(num n) => null;
+
+/*element: method9:*/
+num method9<T>(num n, T t) => null;
+
+@NoInline()
+test(o) => o is num Function(num);
+
+forceInstantiation(num Function(num) f) => f;
+
+main() {
+  Expect.isFalse(test(new Class1().method1));
+  Expect.isFalse(test(new Class1().method2));
+  Expect.isFalse(test(new Class1().method3));
+  Expect.isTrue(test(forceInstantiation(new Class2().method4)));
+  Expect.isTrue(test(forceInstantiation(new Class3().method5)));
+  Expect.isFalse(test(new Class4().method6));
+  Expect.isTrue(test(forceInstantiation(method7)));
+  Expect.isTrue(test(forceInstantiation(method8)));
+  Expect.isFalse(test(method9));
+}
diff --git a/tests/compiler/dart2js/rti/emission/closure_function.dart b/tests/compiler/dart2js/rti/emission/closure_function.dart
index 2b51d64..099dee0 100644
--- a/tests/compiler/dart2js/rti/emission/closure_function.dart
+++ b/tests/compiler/dart2js/rti/emission/closure_function.dart
@@ -8,6 +8,9 @@
 test(o) => o is Function;
 
 main() {
-  test(/*checks=[],functionType,instance*/ () {});
+  test(
+      /*ast.checks=[],functionType,instance*/
+      /*kernel.checks=[],functionType,instance*/
+      /*strong.checks=[],instance*/ () {});
   test(null);
 }
diff --git a/tests/compiler/dart2js/rti/emission/closure_signature_unneeded.dart b/tests/compiler/dart2js/rti/emission/closure_signature_unneeded.dart
index c205496..ac72186 100644
--- a/tests/compiler/dart2js/rti/emission/closure_signature_unneeded.dart
+++ b/tests/compiler/dart2js/rti/emission/closure_signature_unneeded.dart
@@ -10,7 +10,11 @@
   m() {
     // TODO(johnniwinther): The signature is not needed since the type isn't a
     // potential subtype of the checked function types.
-    return /*checks=[$signature],instance*/ (T t, String s) {};
+    return
+        /*ast.checks=[$signature],instance*/
+        /*kernel.checks=[$signature],instance*/
+        /*strong.checks=[],instance*/
+        (T t, String s) {};
   }
 }
 
diff --git a/tests/compiler/dart2js/rti/emission/local_function_list_literal_strong.dart b/tests/compiler/dart2js/rti/emission/local_function_list_literal_strong.dart
new file mode 100644
index 0000000..f3ac8a5
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/local_function_list_literal_strong.dart
@@ -0,0 +1,20 @@
+// 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:expect/expect.dart';
+
+/*class: global#JSArray:checkedInstance,checks=[$isIterable,$isList],instance*/
+
+@NoInline()
+method<T>() {
+  return /*checks=[],instance*/ () => <T>[];
+}
+
+@NoInline()
+test(o) => o is List<int>;
+
+main() {
+  Expect.isTrue(test(method<int>().call()));
+  Expect.isFalse(test(method<String>().call()));
+}
diff --git a/tests/compiler/dart2js/rti/emission/local_function_map_literal_strong.dart b/tests/compiler/dart2js/rti/emission/local_function_map_literal_strong.dart
new file mode 100644
index 0000000..fefa55b
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/local_function_map_literal_strong.dart
@@ -0,0 +1,22 @@
+// 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:expect/expect.dart';
+
+/*class: global#JsLinkedHashMap:checks=[],instance*/
+
+@NoInline()
+method<T>() {
+  return
+      /*checks=[],instance*/
+      () => <T, int>{};
+}
+
+@NoInline()
+test(o) => o is Map<int, int>;
+
+main() {
+  Expect.isTrue(test(method<int>().call()));
+  Expect.isFalse(test(method<String>().call()));
+}
diff --git a/tests/compiler/dart2js/rti/factory_call_test.dart b/tests/compiler/dart2js/rti/factory_call_test.dart
index d3632ae..9d3f08f 100644
--- a/tests/compiler/dart2js/rti/factory_call_test.dart
+++ b/tests/compiler/dart2js/rti/factory_call_test.dart
@@ -83,7 +83,7 @@
 
       js.Name selector = getName(targetName);
       bool callFound = false;
-      forEachCall(fun, (js.Call node) {
+      forEachNode(fun, onCall: (js.Call node) {
         js.Expression target = node.target;
         if (target is js.PropertyAccess && target.selector == selector) {
           callFound = true;
diff --git a/tests/compiler/dart2js/rti/instance_call_test.dart b/tests/compiler/dart2js/rti/instance_call_test.dart
index 1b656ed..337bae0 100644
--- a/tests/compiler/dart2js/rti/instance_call_test.dart
+++ b/tests/compiler/dart2js/rti/instance_call_test.dart
@@ -152,7 +152,7 @@
 
       js.Name selector = getName(targetName, expectedTypeArguments);
       bool callFound = false;
-      forEachCall(fun, (js.Call node) {
+      forEachNode(fun, onCall: (js.Call node) {
         js.Expression target = node.target;
         if (target is js.PropertyAccess && target.selector == selector) {
           callFound = true;
diff --git a/tests/compiler/dart2js/type_test_helper.dart b/tests/compiler/dart2js/type_test_helper.dart
index ee2a76a..95e82a0 100644
--- a/tests/compiler/dart2js/type_test_helper.dart
+++ b/tests/compiler/dart2js/type_test_helper.dart
@@ -263,6 +263,10 @@
     return types.isSubtype(T, S);
   }
 
+  bool isPotentialSubtype(DartType T, DartType S) {
+    return types.isPotentialSubtype(T, S);
+  }
+
   bool isMoreSpecific(ResolutionDartType T, ResolutionDartType S) {
     return (types as Types).isMoreSpecific(T, S);
   }
diff --git a/tests/compiler/dart2js_extra/32928_test.dart b/tests/compiler/dart2js_extra/32928_test.dart
new file mode 100644
index 0000000..549909b
--- /dev/null
+++ b/tests/compiler/dart2js_extra/32928_test.dart
@@ -0,0 +1,23 @@
+// 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.
+
+// dart2jsOptions=--strong
+
+/// Regression test for issue 32928.
+
+abstract class A<T> {
+  set f(T value) {
+    print(value);
+  }
+}
+
+abstract class B extends A {}
+
+class C extends B {
+  m(value) => super.f = value;
+}
+
+main() {
+  new C().m(null);
+}
diff --git a/tests/compiler/dart2js_extra/local_function_generic_strong_test.dart b/tests/compiler/dart2js_extra/local_function_generic_strong_test.dart
new file mode 100644
index 0000000..c7d3ec5
--- /dev/null
+++ b/tests/compiler/dart2js_extra/local_function_generic_strong_test.dart
@@ -0,0 +1,19 @@
+// 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.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+
+method1() {
+  T local<T>(T t) => t;
+  return local;
+}
+
+@NoInline()
+test(o) => o is S Function<S>(S);
+
+main() {
+  Expect.isTrue(test(method1()));
+}
diff --git a/tests/compiler/dart2js_extra/local_function_signatures_strong_test.dart b/tests/compiler/dart2js_extra/local_function_signatures_strong_test.dart
new file mode 100644
index 0000000..d6f4f31
--- /dev/null
+++ b/tests/compiler/dart2js_extra/local_function_signatures_strong_test.dart
@@ -0,0 +1,114 @@
+// 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.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+
+class Class1 {
+  method1() {
+    num local<T>(num n) => null;
+    return local;
+  }
+
+  method2() {
+    num local<T>(int n) => null;
+    return local;
+  }
+
+  method3() {
+    int local<T>(num n) => null;
+    return local;
+  }
+}
+
+class Class2 {
+  method4<T>() {
+    num local(T n) => null;
+    return local;
+  }
+}
+
+class Class3 {
+  method5<T>() {
+    T local(num n) => null;
+    return local;
+  }
+}
+
+class Class4 {
+  method6<T>() {
+    num local(num n, T t) => null;
+    return local;
+  }
+}
+
+method7<T>() {
+  num local(T n) => null;
+  return local;
+}
+
+method8<T>() {
+  T local(num n) => null;
+  return local;
+}
+
+method9<T>() {
+  num local(num n, T t) => null;
+  return local;
+}
+
+method10() {
+  num local<T>(T n) => null;
+  return local;
+}
+
+method11() {
+  T local<T>(num n) => null;
+  return local;
+}
+
+method12() {
+  num local<T>(num n, T t) => null;
+  return local;
+}
+
+num Function(num) //# 01: ok
+    method13() {
+  num local<T>(num n) => null;
+  return local;
+}
+
+num Function(num) //# 01: continued
+    method14() {
+  num local<T>(T n) => null;
+  return local;
+}
+
+num Function(num) //# 01: continued
+    method15() {
+  T local<T>(num n) => null;
+  return local;
+}
+
+@NoInline()
+test(o) => o is num Function(num);
+
+main() {
+  Expect.isFalse(test(new Class1().method1()));
+  Expect.isFalse(test(new Class1().method2()));
+  Expect.isFalse(test(new Class1().method3()));
+  Expect.isTrue(test(new Class2().method4<num>()));
+  Expect.isTrue(test(new Class3().method5<num>()));
+  Expect.isFalse(test(new Class4().method6<num>()));
+  Expect.isTrue(test(method7<num>()));
+  Expect.isTrue(test(method8<num>()));
+  Expect.isFalse(test(method9()));
+  Expect.isFalse(test(method10()));
+  Expect.isFalse(test(method11()));
+  Expect.isFalse(test(method12()));
+  Expect.isTrue(test(method13())); //# 01: continued
+  Expect.isTrue(test(method14())); //# 01: continued
+  Expect.isTrue(test(method15())); //# 01: continued
+}
diff --git a/tests/compiler/dart2js_extra/local_function_signatures_test.dart b/tests/compiler/dart2js_extra/local_function_signatures_test.dart
new file mode 100644
index 0000000..76ce246e
--- /dev/null
+++ b/tests/compiler/dart2js_extra/local_function_signatures_test.dart
@@ -0,0 +1,57 @@
+// 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.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+
+class Class1 {
+  method1() {
+    num local(num n) => null;
+    return local;
+  }
+
+  method2() {
+    num local(int n) => null;
+    return local;
+  }
+
+  method3() {
+    Object local(num n) => null;
+    return local;
+  }
+}
+
+class Class2<T> {
+  method4() {
+    num local(T n) => null;
+    return local;
+  }
+}
+
+class Class3<T> {
+  method5() {
+    T local(num n) => null;
+    return local;
+  }
+}
+
+class Class4<T> {
+  method6() {
+    num local(num n, T t) => null;
+    return local;
+  }
+}
+
+@NoInline()
+test(o) => o is num Function(num);
+
+main() {
+  Expect.isTrue(test(new Class1().method1()));
+  Expect.isFalse(test(new Class1().method2()));
+  Expect.isFalse(test(new Class1().method3()));
+  Expect.isTrue(test(new Class2<num>().method4()));
+  Expect.isTrue(test(new Class3<num>().method5()));
+  Expect.isFalse(test(new Class4<num>().method6()));
+}
diff --git a/tests/compiler/dart2js_extra/method_signatures_strong_test.dart b/tests/compiler/dart2js_extra/method_signatures_strong_test.dart
new file mode 100644
index 0000000..d23ed34
--- /dev/null
+++ b/tests/compiler/dart2js_extra/method_signatures_strong_test.dart
@@ -0,0 +1,50 @@
+// 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.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+
+class Class1 {
+  num method1<T>(num n) => null;
+
+  num method2<T>(int n) => null;
+
+  int method3<T>(num n) => null;
+}
+
+class Class2 {
+  num method4<T>(T n) => null;
+}
+
+class Class3 {
+  T method5<T>(num n) => null;
+}
+
+class Class4 {
+  num method6<T>(num n, T t) => null;
+}
+
+num method7<T>(T n) => null;
+
+T method8<T>(num n) => null;
+
+num method9<T>(num n, T t) => null;
+
+@NoInline()
+test(o) => o is num Function(num);
+
+forceInstantiation(num Function(num) f) => f;
+
+main() {
+  Expect.isFalse(test(new Class1().method1));
+  Expect.isFalse(test(new Class1().method2));
+  Expect.isFalse(test(new Class1().method3));
+  Expect.isTrue(test(forceInstantiation(new Class2().method4)));
+  Expect.isTrue(test(forceInstantiation(new Class3().method5)));
+  Expect.isFalse(test(new Class4().method6));
+  Expect.isTrue(test(forceInstantiation(method7)));
+  Expect.isTrue(test(forceInstantiation(method8)));
+  Expect.isFalse(test(method9));
+}
diff --git a/tests/compiler/dart2js_extra/method_signatures_test.dart b/tests/compiler/dart2js_extra/method_signatures_test.dart
new file mode 100644
index 0000000..569b329
--- /dev/null
+++ b/tests/compiler/dart2js_extra/method_signatures_test.dart
@@ -0,0 +1,48 @@
+// 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.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+
+class Class1 {
+  num method1(num n) => null;
+
+  num method2(int n) => null;
+
+  Object method3(num n) => null;
+}
+
+class Class2<T> {
+  num method4(T n) => null;
+}
+
+class Class3<T> {
+  T method5(num n) => null;
+}
+
+class Class4<T> {
+  num method6(num n, T t) => null;
+}
+
+num method7(num n) => null;
+
+num method8(int n) => null;
+
+Object method9(num n) => null;
+
+@NoInline()
+test(o) => o is num Function(num);
+
+main() {
+  Expect.isTrue(test(new Class1().method1));
+  Expect.isFalse(test(new Class1().method2));
+  Expect.isFalse(test(new Class1().method3));
+  Expect.isTrue(test(new Class2<num>().method4));
+  Expect.isTrue(test(new Class3<num>().method5));
+  Expect.isFalse(test(new Class4<num>().method6));
+  Expect.isTrue(test(method7));
+  Expect.isFalse(test(method8));
+  Expect.isFalse(test(method9));
+}
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index 4b626c0..ce101ae 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -161,6 +161,7 @@
 
 [ $compiler == dart2js && $checked && $fasta && $strong ]
 apply3_test: RuntimeError
+collection_of_test: RuntimeError
 error_stack_trace1_test: RuntimeError # Issue 12399
 from_environment_const_type_test/02: MissingCompileTimeError
 from_environment_const_type_test/03: MissingCompileTimeError
@@ -195,15 +196,24 @@
 dynamic_nosuchmethod_test: Fail # mirrors not supported
 
 [ $compiler == dart2js && $fast_startup && $fasta && $strong ]
-iterable_return_type_test/01: RuntimeError # Issue 20085
+cast_test: RuntimeError
+error_stack_trace1_test: RuntimeError
+growable_list_test: RuntimeError
+int_parse_radix_test/01: RuntimeError
+int_parse_radix_test/02: RuntimeError
+integer_to_radix_string_test/01: RuntimeError
+integer_to_radix_string_test/02: RuntimeError
+integer_to_radix_string_test/none: RuntimeError
+integer_to_string_test/01: RuntimeError
 iterable_return_type_test/02: RuntimeError # Dart2js does not support Uint64*.
-iterable_to_list_test/01: Crash # Wrong number of template arguments, given 2, expected 1
-iterable_to_list_test/none: Crash # Wrong number of template arguments, given 2, expected 1
-list_test/01: Crash # Unsupported operation: Unsupported type parameter type node T.
-list_test/none: Crash # Unsupported operation: Unsupported type parameter type node T.
-map_test: Crash # tests/corelib_2/map_test.dart:903:7: Internal problem: Unhandled Null in installDefaultConstructor.
+list_concurrent_modify_test: RuntimeError
+main_test: RuntimeError
+nan_infinity_test/01: RuntimeError
+string_split_test/checkedstore: RuntimeError
 symbol_reserved_word_test/03: RuntimeError # Issue 19972, new Symbol('void') should be allowed.
 uri_base_test: Crash # RangeError (index): Invalid value: Valid value range is empty: 0
+uri_parameters_all_test: RuntimeError
+uri_test: RuntimeError
 
 [ $compiler == dart2js && $fasta ]
 int_from_environment_test: Pass # Issue 31762
@@ -268,9 +278,6 @@
 [ $compiler == dart2js && !$fasta ]
 *: SkipByDesign
 
-[ $compiler == dart2js && $strong ]
-collection_of_test: RuntimeError
-
 [ $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkp && $compiler != fasta ]
 iterable_element_at_test/static: MissingCompileTimeError
 
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 80b93c7..0453fe4 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -87,7 +87,6 @@
 assign_static_type_test/01: Fail
 assign_static_type_test/02: MissingCompileTimeError
 async_return_types_test/nestedFuture: Fail # Issue 26429
-async_return_types_test/wrongTypeParameter: Fail # Issue 26429
 cha_deopt1_test: RuntimeError
 cha_deopt2_test: RuntimeError
 cha_deopt3_test: RuntimeError
diff --git a/tests/language_2/export1_lib.dart b/tests/language_2/export1_lib.dart
index 77768c1..3f7be5b 100644
--- a/tests/language_2/export1_lib.dart
+++ b/tests/language_2/export1_lib.dart
@@ -4,6 +4,6 @@
 
 library export1_lib;
 
-export "dart:math" show LN10, LN2, E;
+export "dart:math" show ln10, ln2, e;
 
-var E = "E"; // Hides constant E from math lib.
+var e = "E"; // Hides constant E from math lib.
diff --git a/tests/language_2/function_type_alias6_test.dart b/tests/language_2/function_type_alias6_test.dart
index 47821da..4c5a5a6 100644
--- a/tests/language_2/function_type_alias6_test.dart
+++ b/tests/language_2/function_type_alias6_test.dart
@@ -21,7 +21,7 @@
   var f = (List x) {};
   Expect.isTrue(f is F);
   var g = (List<F> x) {};
-  Expect.isTrue(g is F);
+  Expect.isFalse(g is F);
   var d = new D();
   Expect.isTrue(d.foo is! C);
   Expect.isTrue(d.bar is C);
diff --git a/tests/language_2/import_combinators_test.dart b/tests/language_2/import_combinators_test.dart
index ecb5c87..c2757e1 100644
--- a/tests/language_2/import_combinators_test.dart
+++ b/tests/language_2/import_combinators_test.dart
@@ -9,7 +9,7 @@
 import "package:expect/expect.dart";
 import "import1_lib.dart" show hide, show hide ugly;
 import "export1_lib.dart";
-import "dart:math" as M show E;
+import "dart:math" as M show e;
 
 part "import_combinators_part.dart";
 
@@ -19,9 +19,9 @@
   // Top-level function from part, refers to imported variable show.
   Expect.equals("show", lookBehindCurtain());
   // Top-level variable E from export1_lib.dart.
-  Expect.equals("E", E);
+  Expect.equals("E", e);
   // Top-level variable E imported from dart:math.
-  Expect.equals(2.718281828459045, M.E);
+  Expect.equals(2.718281828459045, M.e);
   // Constant LN2 from math library, re-exported by export1_lib.dart.
-  Expect.equals(0.6931471805599453, LN2);
+  Expect.equals(0.6931471805599453, ln2);
 }
diff --git a/tests/language_2/instantiate_tearoff_test.dart b/tests/language_2/instantiate_tearoff_test.dart
index 1c50f7f..254949e 100644
--- a/tests/language_2/instantiate_tearoff_test.dart
+++ b/tests/language_2/instantiate_tearoff_test.dart
@@ -8,10 +8,9 @@
 
 int intToInt(int x) => x;
 String stringToString(String x) => x;
+String stringAndIntToString(String x, int y) => x;
 
-main() {
-  int Function(int) intFunc = f;
-  dynamic intFuncDynamic = intFunc;
+test(intFuncDynamic, stringFuncDynamic, dynamicFuncDynamic) {
   Expect.isTrue(intFuncDynamic is int Function(int));
   Expect.isFalse(intFuncDynamic is String Function(String));
   Expect.equals(intFuncDynamic(1), 1);
@@ -22,8 +21,6 @@
   Expect.throwsNoSuchMethodError(() {
     intFuncDynamic<String>('oops');
   });
-  String Function(String) stringFunc = f;
-  dynamic stringFuncDynamic = stringFunc;
   Expect.isTrue(stringFuncDynamic is String Function(String));
   Expect.isFalse(stringFuncDynamic is int Function(int));
   Expect.equals(stringFuncDynamic('hello'), 'hello');
@@ -35,9 +32,33 @@
   Expect.throwsNoSuchMethodError(() {
     stringFuncDynamic<int>(1);
   });
-  dynamic Function(dynamic) dynamicFunc = f;
-  dynamic dynamicFuncDynamic = dynamicFunc;
   Expect.throwsNoSuchMethodError(() {
     dynamicFuncDynamic<int>(1);
   });
 }
+
+main() {
+  int Function(int) if1 = f;
+  String Function(String) sf1 = f;
+  dynamic Function(dynamic) df1 = f;
+  test(if1, sf1, df1);
+
+  T local<T>(T x) => x;
+
+  int Function(int) if2 = local;
+  String Function(String) sf2 = local;
+  dynamic Function(dynamic) df2 = local;
+  test(if2, sf2, df2);
+
+  dynamic bar<X>() {
+    String foo<T>(X x, T t) {
+      return "$X, $T";
+    }
+
+    String Function(X, int) x = foo;
+    return x;
+  }
+  dynamic fn = bar<String>();
+  Expect.equals("${fn.runtimeType}", "${stringAndIntToString.runtimeType}");
+  Expect.equals(fn("a", 1), "String, int");
+}
diff --git a/tests/language_2/intrinsified_methods_test.dart b/tests/language_2/intrinsified_methods_test.dart
index 6e3401b..c321cf4 100644
--- a/tests/language_2/intrinsified_methods_test.dart
+++ b/tests/language_2/intrinsified_methods_test.dart
@@ -24,7 +24,7 @@
 }
 
 testTrigonometric() {
-  Expect.approxEquals(1.0, sin(PI / 2.0), 0.0001);
+  Expect.approxEquals(1.0, sin(pi / 2.0), 0.0001);
   Expect.approxEquals(1.0, cos(0), 0.0001);
   Expect.approxEquals(1.0, cos(0.0), 0.0001);
 }
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index 0ed2de8..55a2708 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -140,7 +140,6 @@
 switch4_negative_test: CompileTimeError
 switch5_negative_test: CompileTimeError
 switch7_negative_test: CompileTimeError
-syntax_test/none: Fail # Issue 11575
 test_negative_test: CompileTimeError
 try_catch_on_syntax_test/10: MissingCompileTimeError
 try_catch_on_syntax_test/11: MissingCompileTimeError
@@ -520,26 +519,7 @@
 optional_named_parameters_test/08: MissingCompileTimeError
 optional_named_parameters_test/09: MissingCompileTimeError
 override_field_test/02: MissingCompileTimeError
-override_inheritance_abstract_test/02: MissingCompileTimeError
-override_inheritance_abstract_test/03: MissingCompileTimeError
-override_inheritance_abstract_test/04: MissingCompileTimeError
-override_inheritance_abstract_test/08: MissingCompileTimeError
-override_inheritance_abstract_test/09: MissingCompileTimeError
-override_inheritance_abstract_test/10: MissingCompileTimeError
-override_inheritance_abstract_test/11: MissingCompileTimeError
-override_inheritance_abstract_test/12: MissingCompileTimeError
-override_inheritance_abstract_test/13: MissingCompileTimeError
-override_inheritance_abstract_test/14: MissingCompileTimeError
-override_inheritance_abstract_test/17: MissingCompileTimeError
-override_inheritance_abstract_test/19: MissingCompileTimeError
-override_inheritance_abstract_test/20: MissingCompileTimeError
-override_inheritance_abstract_test/21: MissingCompileTimeError
-override_inheritance_abstract_test/22: MissingCompileTimeError
-override_inheritance_abstract_test/23: MissingCompileTimeError
-override_inheritance_abstract_test/24: MissingCompileTimeError
-override_inheritance_abstract_test/25: MissingCompileTimeError
-override_inheritance_abstract_test/26: MissingCompileTimeError
-override_inheritance_abstract_test/28: MissingCompileTimeError
+override_inheritance_abstract_test/*: Skip # Tests Dart 2 semantics
 override_inheritance_field_test/05: MissingCompileTimeError
 override_inheritance_field_test/07: MissingCompileTimeError
 override_inheritance_field_test/08: MissingCompileTimeError
@@ -590,7 +570,6 @@
 override_inheritance_no_such_method_test/09: MissingCompileTimeError
 override_inheritance_no_such_method_test/10: MissingCompileTimeError
 override_inheritance_no_such_method_test/12: MissingCompileTimeError
-override_inheritance_no_such_method_test/13: MissingCompileTimeError
 override_method_with_field_test/02: MissingCompileTimeError
 parser_quirks_test: StaticWarning
 part2_test/01: MissingCompileTimeError
@@ -984,26 +963,7 @@
 optional_named_parameters_test/08: MissingCompileTimeError
 optional_named_parameters_test/09: MissingCompileTimeError
 override_field_test/02: MissingCompileTimeError
-override_inheritance_abstract_test/02: MissingCompileTimeError
-override_inheritance_abstract_test/03: MissingCompileTimeError
-override_inheritance_abstract_test/04: MissingCompileTimeError
-override_inheritance_abstract_test/08: MissingCompileTimeError
-override_inheritance_abstract_test/09: MissingCompileTimeError
-override_inheritance_abstract_test/10: MissingCompileTimeError
-override_inheritance_abstract_test/11: MissingCompileTimeError
-override_inheritance_abstract_test/12: MissingCompileTimeError
-override_inheritance_abstract_test/13: MissingCompileTimeError
-override_inheritance_abstract_test/14: MissingCompileTimeError
-override_inheritance_abstract_test/17: MissingCompileTimeError
-override_inheritance_abstract_test/19: MissingCompileTimeError
-override_inheritance_abstract_test/20: MissingCompileTimeError
-override_inheritance_abstract_test/21: MissingCompileTimeError
-override_inheritance_abstract_test/22: MissingCompileTimeError
-override_inheritance_abstract_test/23: MissingCompileTimeError
-override_inheritance_abstract_test/24: MissingCompileTimeError
-override_inheritance_abstract_test/25: MissingCompileTimeError
-override_inheritance_abstract_test/26: MissingCompileTimeError
-override_inheritance_abstract_test/28: MissingCompileTimeError
+override_inheritance_abstract_test/*: Skip # Tests Dart 2 semantics
 override_inheritance_field_test/05: MissingCompileTimeError
 override_inheritance_field_test/07: MissingCompileTimeError
 override_inheritance_field_test/08: MissingCompileTimeError
@@ -1054,7 +1014,6 @@
 override_inheritance_no_such_method_test/09: MissingCompileTimeError
 override_inheritance_no_such_method_test/10: MissingCompileTimeError
 override_inheritance_no_such_method_test/12: MissingCompileTimeError
-override_inheritance_no_such_method_test/13: MissingCompileTimeError
 override_method_with_field_test/02: MissingCompileTimeError
 parser_quirks_test: StaticWarning
 part2_test/01: MissingCompileTimeError
@@ -1194,25 +1153,6 @@
 multiple_interface_inheritance_test: CompileTimeError # Issue 30552
 no_main_test/01: MissingStaticWarning # Issue 28823
 no_such_method_negative_test: CompileTimeError
-override_inheritance_abstract_test/02: MissingCompileTimeError
-override_inheritance_abstract_test/03: MissingCompileTimeError
-override_inheritance_abstract_test/04: MissingCompileTimeError
-override_inheritance_abstract_test/08: MissingCompileTimeError
-override_inheritance_abstract_test/09: MissingCompileTimeError
-override_inheritance_abstract_test/10: MissingCompileTimeError
-override_inheritance_abstract_test/11: MissingCompileTimeError
-override_inheritance_abstract_test/12: MissingCompileTimeError
-override_inheritance_abstract_test/13: MissingCompileTimeError
-override_inheritance_abstract_test/14: MissingCompileTimeError
-override_inheritance_abstract_test/17: MissingCompileTimeError
-override_inheritance_abstract_test/19: MissingCompileTimeError
-override_inheritance_abstract_test/20: MissingCompileTimeError
-override_inheritance_abstract_test/21: MissingCompileTimeError
-override_inheritance_abstract_test/22: MissingCompileTimeError
-override_inheritance_abstract_test/23: MissingCompileTimeError
-override_inheritance_abstract_test/24: MissingCompileTimeError
-override_inheritance_abstract_test/25: MissingCompileTimeError
-override_inheritance_abstract_test/26: MissingCompileTimeError
 override_inheritance_field_test/04: CompileTimeError
 override_inheritance_field_test/06: CompileTimeError
 override_inheritance_field_test/26: CompileTimeError
@@ -1225,7 +1165,6 @@
 override_inheritance_generic_test/02: CompileTimeError
 override_inheritance_method_test/28: CompileTimeError
 override_inheritance_method_test/29: CompileTimeError
-override_inheritance_no_such_method_test/13: MissingCompileTimeError
 parameter_initializer_test: CompileTimeError
 parser_quirks_test: CompileTimeError
 prefix13_negative_test: CompileTimeError, OK
@@ -1248,6 +1187,8 @@
 super_bound_closure_test/none: CompileTimeError
 super_setter_test: StaticWarning # Issue 28823
 switch_case_test/none: CompileTimeError
+syntax_test/60: MissingCompileTimeError
+syntax_test/61: MissingCompileTimeError
 type_promotion_functions_test/01: Pass
 type_promotion_functions_test/05: Pass
 type_promotion_functions_test/06: Pass
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 742853a..7d81932 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -73,7 +73,6 @@
 function_subtype_call2_test: RuntimeError
 function_subtype_cast1_test: RuntimeError
 function_subtype_not1_test: RuntimeError
-function_subtype_typearg5_test: RuntimeError
 function_type/function_type0_test: RuntimeError # Issue 30476
 function_type/function_type10_test: RuntimeError # Issue 30476
 function_type/function_type12_test: RuntimeError # Issue 30476
@@ -193,8 +192,6 @@
 checked_method_error_order_test: RuntimeError
 class_cycle_test/02: MissingCompileTimeError
 class_cycle_test/03: MissingCompileTimeError
-closure_invoked_through_interface_target_field_test: MissingCompileTimeError
-closure_invoked_through_interface_target_getter_test: MissingCompileTimeError
 compile_time_constant_o_test/01: MissingCompileTimeError
 compile_time_constant_o_test/02: MissingCompileTimeError
 conditional_method_invocation_test/05: MissingCompileTimeError
@@ -339,8 +336,6 @@
 generic_closure_test/01: RuntimeError
 generic_closure_test/none: RuntimeError
 generic_function_dcall_test: Crash # Unsupported operation: Unsupported type parameter type node T.
-generic_function_typedef_test/01: RuntimeError
-generic_instanceof_test: RuntimeError
 generic_tearoff_test: Crash # Unsupported operation: Unsupported type parameter type node T.
 generic_typedef_test: RuntimeError
 getter_override2_test/02: MissingCompileTimeError
@@ -371,7 +366,6 @@
 list_literal_syntax_test/02: MissingCompileTimeError
 list_literal_syntax_test/03: MissingCompileTimeError
 malformed2_test/00: MissingCompileTimeError
-many_generic_instanceof_test: RuntimeError
 map_literal1_test/01: MissingCompileTimeError
 map_literal8_test: RuntimeError
 method_override7_test/00: MissingCompileTimeError
@@ -525,12 +519,12 @@
 switch_case_test/01: MissingCompileTimeError
 switch_case_test/02: MissingCompileTimeError
 symbol_literal_test/01: MissingCompileTimeError
-syntax_test/28: MissingCompileTimeError
-syntax_test/29: MissingCompileTimeError
-syntax_test/30: MissingCompileTimeError
-syntax_test/31: MissingCompileTimeError
-syntax_test/32: MissingCompileTimeError
-syntax_test/33: MissingCompileTimeError
+syntax_test/28: MissingCompileTimeError # Issue 29763
+syntax_test/29: MissingCompileTimeError # Issue 29763
+syntax_test/30: MissingCompileTimeError # Issue 29763
+syntax_test/31: MissingCompileTimeError # Issue 29763
+syntax_test/32: MissingCompileTimeError # Issue 29763
+syntax_test/33: MissingCompileTimeError # Issue 29763
 tearoff_dynamic_test: RuntimeError
 truncdiv_test: RuntimeError # non JS number semantics - Issue 15246
 try_catch_test/01: MissingCompileTimeError
@@ -560,8 +554,6 @@
 issue31596_super_test/04: MissingCompileTimeError
 issue31596_super_test/05: RuntimeError
 issue31596_test: RuntimeError
-nsm5_test: MissingCompileTimeError
-override_inheritance_no_such_method_test/05: MissingCompileTimeError
 
 [ $compiler == dart2js && $fast_startup ]
 const_evaluation_test/*: Fail # mirrors not supported
@@ -592,220 +584,188 @@
 vm/reflect_core_vm_test: Fail # mirrors not supported
 
 [ $compiler == dart2js && $fast_startup && $fasta && $strong ]
-assertion_initializer_const_function_test/01: MissingCompileTimeError
 assertion_test: RuntimeError
+async_await_test/02: RuntimeError
+async_await_test/03: RuntimeError
+async_await_test/none: RuntimeError
 async_star_cancel_while_paused_test: RuntimeError
+async_star_test/01: RuntimeError
 async_star_test/02: RuntimeError
+async_star_test/03: RuntimeError
+async_star_test/04: RuntimeError
+async_star_test/05: RuntimeError
+async_star_test/none: RuntimeError
 bad_override_test/03: MissingCompileTimeError
 bad_override_test/04: MissingCompileTimeError
 bad_override_test/05: MissingCompileTimeError
 bit_operations_test: RuntimeError
 branch_canonicalization_test: RuntimeError
-call_function_apply_test: RuntimeError # Issue 23873
+call_method_implicit_tear_off_implements_function_test/02: RuntimeError
+call_method_implicit_tear_off_implements_function_test/04: RuntimeError
+call_method_implicit_tear_off_test/02: RuntimeError
+call_method_implicit_tear_off_test/04: RuntimeError
 canonical_const2_test: RuntimeError, OK # non JS number semantics
+cha_deopt1_test: RuntimeError
+cha_deopt2_test: RuntimeError
+cha_deopt3_test: RuntimeError
 check_member_static_test/02: MissingCompileTimeError
 class_cycle_test/02: MissingCompileTimeError
 class_cycle_test/03: MissingCompileTimeError
-closure_invoked_through_interface_target_field_test: MissingCompileTimeError
-closure_invoked_through_interface_target_getter_test: MissingCompileTimeError
 compile_time_constant_o_test/01: MissingCompileTimeError
 compile_time_constant_o_test/02: MissingCompileTimeError
-conditional_method_invocation_test/05: MissingCompileTimeError
-conditional_method_invocation_test/06: MissingCompileTimeError
-conditional_method_invocation_test/07: MissingCompileTimeError
-conditional_method_invocation_test/08: MissingCompileTimeError
-conditional_method_invocation_test/12: MissingCompileTimeError
-conditional_method_invocation_test/13: MissingCompileTimeError
-conditional_method_invocation_test/18: MissingCompileTimeError
-conditional_method_invocation_test/19: MissingCompileTimeError
-conditional_property_access_test/04: MissingCompileTimeError
-conditional_property_access_test/05: MissingCompileTimeError
-conditional_property_access_test/06: MissingCompileTimeError
-conditional_property_access_test/10: MissingCompileTimeError
-conditional_property_access_test/11: MissingCompileTimeError
-conditional_property_access_test/16: MissingCompileTimeError
-conditional_property_access_test/17: MissingCompileTimeError
-conditional_property_assignment_test/04: MissingCompileTimeError
-conditional_property_assignment_test/05: MissingCompileTimeError
-conditional_property_assignment_test/06: MissingCompileTimeError
-conditional_property_assignment_test/10: MissingCompileTimeError
-conditional_property_assignment_test/11: MissingCompileTimeError
-conditional_property_assignment_test/12: MissingCompileTimeError
-conditional_property_assignment_test/13: MissingCompileTimeError
-conditional_property_assignment_test/27: MissingCompileTimeError
-conditional_property_assignment_test/28: MissingCompileTimeError
-conditional_property_assignment_test/32: MissingCompileTimeError
-conditional_property_assignment_test/33: MissingCompileTimeError
-conditional_property_assignment_test/34: MissingCompileTimeError
-conditional_property_assignment_test/35: MissingCompileTimeError
-conditional_property_increment_decrement_test/04: MissingCompileTimeError
-conditional_property_increment_decrement_test/08: MissingCompileTimeError
-conditional_property_increment_decrement_test/12: MissingCompileTimeError
-conditional_property_increment_decrement_test/16: MissingCompileTimeError
-conditional_property_increment_decrement_test/21: MissingCompileTimeError
-conditional_property_increment_decrement_test/22: MissingCompileTimeError
-conditional_property_increment_decrement_test/27: MissingCompileTimeError
-conditional_property_increment_decrement_test/28: MissingCompileTimeError
-conditional_property_increment_decrement_test/33: MissingCompileTimeError
-conditional_property_increment_decrement_test/34: MissingCompileTimeError
-conditional_property_increment_decrement_test/39: MissingCompileTimeError
-conditional_property_increment_decrement_test/40: MissingCompileTimeError
+compile_time_constant_static5_test/11: CompileTimeError
+compile_time_constant_static5_test/16: CompileTimeError
+compile_time_constant_static5_test/21: CompileTimeError
+compile_time_constant_static5_test/23: CompileTimeError
+conditional_rewrite_test: RuntimeError
 config_import_test: RuntimeError
-const_constructor2_test/05: MissingCompileTimeError
-const_constructor2_test/06: MissingCompileTimeError
-const_constructor2_test/13: MissingCompileTimeError
-const_constructor2_test/14: MissingCompileTimeError
-const_constructor2_test/15: MissingCompileTimeError
-const_constructor2_test/16: MissingCompileTimeError
-const_constructor2_test/17: MissingCompileTimeError
-const_constructor2_test/18: MissingCompileTimeError
-const_constructor2_test/20: MissingCompileTimeError
-const_constructor2_test/22: MissingCompileTimeError
-const_constructor2_test/24: MissingCompileTimeError
 const_dynamic_type_literal_test/02: MissingCompileTimeError
-const_error_multiply_initialized_test/02: MissingCompileTimeError
-const_error_multiply_initialized_test/04: MissingCompileTimeError
 const_evaluation_test/01: RuntimeError
-const_init2_test/02: MissingCompileTimeError
 const_instance_field_test/01: MissingCompileTimeError
+const_list_test: RuntimeError
 const_map2_test/00: MissingCompileTimeError
 const_map3_test/00: MissingCompileTimeError
+const_map4_test: RuntimeError
 const_switch2_test/01: MissingCompileTimeError
 const_switch_test/02: RuntimeError, OK # constant identity based on JS constants
 const_switch_test/04: RuntimeError, OK # constant identity based on JS constants
-const_types_test/01: MissingCompileTimeError
-const_types_test/02: MissingCompileTimeError
-const_types_test/03: MissingCompileTimeError
-const_types_test/04: MissingCompileTimeError
-const_types_test/05: MissingCompileTimeError
-const_types_test/06: MissingCompileTimeError
-const_types_test/13: MissingCompileTimeError
 const_types_test/34: MissingCompileTimeError
-const_types_test/35: MissingCompileTimeError
 const_types_test/39: MissingCompileTimeError
-const_types_test/40: MissingCompileTimeError
 constants_test/05: MissingCompileTimeError
-constructor_duplicate_final_test/01: MissingCompileTimeError
-constructor_duplicate_final_test/02: MissingCompileTimeError
-constructor_named_arguments_test/01: MissingCompileTimeError
+constructor12_test: RuntimeError
 constructor_named_arguments_test/none: RuntimeError
 constructor_redirect1_negative_test/01: Crash # Stack Overflow
-constructor_redirect1_negative_test/none: MissingCompileTimeError
 constructor_redirect2_negative_test: Crash # Stack Overflow
-constructor_redirect2_test/01: MissingCompileTimeError
 constructor_redirect_test/01: Crash # Assertion failure: Cannot find value Instance of 'ThisLocal' in (local(A.named2#x), local(A.named2#y), local(A.named2#z)) for j:constructor(A.named2).
-covariant_override/runtime_check_test: RuntimeError
-covariant_subtyping_tearoff1_test: RuntimeError
-covariant_subtyping_tearoff2_test: RuntimeError
-covariant_subtyping_tearoff3_test: RuntimeError
+covariance_type_parameter_test/01: RuntimeError
+covariance_type_parameter_test/02: RuntimeError
+covariance_type_parameter_test/03: RuntimeError
+covariant_override/tear_off_type_test: RuntimeError
 covariant_subtyping_test: Crash # Unsupported operation: Unsupported type parameter type node E.
-covariant_subtyping_unsafe_call1_test: RuntimeError
-covariant_subtyping_unsafe_call2_test: RuntimeError
-covariant_subtyping_unsafe_call3_test: RuntimeError
 cyclic_constructor_test/01: Crash # Stack Overflow
+cyclic_type_test/00: RuntimeError
+cyclic_type_test/02: RuntimeError
+cyclic_type_test/03: RuntimeError
+cyclic_type_test/04: RuntimeError
+cyclic_typedef_test/10: Crash # Crash when compiling file:///usr/local/google/home/sra/Dart/sdk/out/ReleaseX64/generated_tests/language_2/cyclic_typedef_test_10.dart,
+cyclic_typedef_test/11: Crash # Crash when compiling file:///usr/local/google/home/sra/Dart/sdk/out/ReleaseX64/generated_tests/language_2/cyclic_typedef_test_11.dart,
+deferred_closurize_load_library_test: RuntimeError
+deferred_constant_list_test: RuntimeError
 deferred_constraints_constants_test/default_argument2: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
 deferred_constraints_constants_test/none: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
 deferred_constraints_constants_test/reference_after_load: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
-deferred_constraints_type_annotation_test/as_operation: MissingCompileTimeError
-deferred_constraints_type_annotation_test/catch_check: MissingCompileTimeError
-deferred_constraints_type_annotation_test/is_check: MissingCompileTimeError
-deferred_constraints_type_annotation_test/new_before_load: MissingCompileTimeError
-deferred_constraints_type_annotation_test/new_generic2: MissingCompileTimeError
-deferred_constraints_type_annotation_test/new_generic3: MissingCompileTimeError
-deferred_constraints_type_annotation_test/type_annotation1: MissingCompileTimeError
-deferred_constraints_type_annotation_test/type_annotation_generic1: MissingCompileTimeError
-deferred_constraints_type_annotation_test/type_annotation_generic2: MissingCompileTimeError
-deferred_constraints_type_annotation_test/type_annotation_generic3: MissingCompileTimeError
-deferred_constraints_type_annotation_test/type_annotation_generic4: MissingCompileTimeError
-deferred_constraints_type_annotation_test/type_annotation_null: MissingCompileTimeError
-deferred_constraints_type_annotation_test/type_annotation_top_level: MissingCompileTimeError
+deferred_constraints_type_annotation_test/new: RuntimeError
+deferred_constraints_type_annotation_test/new_generic1: RuntimeError
+deferred_constraints_type_annotation_test/none: RuntimeError
+deferred_constraints_type_annotation_test/static_method: RuntimeError
+deferred_constraints_type_annotation_test/type_annotation_non_deferred: RuntimeError
+deferred_function_type_test: RuntimeError
+deferred_global_test: RuntimeError
 deferred_inheritance_constraints_test/extends: MissingCompileTimeError
 deferred_inheritance_constraints_test/implements: MissingCompileTimeError
 deferred_inheritance_constraints_test/mixin: MissingCompileTimeError
+deferred_inlined_test: RuntimeError
 deferred_load_constants_test/none: RuntimeError
-deferred_load_library_wrong_args_test/01: MissingRuntimeError
+deferred_load_inval_code_test: RuntimeError
+deferred_load_library_wrong_args_test/01: CompileTimeError
+deferred_mixin_test: RuntimeError
+deferred_no_such_method_test: RuntimeError
 deferred_not_loaded_check_test: RuntimeError # Test out of date. Issue 31933
+deferred_only_constant_test: RuntimeError
+deferred_optimized_test: RuntimeError
 deferred_redirecting_factory_test: RuntimeError
+deferred_regression_22995_test: RuntimeError
+deferred_regression_28678_test: RuntimeError
+deferred_shadow_load_library_test: RuntimeError
+deferred_shared_and_unshared_classes_test: RuntimeError
+deferred_static_seperate_test: RuntimeError
+deferred_type_dependency_test/as: RuntimeError
+deferred_type_dependency_test/is: RuntimeError
+deferred_type_dependency_test/none: RuntimeError
+deferred_type_dependency_test/type_annotation: RuntimeError
 double_int_to_string_test: RuntimeError, OK # non JS number semantics
 duplicate_export_negative_test: Fail
 duplicate_implements_test/01: MissingCompileTimeError
 duplicate_implements_test/02: MissingCompileTimeError
-duplicate_implements_test/03: MissingCompileTimeError
-duplicate_implements_test/04: MissingCompileTimeError
-dynamic_prefix_core_test/none: RuntimeError
-dynamic_test: RuntimeError
+dynamic_prefix_core_test/none: CompileTimeError
+emit_const_fields_test: CompileTimeError
 enum_mirror_test: RuntimeError
+example_constructor_test: RuntimeError
 expect_test: RuntimeError, OK # Issue 13080
 external_test/10: MissingRuntimeError
 external_test/13: MissingRuntimeError
 external_test/20: MissingRuntimeError
-factory_redirection_test/07: MissingCompileTimeError
+external_test/21: CompileTimeError
+external_test/24: CompileTimeError
+extract_type_arguments_test: RuntimeError
+f_bounded_quantification4_test: RuntimeError
 fauxverride_test/03: MissingCompileTimeError
 fauxverride_test/05: MissingCompileTimeError
 field_increment_bailout_test: RuntimeError
+field_initialization_order_test/01: MissingCompileTimeError
+field_initialization_order_test/none: RuntimeError
 field_override3_test/00: MissingCompileTimeError
 field_override3_test/01: MissingCompileTimeError
 field_override3_test/02: MissingCompileTimeError
 field_override3_test/03: MissingCompileTimeError
 field_override4_test/02: MissingCompileTimeError
-final_attempt_reinitialization_test/01: MissingCompileTimeError
-final_attempt_reinitialization_test/02: MissingCompileTimeError
+flatten_test/05: MissingRuntimeError
+flatten_test/08: MissingRuntimeError
+flatten_test/09: MissingRuntimeError
+flatten_test/12: MissingRuntimeError
 full_stacktrace1_test: RuntimeError # Issue 12698
 full_stacktrace2_test: RuntimeError # Issue 12698
 full_stacktrace3_test: RuntimeError # Issue 12698
+function_subtype3_test: RuntimeError
 function_subtype_bound_closure3_test: RuntimeError
 function_subtype_bound_closure4_test: RuntimeError
-function_subtype_bound_closure7_test: RuntimeError
 function_subtype_call1_test: RuntimeError
 function_subtype_call2_test: RuntimeError
 function_subtype_cast1_test: RuntimeError
-function_subtype_checked0_test: RuntimeError
-function_subtype_closure0_test: RuntimeError
-function_subtype_closure1_test: RuntimeError
-function_subtype_factory1_test: RuntimeError
-function_subtype_inline1_test: RuntimeError
 function_subtype_inline2_test: RuntimeError
-function_subtype_named1_test: RuntimeError
-function_subtype_named2_test: RuntimeError
 function_subtype_not1_test: RuntimeError
-function_subtype_optional1_test: RuntimeError
-function_subtype_optional2_test: RuntimeError
-function_subtype_regression_ddc_588_test: RuntimeError
 function_subtype_setter0_test: RuntimeError
-function_subtype_typearg2_test: RuntimeError
-function_subtype_typearg3_test: RuntimeError
-function_subtype_typearg5_test: RuntimeError
-function_type2_test: RuntimeError
 function_type_alias2_test: RuntimeError
-function_type_alias_test: RuntimeError
-generalized_void_syntax_test: CompileTimeError # Issue #30176.
+function_type_alias4_test: RuntimeError
 generic_closure_test/01: RuntimeError
 generic_closure_test/none: RuntimeError
-generic_field_mixin6_test/none: RuntimeError
-generic_function_bounds_test: Crash # Unsupported operation: Unsupported type parameter type node T.
-generic_function_dcall_test: Crash # Unsupported operation: Unsupported type parameter type node T.
-generic_function_typedef_test/01: RuntimeError
-generic_instanceof_test: RuntimeError
-generic_list_checked_test: RuntimeError
-generic_local_functions_test: Crash # Unsupported operation: Unsupported type parameter type node Y.
-generic_tearoff_test: Crash # Unsupported operation: Unsupported type parameter type node T.
-generic_typedef_test: Crash # Unsupported operation: Unsupported type parameter type node S.
+generic_function_bounds_test: RuntimeError
+generic_function_dcall_test: RuntimeError
+generic_function_type_as_type_argument_test/01: MissingCompileTimeError
+generic_function_type_as_type_argument_test/02: MissingCompileTimeError
+generic_instanceof2_test: RuntimeError
+generic_is_check_test: RuntimeError
+generic_method_types_test/02: RuntimeError
+generic_methods_bounds_test/02: MissingRuntimeError
+generic_methods_dynamic_test/02: MissingRuntimeError
+generic_methods_dynamic_test/04: MissingRuntimeError
+generic_methods_generic_class_tearoff_test: RuntimeError
+generic_methods_generic_function_result_test/01: MissingCompileTimeError
+generic_methods_simple_as_expression_test/02: MissingRuntimeError
+generic_methods_type_expression_test: RuntimeError
+generic_methods_unused_parameter_test: RuntimeError
+generic_no_such_method_dispatcher_simple_test: CompileTimeError
+generic_no_such_method_dispatcher_test: CompileTimeError
+generic_tearoff_test: CompileTimeError
 getter_override2_test/02: MissingCompileTimeError
 getter_override_test/00: MissingCompileTimeError
 getter_override_test/01: MissingCompileTimeError
 getter_override_test/02: MissingCompileTimeError
-getters_setters2_test/01: RuntimeError
-getters_setters2_test/none: RuntimeError
 identical_closure2_test: RuntimeError # non JS number semantics
 if_null_precedence_test/none: RuntimeError
-implicit_creation/implicit_new_or_const_composite_test: RuntimeError
-implicit_creation/implicit_new_or_const_test: RuntimeError
-inferrer_synthesized_constructor_test: RuntimeError
 infinity_test: RuntimeError # non JS number semantics - Issue 4984
 instance_creation_in_function_annotation_test: RuntimeError
-instanceof2_test: RuntimeError
-instanceof4_test/01: RuntimeError
-instanceof4_test/none: RuntimeError
+instantiate_tearoff_of_call_test: CompileTimeError
+int64_literal_test/01: RuntimeError
+int64_literal_test/02: RuntimeError
+int64_literal_test/03: MissingCompileTimeError
+int64_literal_test/04: RuntimeError
+int64_literal_test/05: RuntimeError
+int64_literal_test/10: RuntimeError
+int64_literal_test/20: RuntimeError
+int64_literal_test/30: MissingCompileTimeError
+int64_literal_test/40: RuntimeError
+int64_literal_test/none: RuntimeError
 integer_division_by_zero_test: RuntimeError # Issue 8301
 internal_library_test/02: Crash # NoSuchMethodError: Class 'DillLibraryBuilder' has no instance getter 'mixinApplicationClasses'.
 invocation_mirror2_test: RuntimeError # mirrors not supported
@@ -813,39 +773,29 @@
 invocation_mirror_invoke_on_test: RuntimeError
 issue21079_test: RuntimeError
 issue23244_test: RuntimeError
+issue31596_super_test/01: CompileTimeError
+issue31596_super_test/03: CompileTimeError
 left_shift_test: RuntimeError # non JS number semantics
 library_env_test/has_mirror_support: RuntimeError
-list_literal1_test/01: MissingCompileTimeError
-list_literal4_test/00: MissingCompileTimeError
-list_literal4_test/01: MissingCompileTimeError
-list_literal4_test/03: MissingCompileTimeError
-list_literal4_test/04: MissingCompileTimeError
-list_literal4_test/05: MissingCompileTimeError
-list_literal_syntax_test/01: MissingCompileTimeError
-list_literal_syntax_test/02: MissingCompileTimeError
-list_literal_syntax_test/03: MissingCompileTimeError
-malformed2_test/00: MissingCompileTimeError
-many_generic_instanceof_test: RuntimeError
+local_function2_test/none: RuntimeError
+local_function3_test/none: RuntimeError
+local_function_test/none: RuntimeError
+main_test/03: RuntimeError
 many_overridden_no_such_method_test: RuntimeError
-map_literal8_test: RuntimeError
 method_override7_test/00: MissingCompileTimeError
 method_override7_test/01: MissingCompileTimeError
 method_override7_test/02: MissingCompileTimeError
 method_override8_test/00: MissingCompileTimeError
 method_override8_test/01: MissingCompileTimeError
+method_override_test: CompileTimeError
+minify_closure_variable_collision_test: CompileTimeError
 mint_arithmetic_test: RuntimeError # non JS number semantics
 mixin_forwarding_constructor4_test/01: MissingCompileTimeError
 mixin_forwarding_constructor4_test/02: MissingCompileTimeError
 mixin_forwarding_constructor4_test/03: MissingCompileTimeError
 mixin_illegal_super_use_test/01: MissingCompileTimeError
-mixin_illegal_super_use_test/02: MissingCompileTimeError
-mixin_illegal_super_use_test/03: MissingCompileTimeError
 mixin_illegal_super_use_test/04: MissingCompileTimeError
-mixin_illegal_super_use_test/05: MissingCompileTimeError
-mixin_illegal_super_use_test/06: MissingCompileTimeError
 mixin_illegal_super_use_test/07: MissingCompileTimeError
-mixin_illegal_super_use_test/08: MissingCompileTimeError
-mixin_illegal_super_use_test/09: MissingCompileTimeError
 mixin_illegal_super_use_test/10: MissingCompileTimeError
 mixin_illegal_super_use_test/11: MissingCompileTimeError
 mixin_illegal_superclass_test/01: MissingCompileTimeError
@@ -878,14 +828,7 @@
 mixin_illegal_superclass_test/28: MissingCompileTimeError
 mixin_illegal_superclass_test/29: MissingCompileTimeError
 mixin_illegal_superclass_test/30: MissingCompileTimeError
-mixin_issue10216_2_test: RuntimeError
-mixin_mixin4_test: RuntimeError
-mixin_mixin5_test: RuntimeError
 mixin_mixin6_test: RuntimeError
-mixin_mixin7_test: RuntimeError
-mixin_mixin_bound2_test: RuntimeError
-mixin_mixin_bound_test: RuntimeError
-mixin_mixin_test: RuntimeError
 mixin_of_mixin_test/none: CompileTimeError
 mixin_super_2_test/none: CompileTimeError
 mixin_super_constructor_named_test/01: MissingCompileTimeError
@@ -911,7 +854,10 @@
 mixin_supertype_subclass4_test/04: CompileTimeError
 mixin_supertype_subclass4_test/05: CompileTimeError
 mixin_supertype_subclass4_test/none: CompileTimeError
-mixin_type_parameters_super_test: RuntimeError
+mixin_supertype_subclass_test/01: CompileTimeError
+mixin_supertype_subclass_test/03: CompileTimeError
+mixin_supertype_subclass_test/04: CompileTimeError
+mixin_supertype_subclass_test/none: CompileTimeError
 modulo_test: RuntimeError # non JS number semantics
 multiline_newline_test/04: MissingCompileTimeError
 multiline_newline_test/04r: MissingCompileTimeError
@@ -920,17 +866,16 @@
 multiline_newline_test/06: MissingCompileTimeError
 multiline_newline_test/06r: MissingCompileTimeError
 named_parameters_default_eq_test/02: MissingCompileTimeError
+named_parameters_default_eq_test/none: RuntimeError
 nan_identical_test: RuntimeError # Issue 11551
-nested_generic_closure_test: Crash # Unsupported operation: Unsupported type parameter type node F.
+nested_generic_closure_test: RuntimeError
 no_main_test/01: CompileTimeError
+no_such_method_mock_test: RuntimeError
 no_such_method_test: RuntimeError
-not_enough_positional_arguments_test/00: MissingCompileTimeError
-not_enough_positional_arguments_test/01: MissingCompileTimeError
-not_enough_positional_arguments_test/02: MissingCompileTimeError
-not_enough_positional_arguments_test/03: MissingCompileTimeError
-not_enough_positional_arguments_test/05: MissingCompileTimeError
-not_enough_positional_arguments_test/06: MissingCompileTimeError
-not_enough_positional_arguments_test/07: MissingCompileTimeError
+nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test: RuntimeError
+nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError
+nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError
+null_no_such_method_test: CompileTimeError
 null_test/mirrors: RuntimeError
 null_test/none: RuntimeError
 number_identity2_test: RuntimeError
@@ -941,6 +886,13 @@
 override_field_method4_negative_test: Fail
 override_field_method5_negative_test: Fail
 override_field_test/01: MissingCompileTimeError
+override_inheritance_field_test/04: CompileTimeError
+override_inheritance_field_test/06: CompileTimeError
+override_inheritance_field_test/26: CompileTimeError
+override_inheritance_field_test/29: CompileTimeError
+override_inheritance_generic_test/02: CompileTimeError
+override_inheritance_method_test/28: CompileTimeError
+override_inheritance_method_test/29: CompileTimeError
 override_inheritance_mixed_test/01: MissingCompileTimeError
 override_inheritance_mixed_test/02: MissingCompileTimeError
 override_inheritance_mixed_test/03: MissingCompileTimeError
@@ -948,23 +900,24 @@
 override_inheritance_mixed_test/08: MissingCompileTimeError
 override_inheritance_mixed_test/09: MissingCompileTimeError
 override_method_with_field_test/01: MissingCompileTimeError
-positional_parameters_type_test/01: MissingCompileTimeError
-positional_parameters_type_test/02: MissingCompileTimeError
-private_super_constructor_test/01: MissingCompileTimeError
+parser_quirks_test: CompileTimeError
 redirecting_factory_default_values_test/01: MissingCompileTimeError
 redirecting_factory_default_values_test/02: MissingCompileTimeError
-redirecting_factory_long_test: RuntimeError
 redirecting_factory_reflection_test: RuntimeError
-regress_20394_test/01: MissingCompileTimeError
+regress_22443_test: RuntimeError
+regress_23089_test: Crash # Crash when compiling file:///usr/local/google/home/sra/Dart/sdk/tests/language_2/regress_23089_test.dart,
+regress_23408_test: CompileTimeError
 regress_24283_test: RuntimeError # non JS number semantics
 regress_27617_test/1: Crash # Assertion failure: Unexpected constructor j:constructor(Foo._) in ConstructorDataImpl._getConstructorConstant
-regress_28217_test/01: MissingCompileTimeError
-regress_28217_test/none: MissingCompileTimeError
 regress_28255_test: RuntimeError
-regress_28341_test: RuntimeError
+regress_28278_test: RuntimeError
+regress_29025_test: CompileTimeError
+regress_29405_test: CompileTimeError
 regress_29784_test/01: Crash # Assertion failure: Cannot find value Instance of 'ThisLocal' in () for j:constructor(A.ok).
 regress_29784_test/02: MissingCompileTimeError # Issue 29784
-regress_31057_test: Crash # Unsupported operation: Unsupported type parameter type node B.
+regress_30339_test: CompileTimeError
+runtime_type_function_test: RuntimeError
+setter_no_getter_test/01: CompileTimeError
 setter_override_test/00: MissingCompileTimeError
 setter_override_test/03: MissingCompileTimeError
 stacktrace_demangle_ctors_test: RuntimeError # Issue 12698
@@ -972,25 +925,49 @@
 stacktrace_rethrow_error_test/withtraceparameter: RuntimeError # Issue 12698
 stacktrace_rethrow_nonerror_test: RuntimeError # Issue 12698
 stacktrace_test: RuntimeError # Issue 12698
+string_interpolate_test: CompileTimeError
+string_interpolation_and_buffer_test: RuntimeError
+string_split_test: CompileTimeError
+string_supertype_checked_test: CompileTimeError
+super_bound_closure_test/none: CompileTimeError
 super_call4_test: Crash # NoSuchMethodError: The getter 'thisLocal' was called on null.
+super_no_such_method1_test: CompileTimeError
+super_no_such_method2_test: CompileTimeError
+super_no_such_method3_test: CompileTimeError
+super_no_such_method4_test: CompileTimeError
+super_no_such_method5_test: CompileTimeError
+super_operator_index5_test: CompileTimeError
+super_operator_index6_test: CompileTimeError
+super_operator_index7_test: CompileTimeError
+super_operator_index8_test: CompileTimeError
+super_test: RuntimeError
 switch_bad_case_test/01: MissingCompileTimeError
 switch_bad_case_test/02: MissingCompileTimeError
 switch_case_test/00: MissingCompileTimeError
 switch_case_test/01: MissingCompileTimeError
 switch_case_test/02: MissingCompileTimeError
-symbol_literal_test/01: MissingCompileTimeError
-syntax_test/28: MissingCompileTimeError
-syntax_test/29: MissingCompileTimeError
-syntax_test/30: MissingCompileTimeError
-syntax_test/31: MissingCompileTimeError
-syntax_test/32: MissingCompileTimeError
-syntax_test/33: MissingCompileTimeError
-tearoff_dynamic_test: Crash # Unsupported operation: Unsupported type parameter type node T.
+syntax_test/28: MissingCompileTimeError # Issue 29763
+syntax_test/29: MissingCompileTimeError # Issue 29763
+syntax_test/30: MissingCompileTimeError # Issue 29763
+syntax_test/31: MissingCompileTimeError # Issue 29763
+syntax_test/32: MissingCompileTimeError # Issue 29763
+syntax_test/33: MissingCompileTimeError # Issue 29763
+tearoff_dynamic_test: RuntimeError
 truncdiv_test: RuntimeError # non JS number semantics - Issue 15246
 try_catch_test/01: MissingCompileTimeError
+type_error_test: RuntimeError
 type_literal_test: RuntimeError
-type_variable_conflict2_test/02: MissingCompileTimeError
-typevariable_substitution2_test/02: RuntimeError
+type_promotion_functions_test/02: CompileTimeError
+type_promotion_functions_test/03: CompileTimeError
+type_promotion_functions_test/04: CompileTimeError
+type_promotion_functions_test/09: CompileTimeError
+type_promotion_functions_test/11: CompileTimeError
+type_promotion_functions_test/12: CompileTimeError
+type_promotion_functions_test/13: CompileTimeError
+type_promotion_functions_test/14: CompileTimeError
+type_promotion_functions_test/none: CompileTimeError
+type_promotion_more_specific_test/04: CompileTimeError
+type_variable_promotion_test: RuntimeError
 
 [ $compiler == dart2js && $fasta ]
 call_method_as_cast_test/06: RuntimeError
@@ -1005,7 +982,6 @@
 extract_type_arguments_test: Crash # Issue 31371
 function_propagation_test: RuntimeError
 generic_test/01: MissingCompileTimeError # front end does not validate `extends`
-implicit_downcast_during_yield_star_test: RuntimeError
 instantiate_tearoff_of_call_test: RuntimeError
 instantiate_tearoff_test: RuntimeError
 mixin_type_parameter_inference_error_test/none: CompileTimeError
@@ -1033,39 +1009,27 @@
 type_alias_equality_test/04: RuntimeError # Issue 32784
 
 [ $compiler == dart2js && $fasta && $host_checked && $strong ]
-abstract_factory_constructor_test/00: MissingCompileTimeError
-abstract_getter_test/01: MissingCompileTimeError
 abstract_override_adds_optional_args_concrete_subclass_test: MissingCompileTimeError
 abstract_override_adds_optional_args_concrete_test: MissingCompileTimeError
-abstract_syntax_test/00: MissingCompileTimeError
 additional_interface_adds_optional_args_concrete_subclass_test: MissingCompileTimeError
 additional_interface_adds_optional_args_concrete_test: MissingCompileTimeError
 assertion_test: RuntimeError
 async_await_test/02: RuntimeError
 async_await_test/03: RuntimeError
 async_await_test/none: RuntimeError
-async_congruence_local_test/none: RuntimeError
-async_congruence_method_test/none: RuntimeError
-async_congruence_top_level_test: RuntimeError
-async_congruence_unnamed_test/none: RuntimeError
 async_or_generator_return_type_stacktrace_test/01: MissingCompileTimeError
 async_or_generator_return_type_stacktrace_test/02: MissingCompileTimeError
 async_or_generator_return_type_stacktrace_test/03: MissingCompileTimeError
 async_return_types_test/nestedFuture: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||
 async_return_types_test/tooManyTypeParameters: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||
 async_return_types_test/wrongReturnType: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||
-async_star_await_pauses_test: RuntimeError
 async_star_cancel_while_paused_test: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||
-async_star_regression_2238_test: RuntimeError
-async_star_regression_23116_test: RuntimeError
-async_star_stream_take_test: RuntimeError
 async_star_test/01: RuntimeError
 async_star_test/02: RuntimeError
 async_star_test/03: RuntimeError
 async_star_test/04: RuntimeError
 async_star_test/05: RuntimeError
 async_star_test/none: RuntimeError
-async_test: RuntimeError
 await_not_started_immediately_test: Crash # Assertion failure: Runtime type information not available for type_variable_local(bindCallback.R) in (local(_RootZone.bindCallback#)) for j:closure_call(_RootZone_bindCallback_closure.call).
 bad_override_test/01: MissingCompileTimeError
 bad_override_test/02: MissingCompileTimeError
@@ -1092,8 +1056,6 @@
 class_literal_static_test/01: MissingCompileTimeError
 class_literal_static_test/03: MissingCompileTimeError
 class_literal_static_test/07: MissingCompileTimeError
-closure_invoked_through_interface_target_field_test: MissingCompileTimeError
-closure_invoked_through_interface_target_getter_test: MissingCompileTimeError
 closure_self_reference_test: Crash # 'file:*/pkg/compiler/lib/src/ssa/nodes.dart': Failed assertion: line 641 pos 12: 'isClosed()': is not true.
 compile_time_constant_k_test/01: MissingCompileTimeError
 compile_time_constant_k_test/02: MissingCompileTimeError
@@ -1197,7 +1159,6 @@
 f_bounded_quantification4_test: RuntimeError
 f_bounded_quantification_test/01: MissingCompileTimeError
 f_bounded_quantification_test/02: MissingCompileTimeError
-factory2_test/03: MissingCompileTimeError
 factory4_test/00: MissingCompileTimeError
 fauxverride_test/03: MissingCompileTimeError
 fauxverride_test/05: MissingCompileTimeError
@@ -1228,7 +1189,6 @@
 function_subtype_inline2_test: RuntimeError
 function_subtype_not1_test: RuntimeError
 function_subtype_setter0_test: RuntimeError
-function_subtype_typearg5_test: RuntimeError
 function_type_alias2_test: RuntimeError
 function_type_alias4_test: RuntimeError
 generic_closure_test/01: RuntimeError
@@ -1237,9 +1197,7 @@
 generic_function_dcall_test: RuntimeError
 generic_function_type_as_type_argument_test/01: MissingCompileTimeError
 generic_function_type_as_type_argument_test/02: MissingCompileTimeError
-generic_function_typedef_test/01: RuntimeError
 generic_instanceof2_test: RuntimeError
-generic_instanceof_test: RuntimeError
 generic_is_check_test: RuntimeError
 generic_method_types_test/02: RuntimeError
 generic_methods_bounds_test/01: MissingCompileTimeError
@@ -1267,8 +1225,6 @@
 identical_const_test/03: MissingCompileTimeError
 identical_const_test/04: MissingCompileTimeError
 if_null_precedence_test/none: RuntimeError
-implicit_this_test/01: MissingCompileTimeError
-implicit_this_test/04: MissingCompileTimeError
 infinity_test: RuntimeError # non JS number semantics - Issue 4984
 initializing_formal_type_annotation_test/01: MissingCompileTimeError
 initializing_formal_type_annotation_test/02: MissingCompileTimeError
@@ -1321,7 +1277,6 @@
 malbounded_type_test_test/00: MissingCompileTimeError
 malbounded_type_test_test/01: MissingCompileTimeError
 malbounded_type_test_test/02: MissingCompileTimeError
-many_generic_instanceof_test: RuntimeError
 many_overridden_no_such_method_test: RuntimeError
 map_literal3_test/01: MissingCompileTimeError
 map_literal3_test/02: MissingCompileTimeError
@@ -1467,25 +1422,6 @@
 override_field_test/01: MissingCompileTimeError
 override_field_test/02: MissingCompileTimeError
 override_field_test/03: MissingCompileTimeError
-override_inheritance_abstract_test/02: MissingCompileTimeError
-override_inheritance_abstract_test/03: MissingCompileTimeError
-override_inheritance_abstract_test/04: MissingCompileTimeError
-override_inheritance_abstract_test/08: MissingCompileTimeError
-override_inheritance_abstract_test/09: MissingCompileTimeError
-override_inheritance_abstract_test/10: MissingCompileTimeError
-override_inheritance_abstract_test/11: MissingCompileTimeError
-override_inheritance_abstract_test/12: MissingCompileTimeError
-override_inheritance_abstract_test/13: MissingCompileTimeError
-override_inheritance_abstract_test/14: MissingCompileTimeError
-override_inheritance_abstract_test/17: MissingCompileTimeError
-override_inheritance_abstract_test/19: MissingCompileTimeError
-override_inheritance_abstract_test/20: MissingCompileTimeError
-override_inheritance_abstract_test/21: MissingCompileTimeError
-override_inheritance_abstract_test/22: MissingCompileTimeError
-override_inheritance_abstract_test/23: MissingCompileTimeError
-override_inheritance_abstract_test/24: MissingCompileTimeError
-override_inheritance_abstract_test/25: MissingCompileTimeError
-override_inheritance_abstract_test/26: MissingCompileTimeError
 override_inheritance_field_test/04: CompileTimeError
 override_inheritance_field_test/06: CompileTimeError
 override_inheritance_field_test/26: CompileTimeError
@@ -1502,18 +1438,8 @@
 override_inheritance_mixed_test/02: MissingCompileTimeError
 override_inheritance_mixed_test/03: MissingCompileTimeError
 override_inheritance_mixed_test/04: MissingCompileTimeError
-override_inheritance_mixed_test/06: MissingCompileTimeError
-override_inheritance_mixed_test/07: MissingCompileTimeError
 override_inheritance_mixed_test/08: MissingCompileTimeError
 override_inheritance_mixed_test/09: MissingCompileTimeError
-override_inheritance_no_such_method_test/01: MissingCompileTimeError
-override_inheritance_no_such_method_test/02: MissingCompileTimeError
-override_inheritance_no_such_method_test/06: MissingCompileTimeError
-override_inheritance_no_such_method_test/07: MissingCompileTimeError
-override_inheritance_no_such_method_test/09: MissingCompileTimeError
-override_inheritance_no_such_method_test/10: MissingCompileTimeError
-override_inheritance_no_such_method_test/12: MissingCompileTimeError
-override_inheritance_no_such_method_test/13: MissingCompileTimeError
 override_method_with_field_test/01: MissingCompileTimeError
 parser_quirks_test: CompileTimeError
 partial_tearoff_instantiation_test/05: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
@@ -1598,12 +1524,12 @@
 syntax_test/24: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
 syntax_test/25: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
 syntax_test/26: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/28: MissingCompileTimeError
-syntax_test/29: MissingCompileTimeError
-syntax_test/30: MissingCompileTimeError
-syntax_test/31: MissingCompileTimeError
-syntax_test/32: MissingCompileTimeError
-syntax_test/33: MissingCompileTimeError
+syntax_test/28: MissingCompileTimeError # Issue 29763
+syntax_test/29: MissingCompileTimeError # Issue 29763
+syntax_test/30: MissingCompileTimeError # Issue 29763
+syntax_test/31: MissingCompileTimeError # Issue 29763
+syntax_test/32: MissingCompileTimeError # Issue 29763
+syntax_test/33: MissingCompileTimeError # Issue 29763
 tearoff_dynamic_test: RuntimeError
 truncdiv_test: RuntimeError # non JS number semantics - Issue 15246
 try_catch_test/01: MissingCompileTimeError
@@ -1707,39 +1633,27 @@
 wrong_number_type_arguments_test/none: Pass
 
 [ $compiler == dart2js && $fasta && $minified && $strong ]
-abstract_factory_constructor_test/00: MissingCompileTimeError
-abstract_getter_test/01: MissingCompileTimeError
 abstract_override_adds_optional_args_concrete_subclass_test: MissingCompileTimeError
 abstract_override_adds_optional_args_concrete_test: MissingCompileTimeError
-abstract_syntax_test/00: MissingCompileTimeError
 additional_interface_adds_optional_args_concrete_subclass_test: MissingCompileTimeError
 additional_interface_adds_optional_args_concrete_test: MissingCompileTimeError
 assertion_test: RuntimeError
 async_await_test/02: RuntimeError
 async_await_test/03: RuntimeError
 async_await_test/none: RuntimeError
-async_congruence_local_test/none: RuntimeError
-async_congruence_method_test/none: RuntimeError
-async_congruence_top_level_test: RuntimeError
-async_congruence_unnamed_test/none: RuntimeError
 async_or_generator_return_type_stacktrace_test/01: MissingCompileTimeError
 async_or_generator_return_type_stacktrace_test/02: MissingCompileTimeError
 async_or_generator_return_type_stacktrace_test/03: MissingCompileTimeError
 async_return_types_test/nestedFuture: Crash # Interpolated value #1 is not an Expression or List of Expressions: [VariableUse(f), Instance of 'LiteralNull', null]
 async_return_types_test/tooManyTypeParameters: Crash # Interpolated value #1 is not an Expression or List of Expressions: [VariableUse(f), Instance of 'LiteralNull', null]
 async_return_types_test/wrongReturnType: Crash # Interpolated value #1 is not an Expression or List of Expressions: [VariableUse(f), Instance of 'LiteralNull', null]
-async_star_await_pauses_test: RuntimeError
 async_star_cancel_while_paused_test: Crash # Interpolated value #1 is not an Expression or List of Expressions: [VariableUse(f), Instance of 'LiteralNull', null]
-async_star_regression_2238_test: RuntimeError
-async_star_regression_23116_test: RuntimeError
-async_star_stream_take_test: RuntimeError
 async_star_test/01: RuntimeError
 async_star_test/02: RuntimeError
 async_star_test/03: RuntimeError
 async_star_test/04: RuntimeError
 async_star_test/05: RuntimeError
 async_star_test/none: RuntimeError
-async_test: RuntimeError
 await_not_started_immediately_test: Crash # Assertion failure: Runtime type information not available for type_variable_local(bindCallback.R) in (local(_RootZone.bindCallback#)) for j:closure_call(_RootZone_bindCallback_closure.call).
 bad_override_test/01: MissingCompileTimeError
 bad_override_test/02: MissingCompileTimeError
@@ -1766,8 +1680,6 @@
 class_literal_static_test/01: MissingCompileTimeError
 class_literal_static_test/03: MissingCompileTimeError
 class_literal_static_test/07: MissingCompileTimeError
-closure_invoked_through_interface_target_field_test: MissingCompileTimeError
-closure_invoked_through_interface_target_getter_test: MissingCompileTimeError
 compile_time_constant_k_test/01: MissingCompileTimeError
 compile_time_constant_k_test/02: MissingCompileTimeError
 compile_time_constant_k_test/03: MissingCompileTimeError
@@ -1866,7 +1778,6 @@
 f_bounded_quantification4_test: RuntimeError # Issue 12605
 f_bounded_quantification_test/01: MissingCompileTimeError
 f_bounded_quantification_test/02: MissingCompileTimeError
-factory2_test/03: MissingCompileTimeError
 factory4_test/00: MissingCompileTimeError
 fauxverride_test/03: MissingCompileTimeError
 fauxverride_test/05: MissingCompileTimeError
@@ -1897,16 +1808,13 @@
 function_subtype_inline2_test: RuntimeError
 function_subtype_not1_test: RuntimeError
 function_subtype_setter0_test: RuntimeError
-function_subtype_typearg5_test: RuntimeError
 function_type_alias2_test: RuntimeError
 function_type_alias4_test: RuntimeError
 generic_function_bounds_test: RuntimeError
 generic_function_dcall_test: RuntimeError
 generic_function_type_as_type_argument_test/01: MissingCompileTimeError
 generic_function_type_as_type_argument_test/02: MissingCompileTimeError
-generic_function_typedef_test/01: RuntimeError
 generic_instanceof2_test: RuntimeError
-generic_instanceof_test: RuntimeError
 generic_is_check_test: RuntimeError
 generic_method_types_test/02: RuntimeError
 generic_methods_bounds_test/01: MissingCompileTimeError
@@ -1934,8 +1842,6 @@
 identical_const_test/03: MissingCompileTimeError
 identical_const_test/04: MissingCompileTimeError
 if_null_precedence_test/none: RuntimeError
-implicit_this_test/01: MissingCompileTimeError
-implicit_this_test/04: MissingCompileTimeError
 infinity_test: RuntimeError # non JS number semantics - Issue 4984
 initializing_formal_type_annotation_test/01: MissingCompileTimeError
 initializing_formal_type_annotation_test/02: MissingCompileTimeError
@@ -1988,7 +1894,6 @@
 malbounded_type_test_test/00: MissingCompileTimeError
 malbounded_type_test_test/01: MissingCompileTimeError
 malbounded_type_test_test/02: MissingCompileTimeError
-many_generic_instanceof_test: RuntimeError
 many_overridden_no_such_method_test: RuntimeError
 map_literal3_test/01: MissingCompileTimeError
 map_literal3_test/02: MissingCompileTimeError
@@ -2136,25 +2041,6 @@
 override_field_test/01: MissingCompileTimeError
 override_field_test/02: MissingCompileTimeError
 override_field_test/03: MissingCompileTimeError
-override_inheritance_abstract_test/02: MissingCompileTimeError
-override_inheritance_abstract_test/03: MissingCompileTimeError
-override_inheritance_abstract_test/04: MissingCompileTimeError
-override_inheritance_abstract_test/08: MissingCompileTimeError
-override_inheritance_abstract_test/09: MissingCompileTimeError
-override_inheritance_abstract_test/10: MissingCompileTimeError
-override_inheritance_abstract_test/11: MissingCompileTimeError
-override_inheritance_abstract_test/12: MissingCompileTimeError
-override_inheritance_abstract_test/13: MissingCompileTimeError
-override_inheritance_abstract_test/14: MissingCompileTimeError
-override_inheritance_abstract_test/17: MissingCompileTimeError
-override_inheritance_abstract_test/19: MissingCompileTimeError
-override_inheritance_abstract_test/20: MissingCompileTimeError
-override_inheritance_abstract_test/21: MissingCompileTimeError
-override_inheritance_abstract_test/22: MissingCompileTimeError
-override_inheritance_abstract_test/23: MissingCompileTimeError
-override_inheritance_abstract_test/24: MissingCompileTimeError
-override_inheritance_abstract_test/25: MissingCompileTimeError
-override_inheritance_abstract_test/26: MissingCompileTimeError
 override_inheritance_field_test/04: CompileTimeError
 override_inheritance_field_test/06: CompileTimeError
 override_inheritance_field_test/26: CompileTimeError
@@ -2171,18 +2057,8 @@
 override_inheritance_mixed_test/02: MissingCompileTimeError
 override_inheritance_mixed_test/03: MissingCompileTimeError
 override_inheritance_mixed_test/04: MissingCompileTimeError
-override_inheritance_mixed_test/06: MissingCompileTimeError
-override_inheritance_mixed_test/07: MissingCompileTimeError
 override_inheritance_mixed_test/08: MissingCompileTimeError
 override_inheritance_mixed_test/09: MissingCompileTimeError
-override_inheritance_no_such_method_test/01: MissingCompileTimeError
-override_inheritance_no_such_method_test/02: MissingCompileTimeError
-override_inheritance_no_such_method_test/06: MissingCompileTimeError
-override_inheritance_no_such_method_test/07: MissingCompileTimeError
-override_inheritance_no_such_method_test/09: MissingCompileTimeError
-override_inheritance_no_such_method_test/10: MissingCompileTimeError
-override_inheritance_no_such_method_test/12: MissingCompileTimeError
-override_inheritance_no_such_method_test/13: MissingCompileTimeError
 override_method_with_field_test/01: MissingCompileTimeError
 parser_quirks_test: CompileTimeError
 recursive_generic_test: RuntimeError
@@ -2242,12 +2118,12 @@
 switch_case_test/01: MissingCompileTimeError
 switch_case_test/02: MissingCompileTimeError
 symbol_conflict_test: RuntimeError # Issue 23857
-syntax_test/28: MissingCompileTimeError
-syntax_test/29: MissingCompileTimeError
-syntax_test/30: MissingCompileTimeError
-syntax_test/31: MissingCompileTimeError
-syntax_test/32: MissingCompileTimeError
-syntax_test/33: MissingCompileTimeError
+syntax_test/28: MissingCompileTimeError # Issue 29763
+syntax_test/29: MissingCompileTimeError # Issue 29763
+syntax_test/30: MissingCompileTimeError # Issue 29763
+syntax_test/31: MissingCompileTimeError # Issue 29763
+syntax_test/32: MissingCompileTimeError # Issue 29763
+syntax_test/33: MissingCompileTimeError # Issue 29763
 tearoff_dynamic_test: RuntimeError
 truncdiv_test: RuntimeError # non JS number semantics - Issue 15246
 try_catch_test/01: MissingCompileTimeError
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index b259467..b611f55 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -146,6 +146,7 @@
 parameter_initializer_test: CompileTimeError
 part_refers_to_core_library_test/01: Crash
 prefix10_negative_test: Fail # Issue 29920
+regress_23089_test: MissingCompileTimeError
 regress_23408_test: CompileTimeError
 regress_24283_test: RuntimeError # Intended to fail, requires 64-bit numbers.
 regress_29025_test: CompileTimeError # Issue 29081
@@ -170,7 +171,8 @@
 super_operator_index7_test: RuntimeError
 super_operator_index8_test: RuntimeError
 switch_case_test/none: CompileTimeError
-syntax_test/none: CompileTimeError
+syntax_test/60: MissingCompileTimeError
+syntax_test/61: MissingCompileTimeError
 truncdiv_test: RuntimeError # Issue 29920
 try_catch_on_syntax_test/10: MissingCompileTimeError
 try_catch_on_syntax_test/11: MissingCompileTimeError
@@ -287,9 +289,6 @@
 void_type_usage_test/paren_void_init: MissingCompileTimeError
 
 [ $compiler == dartdevk ]
-abstract_factory_constructor_test/00: MissingCompileTimeError
-abstract_getter_test/01: MissingCompileTimeError
-abstract_syntax_test/00: MissingCompileTimeError
 additional_interface_adds_optional_args_concrete_subclass_test: MissingCompileTimeError
 additional_interface_adds_optional_args_concrete_test: MissingCompileTimeError
 async_or_generator_return_type_stacktrace_test/01: MissingCompileTimeError
@@ -317,8 +316,6 @@
 check_member_static_test/02: MissingCompileTimeError
 class_cycle_test/02: MissingCompileTimeError
 class_cycle_test/03: MissingCompileTimeError
-closure_invoked_through_interface_target_field_test: MissingCompileTimeError
-closure_invoked_through_interface_target_getter_test: MissingCompileTimeError
 compile_time_constant_c_test/02: MissingCompileTimeError
 compile_time_constant_k_test/01: MissingCompileTimeError
 compile_time_constant_k_test/02: MissingCompileTimeError
@@ -379,7 +376,6 @@
 external_test/24: CompileTimeError
 f_bounded_quantification_test/01: MissingCompileTimeError
 f_bounded_quantification_test/02: MissingCompileTimeError
-factory2_test/03: MissingCompileTimeError
 factory4_test/00: MissingCompileTimeError
 fauxverride_test/03: MissingCompileTimeError
 fauxverride_test/05: MissingCompileTimeError
@@ -420,8 +416,6 @@
 implicit_creation/implicit_const_not_default_values_test/e30: Pass
 implicit_creation/implicit_const_not_default_values_test/e6: Pass
 implicit_creation/implicit_const_not_default_values_test/e9: Pass
-implicit_this_test/01: MissingCompileTimeError
-implicit_this_test/04: MissingCompileTimeError
 initializing_formal_type_annotation_test/01: MissingCompileTimeError
 initializing_formal_type_annotation_test/02: MissingCompileTimeError
 instantiate_tearoff_of_call_test: CompileTimeError
@@ -524,12 +518,6 @@
 mixin_invalid_bound_test/08: MissingCompileTimeError
 mixin_invalid_bound_test/09: MissingCompileTimeError
 mixin_invalid_bound_test/10: MissingCompileTimeError
-mixin_of_mixin_test/01: MissingCompileTimeError
-mixin_of_mixin_test/02: MissingCompileTimeError
-mixin_of_mixin_test/03: MissingCompileTimeError
-mixin_of_mixin_test/04: MissingCompileTimeError
-mixin_of_mixin_test/05: MissingCompileTimeError
-mixin_of_mixin_test/06: MissingCompileTimeError
 mixin_regress_13688_test: RuntimeError # Issue 32427
 mixin_super_2_test/01: MissingCompileTimeError
 mixin_super_2_test/03: MissingCompileTimeError
@@ -551,7 +539,6 @@
 multiline_newline_test/06r: MissingCompileTimeError
 named_constructor_test/01: MissingCompileTimeError
 named_parameters_default_eq_test/02: MissingCompileTimeError
-nsm5_test: MissingCompileTimeError
 null2_test: RuntimeError # Issue 32194
 null_method_test: RuntimeError # Issue 32194
 null_no_such_method_test: CompileTimeError # Issue 31533
@@ -579,18 +566,8 @@
 override_inheritance_mixed_test/02: MissingCompileTimeError
 override_inheritance_mixed_test/03: MissingCompileTimeError
 override_inheritance_mixed_test/04: MissingCompileTimeError
-override_inheritance_mixed_test/06: MissingCompileTimeError
-override_inheritance_mixed_test/07: MissingCompileTimeError
 override_inheritance_mixed_test/08: MissingCompileTimeError
 override_inheritance_mixed_test/09: MissingCompileTimeError
-override_inheritance_no_such_method_test/01: MissingCompileTimeError
-override_inheritance_no_such_method_test/02: MissingCompileTimeError
-override_inheritance_no_such_method_test/05: MissingCompileTimeError
-override_inheritance_no_such_method_test/06: MissingCompileTimeError
-override_inheritance_no_such_method_test/07: MissingCompileTimeError
-override_inheritance_no_such_method_test/09: MissingCompileTimeError
-override_inheritance_no_such_method_test/10: MissingCompileTimeError
-override_inheritance_no_such_method_test/12: MissingCompileTimeError
 override_method_with_field_test/01: MissingCompileTimeError
 recursive_mixin_test: RuntimeError # Issue 32428
 redirecting_factory_default_values_test/01: MissingCompileTimeError
@@ -637,12 +614,6 @@
 switch_case_test/01: MissingCompileTimeError
 switch_case_test/02: MissingCompileTimeError
 syncstar_yield_test/copyParameters: RuntimeError # Expect.equals(expected: <2>, actual: <3>) fails.
-syntax_test/28: MissingCompileTimeError
-syntax_test/29: MissingCompileTimeError
-syntax_test/30: MissingCompileTimeError
-syntax_test/31: MissingCompileTimeError
-syntax_test/32: MissingCompileTimeError
-syntax_test/33: MissingCompileTimeError
 tearoff_dynamic_test: RuntimeError # Issue 32194
 try_catch_test/01: MissingCompileTimeError
 type_alias_equality_test/02: RuntimeError # Issue 32785
@@ -737,7 +708,6 @@
 flatten_test/12: MissingRuntimeError # Issue 29920
 for_variable_capture_test: RuntimeError # Issue 29920; Expect.equals(expected: <1>, actual: <0>) fails.
 function_subtype_inline2_test: RuntimeError # Expect.fail('Missing type error: 'new C.c1(m2)'.')
-function_type_alias6_test/none: RuntimeError # Expect.isTrue(false) fails.
 generic_function_type_as_type_argument_test/01: MissingCompileTimeError # Issue 29920
 generic_function_type_as_type_argument_test/02: MissingCompileTimeError # Issue 29920
 generic_instanceof2_test: RuntimeError # Issue 29920; ReferenceError: FooOfK$String is not defined
@@ -786,26 +756,6 @@
 numbers_test: RuntimeError # Issue 29920; Expect.equals(expected: <false>, actual: <true>) fails.
 overridden_no_such_method_test: RuntimeError # UnimplementedError: JsInstanceMirror.delegate unimplemented; UnimplementedError: JsInstanceMirror.delegate unimplemented
 override_field_test/03: MissingCompileTimeError
-override_inheritance_abstract_test/02: MissingCompileTimeError
-override_inheritance_abstract_test/03: MissingCompileTimeError
-override_inheritance_abstract_test/04: MissingCompileTimeError
-override_inheritance_abstract_test/08: MissingCompileTimeError
-override_inheritance_abstract_test/09: MissingCompileTimeError
-override_inheritance_abstract_test/10: MissingCompileTimeError
-override_inheritance_abstract_test/11: MissingCompileTimeError
-override_inheritance_abstract_test/12: MissingCompileTimeError
-override_inheritance_abstract_test/13: MissingCompileTimeError
-override_inheritance_abstract_test/14: MissingCompileTimeError
-override_inheritance_abstract_test/17: MissingCompileTimeError
-override_inheritance_abstract_test/19: MissingCompileTimeError
-override_inheritance_abstract_test/20: MissingCompileTimeError
-override_inheritance_abstract_test/21: MissingCompileTimeError
-override_inheritance_abstract_test/22: MissingCompileTimeError
-override_inheritance_abstract_test/23: MissingCompileTimeError
-override_inheritance_abstract_test/24: MissingCompileTimeError
-override_inheritance_abstract_test/25: MissingCompileTimeError
-override_inheritance_abstract_test/26: MissingCompileTimeError
-override_inheritance_no_such_method_test/13: MissingCompileTimeError
 parser_quirks_test: CompileTimeError
 private3_test: RuntimeError # Type 'PrivateSymbol' is not a subtype of type 'Symbol' in strong mode
 regress_16640_test: RuntimeError # Issue 29920; Uncaught Error: type arguments should not be null: E => {
@@ -821,5 +771,7 @@
 switch_label2_test: RuntimeError # Issue 29920; UnimplementedError: node <ShadowContinueSwitchStatement> see https://github.com/dart-lang/sdk/issues/29352 `continue #L1;
 switch_label_test: RuntimeError # Issue 29920; UnimplementedError: node <ShadowContinueSwitchStatement> see https://github.com/dart-lang/sdk/issues/29352 `continue #L1;
 switch_try_catch_test: RuntimeError # Issue 29920; Expect.throws: Unexpected 'UnimplementedError: node <ShadowContinueSwitchStatement> see https://github.com/dart-lang/sdk/issues/29352 `continue #L1;
+syntax_test/60: MissingCompileTimeError
+syntax_test/61: MissingCompileTimeError
 truncdiv_test: RuntimeError # Issue 29920; Expect.throws fails: Did not throw
 vm/*: SkipByDesign # VM only tests.; VM only tests.
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index ea83e68..52eae2d 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -53,11 +53,8 @@
 implicit_creation/implicit_const_not_default_values_test/e8: MissingCompileTimeError
 
 [ $fasta ]
-abstract_factory_constructor_test/00: MissingCompileTimeError # Issue 32013.
-abstract_getter_test/01: MissingCompileTimeError # Issue 32013.
-abstract_override_adds_optional_args_concrete_subclass_test: MissingCompileTimeError # Issue 32013.
+abstract_override_adds_optional_args_concrete_subclass_test: MissingCompileTimeError # Issue 32014.
 abstract_override_adds_optional_args_concrete_test: MissingCompileTimeError # Issue 32014.
-abstract_syntax_test/00: MissingCompileTimeError # Issue 32013.
 additional_interface_adds_optional_args_concrete_subclass_test: MissingCompileTimeError # Issue 32014.
 additional_interface_adds_optional_args_concrete_test: MissingCompileTimeError # Issue 32014.
 async_or_generator_return_type_stacktrace_test/01: MissingCompileTimeError
@@ -71,8 +68,6 @@
 call_non_method_field_test/01: MissingCompileTimeError
 call_non_method_field_test/02: MissingCompileTimeError
 check_member_static_test/01: MissingCompileTimeError
-closure_invoked_through_interface_target_field_test: MissingCompileTimeError
-closure_invoked_through_interface_target_getter_test: MissingCompileTimeError
 compile_time_constant_o_test/01: MissingCompileTimeError
 compile_time_constant_o_test/02: MissingCompileTimeError
 const_cast2_test/01: CompileTimeError
@@ -102,7 +97,6 @@
 duplicate_export_negative_test: Fail # Issue 6134
 f_bounded_quantification_test/01: MissingCompileTimeError
 f_bounded_quantification_test/02: MissingCompileTimeError
-factory2_test/03: MissingCompileTimeError
 factory4_test/00: MissingCompileTimeError
 field3_test/01: MissingCompileTimeError
 field_override_test/00: MissingCompileTimeError
@@ -115,8 +109,6 @@
 identical_const_test/02: MissingCompileTimeError
 identical_const_test/03: MissingCompileTimeError
 identical_const_test/04: MissingCompileTimeError
-implicit_this_test/01: MissingCompileTimeError
-implicit_this_test/04: MissingCompileTimeError
 issue31596_override_test/07: MissingCompileTimeError
 issue31596_override_test/08: MissingCompileTimeError
 issue31596_super_test/02: MissingCompileTimeError
@@ -176,45 +168,14 @@
 mixin_type_parameters_errors_test/05: MissingCompileTimeError
 named_constructor_test/01: MissingCompileTimeError
 named_parameters_default_eq_test/02: MissingCompileTimeError # Fasta bug: Default values are not allowed on redirecting factory constructors.
-nsm5_test: MissingCompileTimeError
 override_field_test/02: MissingCompileTimeError
 override_field_test/03: MissingCompileTimeError
-override_inheritance_abstract_test/02: MissingCompileTimeError
-override_inheritance_abstract_test/03: MissingCompileTimeError
-override_inheritance_abstract_test/04: MissingCompileTimeError
-override_inheritance_abstract_test/08: MissingCompileTimeError
-override_inheritance_abstract_test/09: MissingCompileTimeError
-override_inheritance_abstract_test/10: MissingCompileTimeError
-override_inheritance_abstract_test/11: MissingCompileTimeError
-override_inheritance_abstract_test/12: MissingCompileTimeError
-override_inheritance_abstract_test/13: MissingCompileTimeError
-override_inheritance_abstract_test/14: MissingCompileTimeError
-override_inheritance_abstract_test/17: MissingCompileTimeError
-override_inheritance_abstract_test/19: MissingCompileTimeError
-override_inheritance_abstract_test/20: MissingCompileTimeError
-override_inheritance_abstract_test/21: MissingCompileTimeError
-override_inheritance_abstract_test/22: MissingCompileTimeError
-override_inheritance_abstract_test/23: MissingCompileTimeError
-override_inheritance_abstract_test/24: MissingCompileTimeError
-override_inheritance_abstract_test/25: MissingCompileTimeError
-override_inheritance_abstract_test/26: MissingCompileTimeError
 override_inheritance_field_test/44: MissingCompileTimeError
 override_inheritance_field_test/47: MissingCompileTimeError
 override_inheritance_field_test/48: MissingCompileTimeError
 override_inheritance_field_test/53: MissingCompileTimeError
 override_inheritance_field_test/54: MissingCompileTimeError
-override_inheritance_mixed_test/06: MissingCompileTimeError
-override_inheritance_mixed_test/07: MissingCompileTimeError
 override_inheritance_mixed_test/09: MissingCompileTimeError
-override_inheritance_no_such_method_test/01: MissingCompileTimeError
-override_inheritance_no_such_method_test/02: MissingCompileTimeError
-override_inheritance_no_such_method_test/05: MissingCompileTimeError
-override_inheritance_no_such_method_test/06: MissingCompileTimeError
-override_inheritance_no_such_method_test/07: MissingCompileTimeError
-override_inheritance_no_such_method_test/09: MissingCompileTimeError
-override_inheritance_no_such_method_test/10: MissingCompileTimeError
-override_inheritance_no_such_method_test/12: MissingCompileTimeError
-override_inheritance_no_such_method_test/13: MissingCompileTimeError
 partial_tearoff_instantiation_test/05: MissingCompileTimeError
 partial_tearoff_instantiation_test/06: MissingCompileTimeError
 partial_tearoff_instantiation_test/07: MissingCompileTimeError
@@ -233,14 +194,14 @@
 switch_case_test/00: MissingCompileTimeError # KernelVM bug: Constant evaluation.
 switch_case_test/01: MissingCompileTimeError # KernelVM bug: Constant evaluation.
 switch_case_test/02: MissingCompileTimeError # KernelVM bug: Constant evaluation.
-syntax_test/28: MissingCompileTimeError
-syntax_test/29: MissingCompileTimeError
-syntax_test/30: MissingCompileTimeError
-syntax_test/31: MissingCompileTimeError
-syntax_test/32: MissingCompileTimeError
-syntax_test/33: MissingCompileTimeError
-syntax_test/60: MissingCompileTimeError
-syntax_test/61: MissingCompileTimeError
+syntax_test/28: MissingCompileTimeError # Issue 29763
+syntax_test/29: MissingCompileTimeError # Issue 29763
+syntax_test/30: MissingCompileTimeError # Issue 29763
+syntax_test/31: MissingCompileTimeError # Issue 29763
+syntax_test/32: MissingCompileTimeError # Issue 29763
+syntax_test/33: MissingCompileTimeError # Issue 29763
+syntax_test/60: MissingCompileTimeError # Issue 30176
+syntax_test/61: MissingCompileTimeError # Issue 30176
 type_variable_bounds2_test: MissingCompileTimeError
 type_variable_bounds3_test/00: MissingCompileTimeError
 type_variable_bounds4_test/01: MissingCompileTimeError
@@ -490,13 +451,6 @@
 [ $arch != simarm && $arch != simarm64 && $arch != simdbc64 && $compiler == dartk ]
 export_ambiguous_main_test: MissingCompileTimeError
 
-[ $arch == simdbc64 && $compiler == dartk && $mode == debug && $strong ]
-partial_tearoff_instantiation_test/05: Crash # Issue http://dartbug.com/32340
-partial_tearoff_instantiation_test/06: Crash # Issue http://dartbug.com/32340
-partial_tearoff_instantiation_test/07: Crash # Issue http://dartbug.com/32340
-partial_tearoff_instantiation_test/08: Crash # Issue http://dartbug.com/32340
-partial_tearoff_instantiation_test/none: Crash # Issue http://dartbug.com/32340
-
 [ $compiler != dart2js && $compiler != dartk && $compiler != dartkp && $fasta ]
 const_optional_args_test/01: MissingCompileTimeError
 
@@ -504,12 +458,6 @@
 compile_time_constant_c_test/02: MissingCompileTimeError
 const_constructor_nonconst_field_test/01: MissingCompileTimeError
 const_syntax_test/05: MissingCompileTimeError
-mixin_of_mixin_test/01: MissingCompileTimeError
-mixin_of_mixin_test/02: MissingCompileTimeError
-mixin_of_mixin_test/03: MissingCompileTimeError
-mixin_of_mixin_test/04: MissingCompileTimeError
-mixin_of_mixin_test/05: MissingCompileTimeError
-mixin_of_mixin_test/06: MissingCompileTimeError
 mixin_super_2_test/01: MissingCompileTimeError
 mixin_super_2_test/03: MissingCompileTimeError
 mixin_supertype_subclass_test/02: MissingCompileTimeError
@@ -652,8 +600,6 @@
 for_in_side_effects_test/01: MissingCompileTimeError
 function_propagation_test: RuntimeError
 function_subtype_inline2_test: RuntimeError
-function_type_alias6_test/none: RuntimeError
-generic_function_dcall_test: RuntimeError
 generic_instanceof2_test: RuntimeError
 generic_is_check_test: RuntimeError
 generic_no_such_method_dispatcher_simple_test: CompileTimeError # Issue 31533
@@ -986,7 +932,6 @@
 function_propagation_test: RuntimeError
 function_subtype_inline2_test: RuntimeError
 function_type_alias6_test/none: RuntimeError
-generic_function_dcall_test: RuntimeError
 generic_instanceof2_test: RuntimeError
 generic_is_check_test: RuntimeError
 generic_methods_recursive_bound_test/03: Crash, Pass
@@ -1338,9 +1283,33 @@
 type_promotion_more_specific_test/04: CompileTimeError
 
 [ $compiler == fasta && !$strong ]
+abstract_factory_constructor_test/00: MissingCompileTimeError
+abstract_getter_test/01: MissingCompileTimeError
+abstract_syntax_test/00: MissingCompileTimeError
 call_method_implicit_invoke_local_test/05: MissingCompileTimeError
+closure_invoked_through_interface_target_field_test: MissingCompileTimeError
+closure_invoked_through_interface_target_getter_test: MissingCompileTimeError
+factory2_test/03: MissingCompileTimeError
+implicit_this_test/01: MissingCompileTimeError
+implicit_this_test/04: MissingCompileTimeError
 invalid_override_in_mixin_test/01: MissingCompileTimeError
 map_literal1_test/01: MissingCompileTimeError
+mixin_of_mixin_test/01: MissingCompileTimeError
+mixin_of_mixin_test/02: MissingCompileTimeError
+mixin_of_mixin_test/03: MissingCompileTimeError
+mixin_of_mixin_test/04: MissingCompileTimeError
+mixin_of_mixin_test/05: MissingCompileTimeError
+mixin_of_mixin_test/06: MissingCompileTimeError
+nsm5_test: MissingCompileTimeError
+override_inheritance_mixed_test/06: MissingCompileTimeError
+override_inheritance_mixed_test/07: MissingCompileTimeError
+override_inheritance_no_such_method_test/01: MissingCompileTimeError
+override_inheritance_no_such_method_test/05: MissingCompileTimeError
+override_inheritance_no_such_method_test/06: MissingCompileTimeError
+override_inheritance_no_such_method_test/07: MissingCompileTimeError
+override_inheritance_no_such_method_test/09: MissingCompileTimeError
+override_inheritance_no_such_method_test/10: MissingCompileTimeError
+override_inheritance_no_such_method_test/12: MissingCompileTimeError
 
 [ $fasta && $strong ]
 compile_time_constant_k_test/01: MissingCompileTimeError
@@ -1920,7 +1889,7 @@
 override_field_method4_negative_test: Fail
 override_field_method5_negative_test: Fail
 override_field_test/01: MissingCompileTimeError
-override_inheritance_abstract_test/28: MissingCompileTimeError
+override_inheritance_abstract_test/*: Skip # Tests Dart 2 semantics
 override_inheritance_field_test/05: MissingCompileTimeError
 override_inheritance_field_test/07: MissingCompileTimeError
 override_inheritance_field_test/08: MissingCompileTimeError
diff --git a/tests/language_2/language_2_precompiled.status b/tests/language_2/language_2_precompiled.status
index c188ce8..8ff6cb8 100644
--- a/tests/language_2/language_2_precompiled.status
+++ b/tests/language_2/language_2_precompiled.status
@@ -763,6 +763,7 @@
 override_inheritance_abstract_test/02: MissingCompileTimeError
 override_inheritance_abstract_test/03: MissingCompileTimeError
 override_inheritance_abstract_test/04: MissingCompileTimeError
+override_inheritance_abstract_test/07: MissingCompileTimeError
 override_inheritance_abstract_test/08: MissingCompileTimeError
 override_inheritance_abstract_test/09: MissingCompileTimeError
 override_inheritance_abstract_test/10: MissingCompileTimeError
@@ -779,7 +780,6 @@
 override_inheritance_abstract_test/24: MissingCompileTimeError
 override_inheritance_abstract_test/25: MissingCompileTimeError
 override_inheritance_abstract_test/26: MissingCompileTimeError
-override_inheritance_abstract_test/28: MissingCompileTimeError
 override_inheritance_field_test/05: MissingCompileTimeError
 override_inheritance_field_test/07: MissingCompileTimeError
 override_inheritance_field_test/08: MissingCompileTimeError
@@ -824,7 +824,6 @@
 override_inheritance_mixed_test/08: MissingCompileTimeError
 override_inheritance_mixed_test/09: MissingCompileTimeError
 override_inheritance_no_such_method_test/01: MissingCompileTimeError
-override_inheritance_no_such_method_test/02: MissingCompileTimeError
 override_inheritance_no_such_method_test/06: MissingCompileTimeError
 override_inheritance_no_such_method_test/07: MissingCompileTimeError
 override_inheritance_no_such_method_test/09: MissingCompileTimeError
diff --git a/tests/language_2/language_2_vm.status b/tests/language_2/language_2_vm.status
index 3c012b6..8e3a8e3 100644
--- a/tests/language_2/language_2_vm.status
+++ b/tests/language_2/language_2_vm.status
@@ -774,6 +774,7 @@
 override_inheritance_abstract_test/02: MissingCompileTimeError
 override_inheritance_abstract_test/03: MissingCompileTimeError
 override_inheritance_abstract_test/04: MissingCompileTimeError
+override_inheritance_abstract_test/07: MissingCompileTimeError
 override_inheritance_abstract_test/08: MissingCompileTimeError
 override_inheritance_abstract_test/09: MissingCompileTimeError
 override_inheritance_abstract_test/10: MissingCompileTimeError
@@ -790,7 +791,6 @@
 override_inheritance_abstract_test/24: MissingCompileTimeError
 override_inheritance_abstract_test/25: MissingCompileTimeError
 override_inheritance_abstract_test/26: MissingCompileTimeError
-override_inheritance_abstract_test/28: MissingCompileTimeError
 override_inheritance_field_test/05: MissingCompileTimeError
 override_inheritance_field_test/07: MissingCompileTimeError
 override_inheritance_field_test/08: MissingCompileTimeError
@@ -834,13 +834,11 @@
 override_inheritance_mixed_test/07: MissingCompileTimeError
 override_inheritance_mixed_test/09: MissingCompileTimeError
 override_inheritance_no_such_method_test/01: MissingCompileTimeError
-override_inheritance_no_such_method_test/02: MissingCompileTimeError
 override_inheritance_no_such_method_test/06: MissingCompileTimeError
 override_inheritance_no_such_method_test/07: MissingCompileTimeError
 override_inheritance_no_such_method_test/09: MissingCompileTimeError
 override_inheritance_no_such_method_test/10: MissingCompileTimeError
 override_inheritance_no_such_method_test/12: MissingCompileTimeError
-override_inheritance_no_such_method_test/13: MissingCompileTimeError
 override_method_with_field_test/02: MissingCompileTimeError
 part2_test/01: MissingCompileTimeError
 positional_parameters_type_test/01: MissingCompileTimeError
@@ -1124,6 +1122,7 @@
 function_type/function_type96_test: RuntimeError # Issue 30475
 function_type/function_type9_test: RuntimeError # Issue 30475
 function_type_alias2_test: RuntimeError
+function_type_alias6_test/none: RuntimeError
 invalid_override_in_mixin_test/01: MissingCompileTimeError
 type_literal_prefix_call_test: RuntimeError
 
diff --git a/tests/language_2/override_inheritance_abstract_test.dart b/tests/language_2/override_inheritance_abstract_test.dart
index bb6c449..026fcf3 100644
--- a/tests/language_2/override_inheritance_abstract_test.dart
+++ b/tests/language_2/override_inheritance_abstract_test.dart
@@ -6,7 +6,7 @@
   method1(); //# 01: ok
   method5(); //# 05: ok
   method6(); //# 06: ok
-  method7();
+  method7(); //# 07: compile-time error
   get getter8; //# 08: compile-time error
   set setter9(_); //# 09: compile-time error
   method10(); //# 10: compile-time error
@@ -44,7 +44,7 @@
   var member21; //# 21: continued
 }
 
-abstract class Class extends A implements I, J {
+class Class extends A implements I, J {
   method1() {} //# 01: continued
   method2(); //# 02: compile-time error
   get getter3; //# 03: compile-time error
@@ -62,5 +62,5 @@
 }
 
 main() {
-  new Class(); //# 28: compile-time error
+  new Class();
 }
diff --git a/tests/language_2/override_inheritance_no_such_method_test.dart b/tests/language_2/override_inheritance_no_such_method_test.dart
index 1f90b47..535f5a4 100644
--- a/tests/language_2/override_inheritance_no_such_method_test.dart
+++ b/tests/language_2/override_inheritance_no_such_method_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.
 
-// Test use of @proxy and noSuchMethod in relation to abstract methods in
+// Test use of noSuchMethod in relation to abstract methods in
 // concrete classes.
 
 abstract class A {
@@ -17,14 +17,9 @@
   method11(); //# 11: ok
 }
 
-@proxy //# 02: compile-time error
-@proxy //# 07: continued
-@proxy //# 10: continued
 class Class1 extends A implements I {
   method1(); //# 01: compile-time error
 
-  method2(); //# 02: continued
-
   noSuchMethod(_) => null; //# 03: ok
   method3(); //# 03: continued
 
@@ -39,11 +34,10 @@
   noSuchMethod(_) => null; //# 11: continued
 }
 
-@proxy //# 12: compile-time error
 class B {
-  method12(); //# 12: continued
+  method12(); //# 12: compile-time error
 
-  noSuchMethod(_) => null; //# 13: compile-time error
+  noSuchMethod(_) => null; //# 13: ok
   method13(); //# 13: continued
 }
 
diff --git a/tests/language_2/ref_before_declaration_test.dart b/tests/language_2/ref_before_declaration_test.dart
index d5b8908..65f58ac 100644
--- a/tests/language_2/ref_before_declaration_test.dart
+++ b/tests/language_2/ref_before_declaration_test.dart
@@ -66,7 +66,7 @@
 }
 
 void testLibPrefix() {
-  var pie = math.PI;
+  var pie = math.pi;
   final math = 0; // //# 05: compile-time error
 }
 
diff --git a/tests/language_2/syntax_test.dart b/tests/language_2/syntax_test.dart
index 0982b99..5946a1d 100644
--- a/tests/language_2/syntax_test.dart
+++ b/tests/language_2/syntax_test.dart
@@ -112,7 +112,9 @@
 
 class ListFactory<E> implements List<E>
 native "Array" //# 33: syntax error
-{}
+{
+  noSuchMethod(_) => null; // Allow unimplemented methods
+}
 
 abstract class I implements UNKNOWN; //# 34: syntax error
 
@@ -138,7 +140,9 @@
 
 class XListFactory<E> implements List<E>
 hest "Array" //# 40: syntax error
-{}
+{
+  noSuchMethod(_) => null; // Allow unimplemented methods
+}
 
 class YWindow extends DOMWindow
 for "*Window" //# 41: syntax error
@@ -162,7 +166,9 @@
 
 class YListFactory<E> implements List<E>
 for "Array" //# 46: syntax error
-{}
+{
+  noSuchMethod(_) => null; // Allow unimplemented methods
+}
 
 class A {
   const A()
diff --git a/tests/lib_2/async/null_future_zone_test.dart b/tests/lib_2/async/null_future_zone_test.dart
deleted file mode 100644
index 802c399..0000000
--- a/tests/lib_2/async/null_future_zone_test.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2013, 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";
-import "package:async_helper/async_helper.dart";
-import 'dart:async';
-
-main() {
-  asyncStart(2);
-  () async {
-    var it = new StreamIterator(new Stream.fromIterable([]));
-    Expect.isFalse(await it.moveNext());
-
-    Future nullFuture;
-    Future falseFuture;
-
-    runZoned(() {
-      nullFuture = (new StreamController()..stream.listen(null).cancel()).done;
-      falseFuture = it.moveNext();
-    }, zoneSpecification: new ZoneSpecification(scheduleMicrotask:
-        (Zone self, ZoneDelegate parent, Zone zone, void f()) {
-      Expect.fail("Should not be called");
-    }));
-
-    nullFuture.then((value) {
-      Expect.isNull(value);
-      asyncEnd();
-    });
-
-    falseFuture.then((value) {
-      Expect.isFalse(value);
-      asyncEnd();
-    });
-  }();
-}
diff --git a/tests/lib_2/convert/html_escape_test.dart b/tests/lib_2/convert/html_escape_test.dart
index 55de638..f40c18d 100644
--- a/tests/lib_2/convert/html_escape_test.dart
+++ b/tests/lib_2/convert/html_escape_test.dart
@@ -75,7 +75,7 @@
 const _COUNT = 3;
 
 void main() {
-  _testMode(HTML_ESCAPE, _TEST_INPUT, _OUTPUT_UNKNOWN);
+  _testMode(htmlEscape, _TEST_INPUT, _OUTPUT_UNKNOWN);
   _testMode(const HtmlEscape(), _TEST_INPUT, _OUTPUT_UNKNOWN);
   _testMode(
       const HtmlEscape(HtmlEscapeMode.unknown), _TEST_INPUT, _OUTPUT_UNKNOWN);
@@ -85,5 +85,5 @@
       _OUTPUT_SQ_ATTRIBUTE);
   _testMode(
       const HtmlEscape(HtmlEscapeMode.element), _TEST_INPUT, _OUTPUT_ELEMENT);
-  _testMode(HTML_ESCAPE, _NOOP, _NOOP);
+  _testMode(htmlEscape, _NOOP, _NOOP);
 }
diff --git a/tests/lib_2/math/double_pow_test.dart b/tests/lib_2/math/double_pow_test.dart
index 4d95575..4feac67 100644
--- a/tests/lib_2/math/double_pow_test.dart
+++ b/tests/lib_2/math/double_pow_test.dart
@@ -153,8 +153,8 @@
 
   // Some non-exceptional values.
   checkVeryClose(16.0, pow(4.0, 2.0));
-  checkVeryClose(SQRT2, pow(2.0, 0.5));
-  checkVeryClose(SQRT1_2, pow(0.5, 0.5));
+  checkVeryClose(sqrt2, pow(2.0, 0.5));
+  checkVeryClose(sqrt1_2, pow(0.5, 0.5));
   // Denormal result.
   Expect.identical(5e-324, pow(2.0, -1074.0));
   // Overflow.
diff --git a/tests/lib_2/math/math2_test.dart b/tests/lib_2/math/math2_test.dart
index e24e3b2..83f0183 100644
--- a/tests/lib_2/math/math2_test.dart
+++ b/tests/lib_2/math/math2_test.dart
@@ -14,21 +14,21 @@
   static void testConstants() {
     // Source for mathematical constants is Wolfram Alpha.
     Expect.equals(
-        2.7182818284590452353602874713526624977572470936999595749669, math.E);
+        2.7182818284590452353602874713526624977572470936999595749669, math.e);
     Expect.equals(2.3025850929940456840179914546843642076011014886287729760333,
-        math.LN10);
+        math.ln10);
     Expect.equals(
-        0.6931471805599453094172321214581765680755001343602552541206, math.LN2);
+        0.6931471805599453094172321214581765680755001343602552541206, math.ln2);
     Expect.equals(1.4426950408889634073599246810018921374266459541529859341354,
-        math.LOG2E);
+        math.log2e);
     Expect.equals(0.4342944819032518276511289189166050822943970058036665661144,
-        math.LOG10E);
+        math.log10e);
     Expect.equals(
-        3.1415926535897932384626433832795028841971693993751058209749, math.PI);
+        3.1415926535897932384626433832795028841971693993751058209749, math.pi);
     Expect.equals(0.7071067811865475244008443621048490392848359376884740365883,
-        math.SQRT1_2);
+        math.sqrt1_2);
     Expect.equals(1.4142135623730950488016887242096980785696718753769480731766,
-        math.SQRT2);
+        math.sqrt2);
   }
 
   static checkClose(double a, double b, EPSILON) {
@@ -37,65 +37,65 @@
   }
 
   static void testSin() {
-    // Given the imprecision of PI we can't expect better results than this.
+    // Given the imprecision of pi we can't expect better results than this.
     final double EPSILON = 1e-15;
     checkClose(0.0, math.sin(0.0), EPSILON);
-    checkClose(0.0, math.sin(math.PI), EPSILON);
-    checkClose(0.0, math.sin(2.0 * math.PI), EPSILON);
-    checkClose(1.0, math.sin(math.PI / 2.0), EPSILON);
-    checkClose(-1.0, math.sin(math.PI * (3.0 / 2.0)), EPSILON);
+    checkClose(0.0, math.sin(math.pi), EPSILON);
+    checkClose(0.0, math.sin(2.0 * math.pi), EPSILON);
+    checkClose(1.0, math.sin(math.pi / 2.0), EPSILON);
+    checkClose(-1.0, math.sin(math.pi * (3.0 / 2.0)), EPSILON);
   }
 
   static void testCos() {
-    // Given the imprecision of PI we can't expect better results than this.
+    // Given the imprecision of pi we can't expect better results than this.
     final double EPSILON = 1e-15;
     checkClose(1.0, math.cos(0.0), EPSILON);
-    checkClose(-1.0, math.cos(math.PI), EPSILON);
-    checkClose(1.0, math.cos(2.0 * math.PI), EPSILON);
-    checkClose(0.0, math.cos(math.PI / 2.0), EPSILON);
-    checkClose(0.0, math.cos(math.PI * (3.0 / 2.0)), EPSILON);
+    checkClose(-1.0, math.cos(math.pi), EPSILON);
+    checkClose(1.0, math.cos(2.0 * math.pi), EPSILON);
+    checkClose(0.0, math.cos(math.pi / 2.0), EPSILON);
+    checkClose(0.0, math.cos(math.pi * (3.0 / 2.0)), EPSILON);
   }
 
   static void testTan() {
-    // Given the imprecision of PI we can't expect better results than this.
+    // Given the imprecision of pi we can't expect better results than this.
     final double EPSILON = 1e-15;
     checkClose(0.0, math.tan(0.0), EPSILON);
-    checkClose(0.0, math.tan(math.PI), EPSILON);
-    checkClose(0.0, math.tan(2.0 * math.PI), EPSILON);
-    checkClose(1.0, math.tan(math.PI / 4.0), EPSILON);
+    checkClose(0.0, math.tan(math.pi), EPSILON);
+    checkClose(0.0, math.tan(2.0 * math.pi), EPSILON);
+    checkClose(1.0, math.tan(math.pi / 4.0), EPSILON);
   }
 
   static void testAsin() {
-    // Given the imprecision of PI we can't expect better results than this.
+    // Given the imprecision of pi we can't expect better results than this.
     final double EPSILON = 1e-15;
     checkClose(0.0, math.asin(0.0), EPSILON);
-    checkClose(math.PI / 2.0, math.asin(1.0), EPSILON);
-    checkClose(-math.PI / 2.0, math.asin(-1.0), EPSILON);
+    checkClose(math.pi / 2.0, math.asin(1.0), EPSILON);
+    checkClose(-math.pi / 2.0, math.asin(-1.0), EPSILON);
   }
 
   static void testAcos() {
-    // Given the imprecision of PI we can't expect better results than this.
+    // Given the imprecision of pi we can't expect better results than this.
     final double EPSILON = 1e-15;
     checkClose(0.0, math.acos(1.0), EPSILON);
-    checkClose(math.PI, math.acos(-1.0), EPSILON);
-    checkClose(math.PI / 2.0, math.acos(0.0), EPSILON);
+    checkClose(math.pi, math.acos(-1.0), EPSILON);
+    checkClose(math.pi / 2.0, math.acos(0.0), EPSILON);
   }
 
   static void testAtan() {
-    // Given the imprecision of PI we can't expect better results than this.
+    // Given the imprecision of pi we can't expect better results than this.
     final double EPSILON = 1e-15;
     checkClose(0.0, math.atan(0.0), EPSILON);
-    checkClose(math.PI / 4.0, math.atan(1.0), EPSILON);
-    checkClose(-math.PI / 4.0, math.atan(-1.0), EPSILON);
+    checkClose(math.pi / 4.0, math.atan(1.0), EPSILON);
+    checkClose(-math.pi / 4.0, math.atan(-1.0), EPSILON);
   }
 
   static void testAtan2() {
-    // Given the imprecision of PI we can't expect better results than this.
+    // Given the imprecision of pi we can't expect better results than this.
     final double EPSILON = 1e-15;
     checkClose(0.0, math.atan2(0.0, 5.0), EPSILON);
-    checkClose(math.PI / 4.0, math.atan2(2.0, 2.0), EPSILON);
-    checkClose(3 * math.PI / 4.0, math.atan2(0.5, -0.5), EPSILON);
-    checkClose(-3 * math.PI / 4.0, math.atan2(-2.5, -2.5), EPSILON);
+    checkClose(math.pi / 4.0, math.atan2(2.0, 2.0), EPSILON);
+    checkClose(3 * math.pi / 4.0, math.atan2(0.5, -0.5), EPSILON);
+    checkClose(-3 * math.pi / 4.0, math.atan2(-2.5, -2.5), EPSILON);
   }
 
   static checkVeryClose(double a, double b) {
@@ -127,32 +127,32 @@
 
   static void testSqrt() {
     checkVeryClose(2.0, math.sqrt(4.0));
-    checkVeryClose(math.SQRT2, math.sqrt(2.0));
-    checkVeryClose(math.SQRT1_2, math.sqrt(0.5));
+    checkVeryClose(math.sqrt2, math.sqrt(2.0));
+    checkVeryClose(math.sqrt1_2, math.sqrt(0.5));
     checkVeryClose(1e50, math.sqrt(1e100));
     checkVeryClose(1.1111111061110855443054405046358901279277111935183977e56,
         math.sqrt(12345678901234e99));
   }
 
   static void testExp() {
-    checkVeryClose(math.E, math.exp(1.0));
+    checkVeryClose(math.e, math.exp(1.0));
     final EPSILON = 1e-15;
-    checkClose(10.0, math.exp(math.LN10), EPSILON);
-    checkClose(2.0, math.exp(math.LN2), EPSILON);
+    checkClose(10.0, math.exp(math.ln10), EPSILON);
+    checkClose(2.0, math.exp(math.ln2), EPSILON);
   }
 
   static void testLog() {
     // Even though E is imprecise, it is good enough to get really close to 1.
     // We still provide an epsilon.
-    checkClose(1.0, math.log(math.E), 1e-16);
-    checkVeryClose(math.LN10, math.log(10.0));
-    checkVeryClose(math.LN2, math.log(2.0));
+    checkClose(1.0, math.log(math.e), 1e-16);
+    checkVeryClose(math.ln10, math.log(10.0));
+    checkVeryClose(math.ln2, math.log(2.0));
   }
 
   static void testPow() {
     checkVeryClose(16.0, math.pow(4.0, 2.0));
-    checkVeryClose(math.SQRT2, math.pow(2.0, 0.5));
-    checkVeryClose(math.SQRT1_2, math.pow(0.5, 0.5));
+    checkVeryClose(math.sqrt2, math.pow(2.0, 0.5));
+    checkVeryClose(math.sqrt1_2, math.pow(0.5, 0.5));
   }
 
   static bool parseIntThrowsFormatException(str) {
diff --git a/tests/lib_2/math/math_test.dart b/tests/lib_2/math/math_test.dart
index 3e1e879..ca32951 100644
--- a/tests/lib_2/math/math_test.dart
+++ b/tests/lib_2/math/math_test.dart
@@ -11,21 +11,21 @@
   static void testConstants() {
     // Source for mathematical constants is Wolfram Alpha.
     Expect.equals(
-        2.7182818284590452353602874713526624977572470936999595749669, E);
+        2.7182818284590452353602874713526624977572470936999595749669, e);
     Expect.equals(
-        2.3025850929940456840179914546843642076011014886287729760333, LN10);
+        2.3025850929940456840179914546843642076011014886287729760333, ln10);
     Expect.equals(
-        0.6931471805599453094172321214581765680755001343602552541206, LN2);
+        0.6931471805599453094172321214581765680755001343602552541206, ln2);
     Expect.equals(
-        1.4426950408889634073599246810018921374266459541529859341354, LOG2E);
+        1.4426950408889634073599246810018921374266459541529859341354, log2e);
     Expect.equals(
-        0.4342944819032518276511289189166050822943970058036665661144, LOG10E);
+        0.4342944819032518276511289189166050822943970058036665661144, log10e);
     Expect.equals(
-        3.1415926535897932384626433832795028841971693993751058209749, PI);
+        3.1415926535897932384626433832795028841971693993751058209749, pi);
     Expect.equals(
-        0.7071067811865475244008443621048490392848359376884740365883, SQRT1_2);
+        0.7071067811865475244008443621048490392848359376884740365883, sqrt1_2);
     Expect.equals(
-        1.4142135623730950488016887242096980785696718753769480731766, SQRT2);
+        1.4142135623730950488016887242096980785696718753769480731766, sqrt2);
   }
 
   static checkClose(double a, double b, EPSILON) {
@@ -34,65 +34,65 @@
   }
 
   static void testSin() {
-    // Given the imprecision of PI we can't expect better results than this.
+    // Given the imprecision of pi we can't expect better results than this.
     final double EPSILON = 1e-15;
     checkClose(0.0, sin(0.0), EPSILON);
-    checkClose(0.0, sin(PI), EPSILON);
-    checkClose(0.0, sin(2.0 * PI), EPSILON);
-    checkClose(1.0, sin(PI / 2.0), EPSILON);
-    checkClose(-1.0, sin(PI * (3.0 / 2.0)), EPSILON);
+    checkClose(0.0, sin(pi), EPSILON);
+    checkClose(0.0, sin(2.0 * pi), EPSILON);
+    checkClose(1.0, sin(pi / 2.0), EPSILON);
+    checkClose(-1.0, sin(pi * (3.0 / 2.0)), EPSILON);
   }
 
   static void testCos() {
-    // Given the imprecision of PI we can't expect better results than this.
+    // Given the imprecision of pi we can't expect better results than this.
     final double EPSILON = 1e-15;
     checkClose(1.0, cos(0.0), EPSILON);
-    checkClose(-1.0, cos(PI), EPSILON);
-    checkClose(1.0, cos(2.0 * PI), EPSILON);
-    checkClose(0.0, cos(PI / 2.0), EPSILON);
-    checkClose(0.0, cos(PI * (3.0 / 2.0)), EPSILON);
+    checkClose(-1.0, cos(pi), EPSILON);
+    checkClose(1.0, cos(2.0 * pi), EPSILON);
+    checkClose(0.0, cos(pi / 2.0), EPSILON);
+    checkClose(0.0, cos(pi * (3.0 / 2.0)), EPSILON);
   }
 
   static void testTan() {
-    // Given the imprecision of PI we can't expect better results than this.
+    // Given the imprecision of pi we can't expect better results than this.
     final double EPSILON = 1e-15;
     checkClose(0.0, tan(0.0), EPSILON);
-    checkClose(0.0, tan(PI), EPSILON);
-    checkClose(0.0, tan(2.0 * PI), EPSILON);
-    checkClose(1.0, tan(PI / 4.0), EPSILON);
+    checkClose(0.0, tan(pi), EPSILON);
+    checkClose(0.0, tan(2.0 * pi), EPSILON);
+    checkClose(1.0, tan(pi / 4.0), EPSILON);
   }
 
   static void testAsin() {
-    // Given the imprecision of PI we can't expect better results than this.
+    // Given the imprecision of pi we can't expect better results than this.
     final double EPSILON = 1e-15;
     checkClose(0.0, asin(0.0), EPSILON);
-    checkClose(PI / 2.0, asin(1.0), EPSILON);
-    checkClose(-PI / 2.0, asin(-1.0), EPSILON);
+    checkClose(pi / 2.0, asin(1.0), EPSILON);
+    checkClose(-pi / 2.0, asin(-1.0), EPSILON);
   }
 
   static void testAcos() {
-    // Given the imprecision of PI we can't expect better results than this.
+    // Given the imprecision of pi we can't expect better results than this.
     final double EPSILON = 1e-15;
     checkClose(0.0, acos(1.0), EPSILON);
-    checkClose(PI, acos(-1.0), EPSILON);
-    checkClose(PI / 2.0, acos(0.0), EPSILON);
+    checkClose(pi, acos(-1.0), EPSILON);
+    checkClose(pi / 2.0, acos(0.0), EPSILON);
   }
 
   static void testAtan() {
-    // Given the imprecision of PI we can't expect better results than this.
+    // Given the imprecision of pi we can't expect better results than this.
     final double EPSILON = 1e-15;
     checkClose(0.0, atan(0.0), EPSILON);
-    checkClose(PI / 4.0, atan(1.0), EPSILON);
-    checkClose(-PI / 4.0, atan(-1.0), EPSILON);
+    checkClose(pi / 4.0, atan(1.0), EPSILON);
+    checkClose(-pi / 4.0, atan(-1.0), EPSILON);
   }
 
   static void testAtan2() {
-    // Given the imprecision of PI we can't expect better results than this.
+    // Given the imprecision of pi we can't expect better results than this.
     final double EPSILON = 1e-15;
     checkClose(0.0, atan2(0.0, 5.0), EPSILON);
-    checkClose(PI / 4.0, atan2(2.0, 2.0), EPSILON);
-    checkClose(3 * PI / 4.0, atan2(0.5, -0.5), EPSILON);
-    checkClose(-3 * PI / 4.0, atan2(-2.5, -2.5), EPSILON);
+    checkClose(pi / 4.0, atan2(2.0, 2.0), EPSILON);
+    checkClose(3 * pi / 4.0, atan2(0.5, -0.5), EPSILON);
+    checkClose(-3 * pi / 4.0, atan2(-2.5, -2.5), EPSILON);
   }
 
   static checkVeryClose(double a, double b) {
@@ -124,26 +124,26 @@
 
   static void testSqrt() {
     checkVeryClose(2.0, sqrt(4.0));
-    checkVeryClose(SQRT2, sqrt(2.0));
-    checkVeryClose(SQRT1_2, sqrt(0.5));
+    checkVeryClose(sqrt2, sqrt(2.0));
+    checkVeryClose(sqrt1_2, sqrt(0.5));
     checkVeryClose(1e50, sqrt(1e100));
     checkVeryClose(1.1111111061110855443054405046358901279277111935183977e56,
         sqrt(12345678901234e99));
   }
 
   static void testExp() {
-    checkVeryClose(E, exp(1.0));
+    checkVeryClose(e, exp(1.0));
     final EPSILON = 1e-15;
-    checkClose(10.0, exp(LN10), EPSILON);
-    checkClose(2.0, exp(LN2), EPSILON);
+    checkClose(10.0, exp(ln10), EPSILON);
+    checkClose(2.0, exp(ln2), EPSILON);
   }
 
   static void testLog() {
     // Even though E is imprecise, it is good enough to get really close to 1.
     // We still provide an epsilon.
-    checkClose(1.0, log(E), 1e-16);
-    checkVeryClose(LN10, log(10.0));
-    checkVeryClose(LN2, log(2.0));
+    checkClose(1.0, log(e), 1e-16);
+    checkVeryClose(ln10, log(10.0));
+    checkVeryClose(ln2, log(2.0));
   }
 
   static bool parseIntThrowsFormatException(str) {
diff --git a/tests/lib_2/math/pi_test.dart b/tests/lib_2/math/pi_test.dart
index aec9789..ea31ade 100644
--- a/tests/lib_2/math/pi_test.dart
+++ b/tests/lib_2/math/pi_test.dart
@@ -48,5 +48,5 @@
   // Mmmmh, Pie!
   var pie = 4.0 * (inside / (inside + outside));
   print("$pie");
-  Expect.isTrue(((PI - 0.009) < pie) && (pie < (PI + 0.009)));
+  Expect.isTrue(((pi - 0.009) < pie) && (pie < (pi + 0.009)));
 }
diff --git a/tests/standalone_2/io/certificates/bad_server_chain.pem b/tests/standalone_2/io/certificates/bad_server_chain.pem
new file mode 100644
index 0000000..3c5024b
--- /dev/null
+++ b/tests/standalone_2/io/certificates/bad_server_chain.pem
@@ -0,0 +1,58 @@
+-----BEGIN CERTIFICATE-----
+MIIDJzCCAg+gAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
+cm1lZGlhdGVhdXRob3JpdHkwHhcNMTgwNDIzMjAxNjM0WhcNMjgwNDIwMjAxNjM0
+WjAXMRUwEwYDVQQDDAxiYWRsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQC6gVBNsFLEkomxJ1VRe5rZ1ELduRLHJKio9zTrh+o/6EaCZ4X6
+EIr3CwVx7UiBDRyCApGZXbqvtNbP/ihbjRvxmlvCSL9ztF9tNrLqsaEq4w5KvQDT
+5u27+pAzdLjjoFTK6VZfw+AhEZHxiokEDDYB3t6gWkfabOstDouLyEYL25RLKaGQ
+v/Qb7XU6K4f20OnuXVoQ4FxNdqtvm7TgmXBT0kp+f62q6BvLUIzewpblBlgT5h3h
+KAZF7RDpGBxRgYxA6ZH4n3mv4kh84YtTODRGfb8ugdaQjrgTWOhQ4nddcdR5TVww
+A8Jp+G000RQ97Go0zgd29CicKF96zbGdKFkZAgMBAAGjdTBzMAwGA1UdEwEB/wQC
+MAAwHQYDVR0OBBYEFG8s5yvy1kAoNjJ5PYrx9RNSPFJXMB8GA1UdIwQYMBaAFCpT
+tHybjDJ/Jz25uI9Bxikc1muYMA4GA1UdDwEB/wQEAwIDqDATBgNVHSUEDDAKBggr
+BgEFBQcDATANBgkqhkiG9w0BAQsFAAOCAQEAgom55wfxp9ywWKZOzaGCa+uXZjPK
+rmdUcnJLduRdnchuIsQUZa3Ijpzn7Dw+UZV8ggxvU0L07PbT0QlZUoKhDj6BlZ4W
+TAseBh5QyBUeEdMU+Tr2fXGM6+mmVURBLTX5I2Chmnw2ymqqUK8MtbUhPXbfZayV
+eUV35iloOhm3q/5rKBtfdNq31zrg+Naam6/UyRgBhinweFFXiYeZRpctD3w3cA3g
+RGjuNNNRASZZzAXGiE4IOv9drd0/wGajwBT1DJDQOAxZPfADC3wEcDRG4ve1SYHY
+5N3AlidXe8dPDePhlxH3JH9s2WPi6lgiHQSmtzyeehbzqpJ9JCBM5BerdQ==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDLjCCAhagAwIBAgIBAjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE4MDQyMzIwMTYzM1oXDTI4MDQyMDIwMTYzM1owIDEeMBwG
+A1UEAwwVaW50ZXJtZWRpYXRlYXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAsSFr3/sYhGFF7gEZSn7Am8ATtPhTo5ypQqSAv/4Uy+k4zvT3
+b3OZyYpzr5Wsa6NXcEKwNipyR1GBpYwaYI/W4DSi+COdH4DQSZDQFr+hvmXRazzj
+VSsOxF6veGLcza53meLPRb4o4yVoZARd6xR5i3OUD4kezvOjpmlFT3OKNU0Di+Vq
+qeS14/at6Vt6G0rS8CluafD7Z0/5zp6vrImKwC6OWzlmmcAqBGsE/BTzrAxLdt4K
+uw3Xs3uvS3YZIAC536C1Mop1n4FBUGxeUMWH+I/llzK9ol1pmQHJrxfOD5WdFuuE
+iFfpiOmBdUfDBbEPllmIvzUBFOo5VhxVmq8EHQIDAQABo3sweTASBgNVHRMBAf8E
+CDAGAQH/AgEAMB0GA1UdDgQWBBQqU7R8m4wyfyc9ubiPQcYpHNZrmDAfBgNVHSME
+GDAWgBT0rD9lRUhqJvAg7hfBEz/ZqHCzHjAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
+BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAGjRSFvVeIrRF3iuA5vr
+SgufTCNzAyEz7+pDKflzHSQXF1fdItiOdPGv1i57gIr7HaYuxvBiEklhmnWreYye
+Tn6ghfhEHhdZHBpihDXuIvLizhtR/lg9CDZrHjuY6nukyx4JnWwUBR3TulPK5gJu
+jB9YISY8tjXrvVNqdi0a+G0T4HHnVs3v6Nd/Qdsxfp4maAB1U3HFmR3DXKTxDtBK
+mNNMqf9PpX4lw4o6UieiEwOMd+4REhmwLNTwhWrhVg5q6GKQl873Ge/7J2nXvgkH
+nUbEsncLsArqqrz201f2m32A6pinwY/j85vEeRkHwlsU0jOvVnHzAlggP0u/kFAF
+EjE=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIC/jCCAeagAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE4MDQyMzIwMTYzM1oXDTI4MDQyMDIwMTYzM1owGDEWMBQG
+A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBALkvRWdbx9GwxePkh0nnpht4MrPW5NkZBORqfhFi7PFbQ7Rwgl39hm9iAmci
+pOWZGSJi7AaqLuSID0UEeRdG/fNFawI5XIoxP+TmdKdrk/SaTJQKKJiZ9B8+EG0z
+hV8/v6jrlwj0gq9eBBAmOInnmQiEYE4gKFNvh9xdP//gi+otBf30gmtJ4AxXOTu/
+M+XEigXelmIvy57b+B+qnonTFcGkXhSr+JfCA1l6ta7OtknQtItpV0FDr/d8hA+6
+Bn25ZSisd00GC3CUMX1tM5V8cQE6GO/W2mnpUFVvWycYx9wDyU7rlyNUf8nWeoIW
+3d3s/6KAppa07KrkLiTantIrqMUCAwEAAaNTMFEwHQYDVR0OBBYEFPSsP2VFSGom
+8CDuF8ETP9mocLMeMB8GA1UdIwQYMBaAFPSsP2VFSGom8CDuF8ETP9mocLMeMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ1VynTevPnNtwevQpUa
+zlur64N+Dx/yF4gvd4byjO+JouMJLaJqV2dwnqgAahg6YKasVtv4xX9MVJR2IjIb
+Tfa0nYQxM5clwk3J78nh82Ncb2RNeYJyNmSdocnOkmTSoOGUFOxtRz1vmKUcrfwl
+yENO/qGe/sYmOv0IWJjeGQ2OZPblRumV4dJy3qTHFmOLpYwA0BGiIV5uj5Ou7QU1
+R5PY2pnJg4RXeaq95Pr50lkO9vpRyFUJHjR+P+J05M9FbjLPOQIFkpMYx/GyBg5n
+P+omyagOGW8bXfBTtUYu+rP/k+BC5AxI3Kdv/AD5vyHKi/JXhP3ycb8AYx5ENHoK
+qjA=
+-----END CERTIFICATE-----
diff --git a/tests/standalone_2/io/certificates/bad_server_key.pem b/tests/standalone_2/io/certificates/bad_server_key.pem
new file mode 100644
index 0000000..4b5670a
--- /dev/null
+++ b/tests/standalone_2/io/certificates/bad_server_key.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE4zAcBgoqhkiG9w0BDAEBMA4ECPLRqWLveTDuAgIIAASCBMGjMwpu3Hy4cuO7
+i3p2EyH+UJGm9J/KcRN2ys6E5rwCdLHtURLmdWsmtNkDNTvmgdllXfdVhO9XavRJ
+ShBSvTzvOokpl/nxRaFmhEhMWskdGpP1WSp+GtQiVHM2gczDR2jNZDZKWEnZfU5B
+CUt0VJkokJZxmdeSpFIrTTJxcOQZEsbb1ujrAMpWqEvIGq+U2Is7A5RxWJl1XKmY
+5QB9nfw5Olj0J499kMKJx8WjRhmfQHu+qMpN2HglBVK44fnk/I5ilNdhuScuaKPZ
+csOv5D5Ojlgc6hQG1zCPh8lRNH1MXLd2BMwEJqPSKNbvfrUWvr7BnJMoOdnlZwaH
+73/zJrMwuUpZzAm2sgHZlJhELoYyK0A40IhAz4u9XF1iv35yK2D6/O2qJO6VUzqD
+TsdSnUYaUTZkZdgfucR+EbmPSw7r+QYEsHFzErPTUR64hwIeC3bCv0Q4hrPskxKj
+135iDQDbuCykeNe8s51qgEt8oawdig/Anaguksuj/eKGTWZXPrhA3LTYqBkaX8ao
+XFWkj3ALvjRHCeLfQ5AlXyd3mJiHl93pxH9GIaTiL66ptYvfcN5tERcD6GL/sUXh
+vJ0kr8HsBS9WTFvVg4dzQ9NAqtRoDB1IUqEq2dLys/gjrhE26tmUnuaXiOuokSWx
+HXEK/2pWAqZ/ZA7vbQ/DyV25TDeEP3SRKeTDLdlWBjTNUKyBv3nfsoZBK1K2wOUh
+UDmB3TMBEdXI6L2FvjxMuDRJxruhn7HhRz7ifsizRHPyaPDbUFF9IK/x9qPAzufK
+lk6NqqcgJdNg8wxv/dVYAHeJmMOhTau9CL6N7AYo2VDWphlZSjBgtTZw7sY739c2
+35ziR9yBoJyveFcQko01ycJrjhivn3cqbFXZfsIbecDKz+8qZhWjKw/yysv0X6tI
+tB1btpWtlVB8h7WlXWgUGJWKCUFXRC1fCJA5W7LoTnvZ9VvYMBRKUbDsMiSWNcTZ
+mLmJj0yIhve9uCHsFXBidTCT751CYucaZYvOqNr3pKf4eTQQNCYB5Pt6jx4V7Xks
+ZDjr5ljVy6Ux6NweQT2Zs/hOnuS3q1XoLbRVsW9d9YttahnNyjP8il3HphSzBHOF
+SUReTlgAHEbSUZTZ1z2GXFblUJPb2syfJOIXP5qHQtSrGN3CkQ//JvysxlOck41h
+fLO6TZUadorgEHqb+en6h6gVvDvI3i0T66yWwurhlEvWZepAWetzSv64VsVGXEjc
+lrT8yj6AAZYISoYZU0vtM0tP+FDqvyA597DZMiDDBU6chmGxWhcnaqIIDTP2KQIJ
+Z0NAYp924NHAgnTq1FbXxllej6vxcCwymsnXGyCMhsOt1RTAVHeY0uZ5qPCToJ30
+xS/WTrVH5z0xtp2Qz+INFleNnseYKBJvEDfk+gK0sLm533fehnFeB+GgNqqV9hKc
+bLpU+C3VrsxX0JLWYgfweVDT+jT78FXzUIkWykvBGv+iv+ztFUFiopDzJzfLriH8
+K4kG2o/K3MQWrygjnt+iTjpBe08auX9Ot8X65ygArOa0zOy0nUwSQGyPXL/7L3dQ
+LqS6ZBpreqXClTeegKH8SwEYnXLFNDuU1GuD+pRyQJVWYfqiiWeenaKpCi73VWaK
+J+9e86VqcQ==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/standalone_2/io/certificates/client1.p12 b/tests/standalone_2/io/certificates/client1.p12
index 8d19d04..69a674d 100644
--- a/tests/standalone_2/io/certificates/client1.p12
+++ b/tests/standalone_2/io/certificates/client1.p12
Binary files differ
diff --git a/tests/standalone_2/io/certificates/client1.pem b/tests/standalone_2/io/certificates/client1.pem
index 429cd72..468a677 100644
--- a/tests/standalone_2/io/certificates/client1.pem
+++ b/tests/standalone_2/io/certificates/client1.pem
@@ -1,19 +1,19 @@
 -----BEGIN CERTIFICATE-----
-MIIDBzCCAe+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9jbGll
-bnRhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1WjAQMQ4w
-DAYDVQQDDAV1c2VyMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALlg
-zRZlohMtAg44+kPk04G/gIkdeyh7toUA3nR/2sS11j8EutHewezvMV8YyxBxQn8f
-8x8FkDbrE/6GYg2Dsu6TxrXIFre9Lt5jLlJi/6qEaVtXNTdP3vKO87FJ7YVLCeYe
-MxuTCdHloeUICP5x3GJz3AVdcg/S9qRWrpm8LdRdFk66l8vD+aDf+Oqe+mLVtAr6
-kqkdq1nUJOkRBp+zFMmB3Zfm28aYew6BmFQSscxemZyJxiv4dB+EDr821kEjgGBY
-IQGpdADrfh3j9JAzEr30o6sjfr6QWKHG6ZD7xhSl7rIxmx1yoKoJh8vLpcQfdv79
-7VZZT5N7xjz0xkjqTA0CAwEAAaNiMGAwCQYDVR0TBAIwADAdBgNVHQ4EFgQUMpcX
-0o3lu3BTmaKwCfIJMO5aMs4wHwYDVR0jBBgwFoAUtyLBueMoMi7TborRvM7CnwOi
-SQ4wEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAAB1rNFg
-wdK79r7WO0OvE90uvtFf8sO2kqwW/7JIP/kcnIwIIkNiffUEfLfVr7aecK0rPer4
-DDZFAciuaOcts7dTxXRU+la1ZEPaEyx1mHaC6HJbgFYC9cG30L6GJGkZkIGOCTn+
-/yPxTM//dSc7YACc90GNTeUFVnAw6vskH91Ph4VYbdYxt7L1d1pzvBeun6Qi0eJq
-rkWQ2DOO9h9E6Rnt8Jea3w7WzX5P8pBjm74bv38YBKefawPeiiXck2Q/lUehLePV
-U1MRdy1QWC924+p6cXbR1GEhg0FZyvS/9WdpLMGIat/j/98juN6qyAbw7XXhlB1g
-fBHlfXbx+KMZAuY=
+MIIDBzCCAe+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9jbGll
+bnRhdXRob3JpdHkwHhcNMTgwNDIzMjAxNjM0WhcNMjgwNDIwMjAxNjM0WjAQMQ4w
+DAYDVQQDDAV1c2VyMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ0k
+FC9D1LDt0as0Kk3EbMKR9IXBtKazVOXq1y3VYmSM+r8l70HViKZOQ13vWHBt+iYI
+2ATt+lFfKrAo2xO74d7bJD6ag12Ar60mpfVWO1lrmbSzGGsfJZl1kI7Z9SJ4RQCp
+xqAKu+ZtIY40fO7YqRFT+yPjjdcsNOYHedATa4coq1ZHnFbU4HZgerFIeMCHr2Mb
+MPuqraJuk4G7yJgPWMwNawKKfWWiH4aRNGgmVqInVTh6hLLFC2po0koF8h4fyVz9
+BmptVyn7+/V5OOWteiaaNanRlSc9ozljSxVnqSUD9JuaIINd4+0Lf5Yp2hcPj54l
+Mt8q51euv2JGzk5NLOcCAwEAAaNiMGAwCQYDVR0TBAIwADAdBgNVHQ4EFgQUZOyE
++fTDi2XHfAg9q9Ci4B3/PKIwHwYDVR0jBBgwFoAU+TlPoMTEPn2GHUDuD49Nm+iq
+vwwwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAADdlG1z
+kHKAI4HQojtx8yWM/D5q48/5wQjmsx6oBfaWPobL1mkc0iPQ6GNARY1Mv8OPbGkk
+8M00qVikaUyA3K14mZBzNY1Pprr06JRlDuYZABU7Jcfd6pe1LAfM0GMlng5KbHlK
+NqsECNQNIihEECdJ9UxEl191aAf4hnfvnL+RRaalCCeM9LZY+CTCuG1RH61H8Dxl
+Fq615+4DP7bKHUf2FiYVcqu9MqLCw6YasrCNFcBQuZuzO/3HUyBWHOQ2jb5w5uID
+cDsV5rGtQjc0DNc7v34lHYsfP8BWRF+z/VE865wgupQ3f5OTTHPBeMy1bO0t5rU6
+iDdImoz2KZ3ZwDc=
 -----END CERTIFICATE-----
diff --git a/tests/standalone_2/io/certificates/client1_key.p12 b/tests/standalone_2/io/certificates/client1_key.p12
index 5d11e73..8f5681d 100644
--- a/tests/standalone_2/io/certificates/client1_key.p12
+++ b/tests/standalone_2/io/certificates/client1_key.p12
Binary files differ
diff --git a/tests/standalone_2/io/certificates/client1_key.pem b/tests/standalone_2/io/certificates/client1_key.pem
index 0e2ef5e..16c513c 100644
--- a/tests/standalone_2/io/certificates/client1_key.pem
+++ b/tests/standalone_2/io/certificates/client1_key.pem
@@ -1,29 +1,29 @@
 -----BEGIN ENCRYPTED PRIVATE KEY-----
-MIIE4jAcBgoqhkiG9w0BDAEBMA4ECF4ZB27y60SWAgIIAASCBMCEL3ZCzfC0q+m+
-B8gM9jQe1JFRD5reAuwK6+3speBS4KE+wjbcyQq09/5UoQu3Dci1WG1nKLB1u0Bk
-w9NuRahWCpvVLzz/GQ6Psesixq3V69zD3N6iMl/XQKymQBwGK51xIkeJO+6Skh2d
-+qoyBHINTlKY9+548Zgqu+Z3mI3pGmdhd7hCiamiffDwCLEqRxbXdZdLpC9GpAP5
-HOqXHzN2aZbAGHb1GkHVxskSNzAwlEEZhh4Ibe6o7U65hoL9borewT+gj6sQohI5
-/LHL0P2bVvtRZiwBVPUX8HZWuVYIFb6GEGTTqOofNhNHvHaKUlD8Uxi5/h/Xi8fq
-xpdkjIn7VXj9e+I3TkfiphDtk0+Q+f+UkuPyuzU1PafinPfRK1J6gk+ZqAQHW/sp
-g6GVr2r4PkOrBPsA6jmCnQhs2C4MlZyR2p65qjVutdkKU5NgftW+giK9shgglcza
-38RF8i01THOnD3j+2teM/t/Ziqb2PGWv/bmvhcYqt1aG186Pe3bBCxhh/L7bqNKD
-q7sxDmaDE2pTkfyvh07udarmBQc5gvfXYqwghbqP/n7wizqjeEJgAwwHyi8LLsFV
-XreBQ/8Z2gQwXurrh5WD+7KSgvgopW/oVC8a3++8Hmf5Nkj27lACzoDWTG2/Swah
-O1MmdtPyy/KCbf5ujt2BlXM9D206Rsr6hoO9UZ1s1ohRdJReVGc4NZ4XrVWc4TKT
-gUAFTaHIKgFe/DgLaQn8L8Pqb8B/JfoSgQ74r69S434Kc+EDKui8wnkgso5bqrr1
-M07H9Xo+OtG1D6rma2EUlpoU06CAIcyqNx5fHJ3xfk9GHScQi4U6vEDCAQTNTS65
-I5AOHthZ2kZzfXvP6TF39S5D37NrV7/WJu7ZFaJx3bUGwnS2HYTwjFPABHpVLMwJ
-nBylVJs+h7bCZdBNCWgTytcn1mYMCvXVmrW8VTwBRjUQsy4rgE2wjpZuIM9rx+gZ
-HtNvy5t2RlOSqVKapyvV0ll7qbT1lwGIePxjttiWmNbgbwRBQzjv6FZ1Yo331Fl4
-qgXGcvZWgsgQFPXviKmDx+9KJ2oL35cLnDcMCRN7lLPdAhk8J/XrUq/iIYXNxud6
-f9mfVOsd0LT030je/N25IdEoPimTnps/INGGNug+FuJ3dCeIQGwB7uQB5ozoHL5h
-hzdQYq5+FWksuHPCOL1YLRJux9sH6OYxlXy2oigLtA05EHhq83Wwb2oTW6boo+rs
-gKqzc7OtFgYDsV8R1raoqlzAv3GNgkzyuHTSUakDdnJYmfcoOuK+Ch+MjVeZW5bS
-Ir7uqugUqqI/AiO/eHkvoGpQs0c67ao0qPR7ZQna/1FBj1O8J/dI4JBUtPvDa0tW
-7U+Ja/twJWri+Nn6/iEEWEuM/xx/xFmxrTb4WYza1ysrCls5l6POjQu2n6dT52+o
-cobwltkJmSNoIT2SYRuvEfgGlwyzY5p5B8U24HIAkNJIkO7hc9oD1mbq+K526HNl
-h6TG7RGUOffXIYuykrMmCTRRnv3bXmjTgsvWhVFujpCSQf9PqkQpv+KQPeFmy12h
-TA1QNtdVOZlh2GLEUgZuJVytyEz4m+3BfvBql5K9rlAUSQqsLJDKVxsmBDl132o3
-yy9JR7iC
+MIIE5DAcBgoqhkiG9w0BDAEBMA4ECDBZgjf6kratAgIIAASCBML/IWUC3eylBatQ
+SawxuYM81Ak+LnjidlC+/3APnYNFdppoUbZu8WK9Nj/SPQBXnpuGpVuUWWaIkjzI
+d3tivlboh17M6TBSBiI6wopmi4uO7k+BKTCH0chdqKM8OjJajpeGOfejW7Jojnr8
+Yx8G3IYO5DWWXSU7kp4w5WwN93vvRZh4pmLwOIFLwdGVNooBu1FRBaguPFQoWgO+
+JFbT3qDYvpttdsgtOalqpudHcQteapgQkUfKwk+unB+dgxS3sTTY+Zy9ClnArd0d
+1wlgOm34jgDxxWIdfaa/l/hcz82F45HeA/jwvP7/EXTni3hkDT92vTMHJQPKguhL
+V+be+XNnGihNT3k6fXpHAr6Y+HXN+4nqd/ndKRkfzVeZkNMzjFgeWy/LQ1bruMSP
+Cz/RdpatxH/fRvazCXe160YIB25cwFMUvt4saiN3SvHETxC02SsA6hY1TZB2UOmO
+/PjyXiXB6nyHchwEbTkzwnHKJSDX5FlAvweOkJ9PhKZIgfXRG/5orqXWqczUV+Vk
+FyC4338kCtY8sGYlbBvusNqugkbOEMaKUtJd4R2vvXUUbcybrAmjHg10To1uHAxw
+2xE/gewcvrPTdo4upV4JzyGszJte3MWspv/tyXY/s8F1/ENwatPOZWqMDAa3WSaz
+dzi8cfQFVo2Pq2b2TtrBE0KPKt1Zw7zIHYcyWnGJaLTzXhFdaw+8jY1+tudnBtzE
+l84fqwBX/9sAjOdCz1TkIskdpDhWQm33MvTbWluj1FvEQMYgLpLpLIOs1kw8DMNE
+TH6rrVnMDpdr9bGOPwmxBa/SC6n0EHGczSJ0IyGt5GrjOLGhPgYvETUDCH00GUY7
+cH+v6S4Lh4Z19aBcDEcW+drU/I+HfoC1qhnqksvNJFeYbEDqTcXD3De2zd6MzMiL
+qoxaNWshoAYqMbNdZNeCjlJTFq4mU2v+CxLKxUmnoLzkPsrfdniEfTwCg+LoERCk
+t588o6N8g3JfPDjpTWiH17KEuiKvDYPfheKr3Zu2Zzgd3Rm63l80vINtYffTfKB+
+U/nuGRzX0bRqWLZlEEnUJxnSYurG7DH7uozCgozbkVqYRE75/wxBDNSeOWSy5HDq
+0UeRafBOJmGU/7jhNLnKP8YZ5o+XBI3oQMfLb2q3uNbLTc73vqWoFCC7hCUJnKq9
+z8yD7mETNYTyS1g7uGt2yWmuYinyn+VQkg/f2ExQ36HCjzkoaJyobpNgdzoTF0+q
+dhzCAfb3C04p/iUIXFQCD1YdZVgwXCmAgxRKbfJaW6B1FFHe3PYzac5RQtvLJQ0q
+u8sUFlkhr/ax5wUXhILXnvH0S7QtEcGTRJawna7TBZWk4kvTlU0N0DcLU+LKUmws
+3seuvYROHZ6VSrGikL5IMVZl+h47Ub4HMTvdWAiaSMchl3fxVFW5kGJcAMvoI9ZO
+ENIWeZVgXrz7FPfnfYnLLNXeHC1LM0hYHztkaXuBC4ujupPmy4/oHNmQXx/yufDK
+wmQEWsFPf/JrwraW6PAX+/FvZ2G97LIDoxB4TjaIdBXKr17YRAOD9PCcqWBtFrHu
+4HXwSF4tALbDlMryhjMNOOs0jWjl+jx1LtZ+I+USOjX+3G1ZBWgl5Ps29YMJYF5e
+NRqyXPpLaco=
 -----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/standalone_2/io/certificates/client2.pem b/tests/standalone_2/io/certificates/client2.pem
index f34bde4..3999216 100644
--- a/tests/standalone_2/io/certificates/client2.pem
+++ b/tests/standalone_2/io/certificates/client2.pem
@@ -1,19 +1,19 @@
 -----BEGIN CERTIFICATE-----
-MIIDBzCCAe+gAwIBAgIBAzANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9jbGll
-bnRhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1WjAQMQ4w
-DAYDVQQDDAV1c2VyMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMay
-a0BYpNJHlwcNz6TyX+D6dKnqxUfdHQDgW9/5Hl4RiHDKAH+2iVYEsedksOmxNDlV
-HqZg4fBsyPVRzeGqia7nCsN3KlMbaqZgNI3ynvvMFIJkb3e/ZJtodg+cYzqnOu2F
-G3LijzRJG363aavTnjLdFumLnsOtSDdYnjRM43eeE3X2ajAiKkE9r6b6/wt8Ki5T
-GVIm9kG674iCloawK6dgCBA1dDPsKmzhcFoAl5UMpQSvd1OuW034qryE+RzQ0RCe
-G5u2leVgiuoq2rpmPL6fA0BHsyJ3wP1Gs74i+NhZdhiBhv+E89sfKaJOPpmDBW7b
-3jCpEmgRSm5h5SDm8KsCAwEAAaNiMGAwCQYDVR0TBAIwADAdBgNVHQ4EFgQUj0t8
-BdHrTqd7aKIV4+OLWvT6WX4wHwYDVR0jBBgwFoAUtyLBueMoMi7TborRvM7CnwOi
-SQ4wEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABQ4PKRG
-VJYhWtktqpilP+C8CXsMArsqkEdMwHgQi8Xv3WVvXZpiLZHvO0To9J3+dgD2sOys
-MphZBXMJuOfX/+3IGerxsBxVj7Pnx37nn83g6PfCvGgVQQw7cGUjn5/Dw6apH2HH
-eO3yG+fgYeMNXyKt1KVWYeIToZfXUFvm+oMbWxxdpcctsKLRgCRvf1+r5EK9xE8+
-jYYk3S3pXvsk3qwWJz3pjg6zR3IbakkEuhE1Gl0Wrf4zZ9DOB8rd00/xirAuuYwm
-aIZ3KcFCTgVdGtB41q03D31xWNZPODCxAEADiICNE+3cuUMCi3wwBeCrybXSLhj/
-6St8K4NBvg+xL/w=
+MIIDBzCCAe+gAwIBAgIBAzANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9jbGll
+bnRhdXRob3JpdHkwHhcNMTgwNDIzMjAxNjM0WhcNMjgwNDIwMjAxNjM0WjAQMQ4w
+DAYDVQQDDAV1c2VyMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMBX
+SxFoCWZxTjBXABqf9ygEicJDLcBEnStDbo+XE7CGDNkf6AmYy9cFpNK3brxfmU3x
+ZKizie8fLeTMpaEAAR73epPn9Ui3JzP4e12HacLXVIZkDdoOjCcksf1n6CTXSTeC
+K2h8aO5oqC7ouwUcWbCbdLu+OxohAMg/vmDXvRhJC9uoJyW8hYJwpAuErh/W/DuX
+LUgAAGNnztth5UWmrD4b9vdhU6yR2t5Gj2DP44Ow5rlurqC0vY87pe+rMal26mF0
+GLYCzrJOdEwy4WGCuTxXtbqvud9NIV++61cPtOu+GQKwI6/KJ5TEKsLGEbqQViM4
+rUguOwndm/7HK00nbPECAwEAAaNiMGAwCQYDVR0TBAIwADAdBgNVHQ4EFgQUKpNM
+YZQHavaPs/m1k7d3a9QbbTQwHwYDVR0jBBgwFoAU+TlPoMTEPn2GHUDuD49Nm+iq
+vwwwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAJSyKalJ
+wh1wQvmZ6sa7imzsWwQ70Kr8NgDZFm8Ds1dkfzxsP6lBey8HVY6nDQD2LzJth9ny
+2AXcHvT9DKRto1cJI5z8/H+E7oKzPAlJjnmhL2dIk6als2KYfBHu5eLyaoWOCvNx
+wd4wk+JrMIQuVeIQwrG2PPDSUffScb5y5OeW1PvmnAJNTI9bHSIA4/GN45/l3FEW
+IZuOBfv5DjubYoWT+OJMfSXoqIU/wciyx+SsSPHQ8F8Q6eLgxhF74eqIrIWstZIf
+bwo83QHOpqXxEkzny4Pbdcis6rGWagH6JXHoiIHcHlsRveMEUGLUJaV0nxN2DgUa
+Umod67RaTcbdses=
 -----END CERTIFICATE-----
diff --git a/tests/standalone_2/io/certificates/client2_key.pem b/tests/standalone_2/io/certificates/client2_key.pem
index b4074f9..8bb2fd8 100644
--- a/tests/standalone_2/io/certificates/client2_key.pem
+++ b/tests/standalone_2/io/certificates/client2_key.pem
@@ -1,29 +1,29 @@
 -----BEGIN ENCRYPTED PRIVATE KEY-----
-MIIE5DAcBgoqhkiG9w0BDAEBMA4ECC/vc3ONj4KfAgIIAASCBMI1liT+B00kYYj+
-VRcEHQVrWsvD648OCd6BNQ9gKTYL5767lHUN0iG2JAdTHTKJy7XeEVVdPweU58jb
-HnS1yWbs0IuUFkCGy9wH3Lb6SkZtEScoAmzsNRdSY3WwmNhUG/yHrLITKM1SGkg3
-nf3ywIJYwO3YH22InVK0puVT/y943F1GXZSvklG/TGawR0uIyNuZOl0rg+5bsCaf
-1VSCWvt/Czgqm9Pc+Iz2PAKwyyjmvqRMBCtKvJTGNEPB63eDyHWQTtvQe0un06AF
-lvB7JYWaTXiwccSww2BuqTdJdBYKWxzPbdBfcqUT5Q9/LE0JhwvfZY/oDeJFP0HC
-HVBajuESZPJgb06xcsiX1qmk/iqAjZVZQ/CQ9K08qXem7YRFxJCy90wjLu3abjzQ
-Nvq0VsI8a8vlODQlr/Z5iXSYEKMYvUwh5Y9e8fc0BOOc1QzOYV2vxy28OVHmigOn
-tVHdj/FXK6N97QgtFzVUTjisO3YFygI2wybrz1BEys/vwqfCBiT+/hu+ur/lCrkn
-E2S6I967TyTvaxn+WCo9EW2Rb66XdI7tL09AkV2VZqJN4PTyis9YYgkr2uKjj4qX
-ySAQp/XHGEF1mmvjeptKTb2CMut0vcP+nl1bsUUXpSiKYGQ2BBcqgTcEFUEd75ms
-kcPMOuHdioaYh72nCRVzsRoDTDGF08NMTndW5PC8RpFsNS0vx8dq/A3VHAvJa2Rc
-9lP939FAU/Ck9b3NxH6hUgfDEFHQ61oW2Inpu4s3eRoClkgyf+aQEZZI7GTiNICm
-xqHosZ+hLe2mYoGk6xl1AruMk7kGeebRaPxzvS0UKfftOQDahFcDp8iEtLAcM1nx
-8Pdu4csyWFk+eBsTT6sPur2ZkD2LO0gLjR+N2nZNTqEJYy7n1jyV7M/JZBfh0fGi
-VX+sb+urTBAlDszX6b1LV7M78MDs6QwziDsrytjuClOWN47wzYbYYnSZZnDtTR+B
-CDHyK5wa8gNs4A+643HvD6sJz6zALOu2UI/9SrvuyYPltCwCUmWJ3A2XxoBmdJ/e
-yHEj/VdsNi6TtQ5qpBWqm43LpF0WAKNgksGnbFjOc/0QsUVk0txB9D6/oC9HyCd8
-u9nR8vLUC7l1dtYL0CwpocqU67qzVoRxrkkyCE4iblusKjr1ZlfstHDS0tPELodo
-8RroSs4vKXV9dzhzLQyqp6PzzdB7y/5Bpn0grxXrwln6/shoSR462h2CB4z9chGA
-Vdsp+KE8LDogIwZDT6iVVrpaBQDLoSxmX+E2IKRCUcj/l+gepEPyHbhOAn8/NxGX
-h16v89aDMtnyWqUcc/Gm2/Qep3o7goRfodyoyWvwy8nq9Lgf/wJIfEGn0lEeR0I/
-/Om/UAiId1o47C3LsGMm+qO+FcWesLA67eMQnp1WYoWpnanb3q4t8PWATzAlW05n
-cA59dYjutUmKJEjrh595AptMLXn6RM1GzA7x53+uAKvXaI+aR8wrtujiJLg9DwY2
-+f4ehwfwNptBxzZX97a7/3lGZ5U7BgDeJhNo9T02VQTvXxB29H6J/v6XYyPCKpuM
-upPhiHzrs9UyMvINfDnd/fJ58qr6TvEuBi0QxMMmOCfccYlj6Q5Bfqp+iuST0igg
-SLmBml+LkIM=
+MIIE5DAcBgoqhkiG9w0BDAEBMA4ECOesX1fugaR0AgIIAASCBMIl6TrcBn0oHRHl
+X3MSXdAyEMLYBaSVgyRUt1gu0WhyT9uu1xlB1VGu14QHY3uqvTMZpJabSYsafV+P
+3dbFmk9YHg3Ss0GPaRcx4Q74NR/3BzMIB3q429JSK+GYKHNkRtdMNiQ9OcFVavhD
+BDApEkavka/A9U5YOB4+/20BPYpfSZT9Z+hLffH6vl6PSsuRzYHdqbbTi44Rff+R
+m62xzgSxG2+n9J68XPaVxVOLAoNQAlPVfq+lxYF04PdZGz8euJMw2C281Ddpo+sU
+Jtvbp0JuAa24GNLM5DnmHvRbfQVxlm6dKJi40Gi0g4ellSs0roqUY+RXUC6VqL/R
+qPWiJhtnvue8zOA6F0C2nFF+Qdtm0UiwEp4TR5jhC5y1+uWzy190mM2fuo0m/7/0
+6FRv2Oc3tnYXTYg0m8h8QjPGCp3A1TwDlTOoeG81GD4sYvu/kPQH0cKmytwAqMJw
+LP6OCgOjEFwWxKkYaBVSnr7aP7f/26F8Rf8eGJO0VH2P67F8usweof30bP9eQ9MR
+rrA9uA0+odpufNMaVbA9Vnj4ipCWR0xqU0Uq+UODVwvI3Vnf1c8gWm9rFCi3hZb5
+kuxtDpXWlR7SgiRejt1cZmWTWijToF81HkFZf9XoS8jdN26XLlhqy45h9G2N3mVQ
+jS0uSAjZVk4A1k/HbicOcj92eL1nXK0QFY7OPL9XBSms+KlwAVN15M2tnfQ5mlxC
+mVAFqho5KQmYipViO/VI5aS/CxVnABSqLxhhj/ge9SQFONjsNDKkaIz7tYtz5KJ+
+dvJAg2IMcOtV4jZIBrNdfslw0TP17GZwrCUibLzEdPQ02awpemyi1sHquR/B9uoi
+3CDsPoDABzVp79wsiYz2sEwY23AaKZtMuQRSbR8BtvmMIArgJ273/vfx92skMdjn
+dpJbxTlNZ/xPo3NSXVTQYxlfeNrGelXvJYT0LxZ4uapMa91gRXRvJsjC3JGu4o+T
+CeMtclG9uYrSOlbyg4WzVKpwIHTjSCp/CkWCBJIkdxKkScwhDoG3mAcglwMikUEt
+Eg60+jPBHH3dTOvuaRXvYDVdPG8SPa3txrR1tetKGB6g7eMjYgbmYDOxQESS0j1H
+cUCIfK+NwKMBRJFy1wjWqZLKhCWrtevAMhpPFa3HWv2fLY0Vf2s6n9W9mr/hA3Tt
+tPo+c5r7M/I2jzxiHSo1bJD/0yeZDegWrB+8+8PzHoFY05458ei1rc9iNTziogl1
+DYOOcBlROOitO3VZYjbab0iwX0zqEuSYQy41zVJHbMQFp+rbIpuPWQpNAC3FxZuW
+iTVchbpHiCHZ+I1Lud3aqN2z3CBC6GLONUoyCvLfmCKoLIbjusZ/xFH9Q7INPOkH
+g2Sr/bw+8oC+FCujORB2iUmFo5fcgrF1FLxFEbYaB629ed8vE+2aII2OA4amsiD5
+1RkylPMD4Tv6FOvp4G37ph98vfdQvZeX9OdkqS3rGdbwSCf6+AngomJEJ7uVA/c7
+Won/1j0eF6JtcRPBo+jFKfdzr6ynu2AoAyKg0Rn/S7HC0YLEB1iPDWpOC39yQp+A
+x4NNJm1NJjR3oby6LdVp2J8GlKuhztxqkJ6aV9BZDM0rEpP4EdA0QClhXnIJ9H6e
+7bQ8uhT8sW8=
 -----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/standalone_2/io/certificates/client_authority.p12 b/tests/standalone_2/io/certificates/client_authority.p12
index 545282e..76b0575 100644
--- a/tests/standalone_2/io/certificates/client_authority.p12
+++ b/tests/standalone_2/io/certificates/client_authority.p12
Binary files differ
diff --git a/tests/standalone_2/io/certificates/client_authority.pem b/tests/standalone_2/io/certificates/client_authority.pem
index ae9ae5b..142756f 100644
--- a/tests/standalone_2/io/certificates/client_authority.pem
+++ b/tests/standalone_2/io/certificates/client_authority.pem
@@ -1,19 +1,19 @@
 -----BEGIN CERTIFICATE-----
-MIIDKjCCAhKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9jbGll
-bnRhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1WjAaMRgw
-FgYDVQQDEw9jbGllbnRhdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQCi6wJAs6nppNmTZ3e/wE9l0pAmkMtDONwB9o115XXTG3rmSKfZOxa8
-TFjSn818Pr1OYb9fPdI1Y6x4WY9PELUtQyEBlNcKjwg96vhrP4p2DhqbWsI5nASH
-DSjJsM75bQ7D7qHYzriuAl0Fk1C4LcodRj+5wmErMtvGJG0x06qFbxCCMAJ2kC+h
-SneTN955/YHSXADgxjFlt3s1T0QPnqrr+G7Ro6PrVKLPBulglq7wAeTwrGkPRUt0
-3lDGOSi6i97NbpiXwrGp5XiLUtVCiID6Ro0xKWH4sjJ4JnVjIUG8CQWERc6sFDJM
-4adgFQJagkTUoxWtDGL58+WcbcJa73XJAgMBAAGjezB5MBIGA1UdEwEB/wQIMAYB
-Af8CAQAwHQYDVR0OBBYEFLciwbnjKDIu026K0bzOwp8DokkOMB8GA1UdIwQYMBaA
-FLciwbnjKDIu026K0bzOwp8DokkOMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAK
-BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAh8rryWFoGjFdm0i4FLRktF8B
-aUqVCCpFVHIYlFcsQstznIb01X2Zq5nfSfrFxbr5STVGzGJ0HGDuFpicT8+qMnJX
-dou5AuaqubIDWeKL+oAgvI71Nt1gsesixqzFQAoCTRgUjrSGpY2fL7rElV0Ndy9b
-YepVouktP1/GULc8XbIG9ZLx70Id7YTyrITDgbH3hSnbjmmZSr9RKyKas4MXN0s8
-oKGHEgAx7KyNQRppjydz3bDeH/jVbM4W98vwL6rjKUJlOlo0Ru+3+oioFHqLMSvN
-w4f5rQEiuF260h7y8KKxRxQ8rw188gsBapZr4Rcp+y8gdQvlzJONtv3d1dap5A==
+MIIDKjCCAhKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9jbGll
+bnRhdXRob3JpdHkwHhcNMTgwNDIzMjAxNjM0WhcNMjgwNDIwMjAxNjM0WjAaMRgw
+FgYDVQQDDA9jbGllbnRhdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDckwmIcOYIRbH1jcuBCC/y1a4aiqXhvUCty59Cdqzlx0gbrhkVGmf0
+B0Tmo/PW4p9rcl0hwwxGvGoCvsxVpodHQmIxYwwn1sRl2C7Yo2ZHPMYbv9uq+D0d
+kS8SxHb5l4HvpcT7WoqUq8ZWEm0Losbp8cOcrvLiBQgo8xIOKQzKbwrXydnviQKL
+E5iBmUswzHwb7ZK84u6dS3iHbl9iPy+QTfiboT6BNMsO/dm6Nqmdj35fOPQgFUN/
+QR3NsPWL9GtzB9iZc3D7c30FqqqQO/THjaLJIyzdFdF3Fsp+omSuZw/q1d4/R8M3
+FRCcqzbWLA9Dy12kK/9asmlpf/fdHByVAgMBAAGjezB5MBIGA1UdEwEB/wQIMAYB
+Af8CAQAwHQYDVR0OBBYEFPk5T6DExD59hh1A7g+PTZvoqr8MMB8GA1UdIwQYMBaA
+FPk5T6DExD59hh1A7g+PTZvoqr8MMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAK
+BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAh4f1I0kXK88S3yC8k0zRAp4n
+RyyjnPW9Sr2nIuC27RgfH0lxWGOlAVVrFUlgifECD/RSoMuQk5yYgAJiALbnfdlP
+AutjtwClWZ6u1BXnwdUxS+ypWtq4Fb4+vz/VRSK24ZNcrI9NF3wkqKHxnjccxROA
+BratiMbHi5VxU63iec2XqAEhqi+ArWks8XJyTvv/tBYOqmmP4Fi0i/wbpzxmFJ61
+ZGUiHFifkYHKBI/HhjDazdeAhAwcFHSbVInea10+V0dkW7sOGnJFW5PyW1F/TBBe
+3dsp8Tz88+oHbSGwV7qF/Qf6U6kRxeVVctmSSCAohUbPH26xhPhk+t1TVdb3EA==
 -----END CERTIFICATE-----
diff --git a/tests/standalone_2/io/certificates/server_chain.p12 b/tests/standalone_2/io/certificates/server_chain.p12
index 79e412d..9ef96a7 100644
--- a/tests/standalone_2/io/certificates/server_chain.p12
+++ b/tests/standalone_2/io/certificates/server_chain.p12
Binary files differ
diff --git a/tests/standalone_2/io/certificates/server_chain.pem b/tests/standalone_2/io/certificates/server_chain.pem
index 341a86f..0d18b96 100644
--- a/tests/standalone_2/io/certificates/server_chain.pem
+++ b/tests/standalone_2/io/certificates/server_chain.pem
@@ -1,59 +1,60 @@
 -----BEGIN CERTIFICATE-----
 MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
-cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1
+cm1lZGlhdGVhdXRob3JpdHkwHhcNMTgwNDIzMjAxNjM0WhcNMjgwNDIwMjAxNjM0
 WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQCkg/Qr8RQeLTOSgCkyiEX2ztgkgscX8hKGHEHdvlkmVK3JVEIIwkvu
-/Y9LtHZUia3nPAgqEEbexzTENZjSCcC0V6I2XW/e5tIE3rO0KLZyhtZhN/2SfJ6p
-KbOh0HLr1VtkKJGp1tzUmHW/aZI32pK60ZJ/N917NLPCJpCaL8+wHo3+w3oNqln6
-oJsfgxy9SUM8Bsc9WMYKMUdqLO1QKs1A5YwqZuO7Mwj+4LY2QDixC7Ua7V9YAPo2
-1SBeLvMCHbYxSPCuxcZ/kDkgax/DF9u7aZnGhMImkwBka0OQFvpfjKtTIuoobTpe
-PAG7MQYXk4RjnjdyEX/9XAQzvNo1CDObAgMBAAGjgbQwgbEwPAYDVR0RBDUwM4IJ
+ggEKAoIBAQDZE0gF3bAFxBaxAZUFGkeFkF5B8nJD//+14rcz/Kr/Rau38g38jNyp
+K3bsyWIBq/4A/cPykwncG6Z04WD2FrLR1xDdAbO2zD3cQKbOoFOYXeYMmP4FZcbq
+nSngCzfUfJkwXXHfCC6v3XZkmR0ojWp9tGHJ6G4f9QI8wwT/Y9pvAVQVR9+S43C0
+ZAPkuNiMBN3lAH4QF2WTC5GTQo4hR+IAWN28lnqAbVoRMNvFoDenDZxURq2kT/6j
+ot6UB9f6AOugCUlEpVovTX3evPKrIZz68BM4DttA/r2wo6dw3fouZk/REJ38fi7x
+lg5n5ccCmguE2fF5PoAMH7WCc7EupYKNAgMBAAGjgbQwgbEwPAYDVR0RBDUwM4IJ
 bG9jYWxob3N0ggkxMjcuMC4wLjGCAzo6MYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAA
-ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSvhJo6taTggJQBukEvMo/PDk8tKTAf
-BgNVHSMEGDAWgBS98L4T5RaIToE3DkBRsoeWPil0eDAOBgNVHQ8BAf8EBAMCA6gw
-EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAHLOt0mL2S4A
-B7vN7KsfQeGlVgZUVlEjem6kqBh4fIzl4CsQuOO8oJ0FlO1z5JAIo98hZinymJx1
-phBVpyGIKakT/etMH0op5evLe9dD36VA3IM/FEv5ibk35iGnPokiJXIAcdHd1zam
-YaTHRAnZET5S03+7BgRTKoRuszhbvuFz/vKXaIAnVNOF4Gf2NUJ/Ax7ssJtRkN+5
-UVxe8TZVxzgiRv1uF6NTr+J8PDepkHCbJ6zEQNudcFKAuC56DN1vUe06gRDrNbVq
-2JHEh4pRfMpdsPCrS5YHBjVq/XHtFHgwDR6g0WTwSUJvDeM4OPQY5f61FB0JbFza
-PkLkXmoIod8=
+ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSFtW0d7VGk7g7ywHgrf+bbg/BhQTAf
+BgNVHSMEGDAWgBQqU7R8m4wyfyc9ubiPQcYpHNZrmDAOBgNVHQ8BAf8EBAMCA6gw
+EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAKL0FaPO+YM+
+JJgQryvkf2/WqdnnTGg/7A/HCOk1rkT9q0282Bj1OT4GiyOIOTyHkxrF72dSiN4Q
+0hg1YoUITR1uR5odQsnK3YKSfmGfn+IRNuHf/Oy1XfRrjuIgo3syeqquIJM4W1MO
+uZBkqwdXQIYqBGj4E+y32bxGVhI53rb9MyKfugajRxImTO7UnUydHsIgqNG6MfuH
+LXBNUAw6uPLyW6srfWiiDVlkUzSmXYFoScCXTj7u12Ar/hffGKrXqHojSE0XtcRz
+WuncYKJE/pflgClA5Qe64erD3q2w2SfOZDFwizP7aZU9uAMin8NbiE8Nd6h8hoRc
+ztJfeC+1gro=
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
 MIIDLjCCAhagAwIBAgIBAjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
-YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNVoXDTI1MTAyNDEwMjYzNVowIDEeMBwG
+YXV0aG9yaXR5MB4XDTE4MDQyMzIwMTYzM1oXDTI4MDQyMDIwMTYzM1owIDEeMBwG
 A1UEAwwVaW50ZXJtZWRpYXRlYXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEA6GndRFiXk+2q+Ig7ZOWKKGta+is8137qyXz+eVFs5sA0ajMN
-ZBAMWS0TIXw/Yks+y6fEcV/tfv91k1eUN4YXPcoxTdDF97d2hO9wxumeYOMnQeDy
-VZVDKQBZ+jFMeI+VkNpMEdmsLErpZDGob/1dC8tLEuR6RuRR8X6IDGMPOCMw1jLK
-V1bQjPtzqKadTscfjLuKxuLgspJdTrzsu6hdcl1mm8K6CjTY2HNXWxs1yYmwfuQ2
-Z4/8sOMNqFqLjN+ChD7pksTMq7IosqGiJzi2bpd5f44ek/k822Y0ATncJHk4h1Z+
-kZBnW6kgcLna1gDri9heRwSZ+M8T8nlHgIMZIQIDAQABo3sweTASBgNVHRMBAf8E
-CDAGAQH/AgEAMB0GA1UdDgQWBBS98L4T5RaIToE3DkBRsoeWPil0eDAfBgNVHSME
-GDAWgBRxD5DQHTmtpDFKDOiMf5FAi6vfbzAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
-BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAD+4KpUeV5mUPw5IG/7w
-eOXnUpeS96XFGuS1JuFo/TbgntPWSPyo+rD4GrPIkUXyoHaMCDd2UBEjyGbBIKlB
-NZA3RJOAEp7DTkLNK4RFn/OEcLwG0J5brL7kaLRO4vwvItVIdZ2XIqzypRQTc0MG
-MmF08zycnSlaN01ryM67AsMhwdHqVa+uXQPo8R8sdFGnZ33yywTYD73FeImXilQ2
-rDnFUVqmrW1fjl0Fi4rV5XI0EQiPrzKvRtmF8ZqjGATPOsRd64cwQX6V+P5hNeIR
-9pba6td7AbNGausHfacRYMyoGJWWWkFPd+7jWOCPqW7Fk1tmBgdB8GzXa3inWIRM
-RUE=
+AQ8AMIIBCgKCAQEAsSFr3/sYhGFF7gEZSn7Am8ATtPhTo5ypQqSAv/4Uy+k4zvT3
+b3OZyYpzr5Wsa6NXcEKwNipyR1GBpYwaYI/W4DSi+COdH4DQSZDQFr+hvmXRazzj
+VSsOxF6veGLcza53meLPRb4o4yVoZARd6xR5i3OUD4kezvOjpmlFT3OKNU0Di+Vq
+qeS14/at6Vt6G0rS8CluafD7Z0/5zp6vrImKwC6OWzlmmcAqBGsE/BTzrAxLdt4K
+uw3Xs3uvS3YZIAC536C1Mop1n4FBUGxeUMWH+I/llzK9ol1pmQHJrxfOD5WdFuuE
+iFfpiOmBdUfDBbEPllmIvzUBFOo5VhxVmq8EHQIDAQABo3sweTASBgNVHRMBAf8E
+CDAGAQH/AgEAMB0GA1UdDgQWBBQqU7R8m4wyfyc9ubiPQcYpHNZrmDAfBgNVHSME
+GDAWgBT0rD9lRUhqJvAg7hfBEz/ZqHCzHjAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
+BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAGjRSFvVeIrRF3iuA5vr
+SgufTCNzAyEz7+pDKflzHSQXF1fdItiOdPGv1i57gIr7HaYuxvBiEklhmnWreYye
+Tn6ghfhEHhdZHBpihDXuIvLizhtR/lg9CDZrHjuY6nukyx4JnWwUBR3TulPK5gJu
+jB9YISY8tjXrvVNqdi0a+G0T4HHnVs3v6Nd/Qdsxfp4maAB1U3HFmR3DXKTxDtBK
+mNNMqf9PpX4lw4o6UieiEwOMd+4REhmwLNTwhWrhVg5q6GKQl873Ge/7J2nXvgkH
+nUbEsncLsArqqrz201f2m32A6pinwY/j85vEeRkHwlsU0jOvVnHzAlggP0u/kFAF
+EjE=
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
-MIIC+zCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
-YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNFoXDTI1MTAyNDEwMjYzNFowGDEWMBQG
+MIIC/jCCAeagAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE4MDQyMzIwMTYzM1oXDTI4MDQyMDIwMTYzM1owGDEWMBQG
 A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAMl+dcraUM/E7E6zl7+7hK9oUJYXJLnfiMtP/TRFVbH4+2aEN8vXzPbzKdR3
-FfaHczXQTwnTCaYA4u4uSDvSOsFFEfxEwYORsdKmQEM8nGpVX2NVvKsMcGIhh8kh
-ZwJfkMIOcAxmGIHGdMhF8VghonJ8uGiuqktxdfpARq0g3fqIjDHsF9/LpfshUfk9
-wsRyTF0yr90U/dsfnE+u8l7GvVl8j2Zegp0sagAGtLaNv7tP17AibqEGg2yDBrBN
-9r9ihe4CqMjx+Q2kQ2S9Gz2V2ReO/n6vm2VQxsPRB/lV/9jh7cUcS0/9mggLYrDy
-cq1v7rLLQrWuxMz1E3gOhyCYJ38CAwEAAaNQME4wHQYDVR0OBBYEFHEPkNAdOa2k
-MUoM6Ix/kUCLq99vMB8GA1UdIwQYMBaAFHEPkNAdOa2kMUoM6Ix/kUCLq99vMAwG
-A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBABrhjnWC6b+z9Kw73C/niOwo
-9sPdufjS6tb0sCwDjt3mjvE4NdNWt+/+ZOugW6dqtvqhtqZM1q0u9pJkNwIrqgFD
-ZHcfNaf31G6Z2YE+Io7woTVw6fFobg/EFo+a/qwbvWL26McmiRL5yiSBjVjpX4a5
-kdZ+aPQUCBaLrTWwlCDqzSVIULWUQvveRWbToMFKPNID58NtEpymAx3Pgir7YjV9
-UnlU2l5vZrh1PTCqZxvC/IdRESUfW80LdHaeyizRUP+6vKxGgSz2MRuYINjbd6GO
-hGiCpWlwziW2xLV1l2qSRLko2kIafLZP18N0ThM9zKbU5ps9NgFOf//wqSGtLaE=
+ggEBALkvRWdbx9GwxePkh0nnpht4MrPW5NkZBORqfhFi7PFbQ7Rwgl39hm9iAmci
+pOWZGSJi7AaqLuSID0UEeRdG/fNFawI5XIoxP+TmdKdrk/SaTJQKKJiZ9B8+EG0z
+hV8/v6jrlwj0gq9eBBAmOInnmQiEYE4gKFNvh9xdP//gi+otBf30gmtJ4AxXOTu/
+M+XEigXelmIvy57b+B+qnonTFcGkXhSr+JfCA1l6ta7OtknQtItpV0FDr/d8hA+6
+Bn25ZSisd00GC3CUMX1tM5V8cQE6GO/W2mnpUFVvWycYx9wDyU7rlyNUf8nWeoIW
+3d3s/6KAppa07KrkLiTantIrqMUCAwEAAaNTMFEwHQYDVR0OBBYEFPSsP2VFSGom
+8CDuF8ETP9mocLMeMB8GA1UdIwQYMBaAFPSsP2VFSGom8CDuF8ETP9mocLMeMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ1VynTevPnNtwevQpUa
+zlur64N+Dx/yF4gvd4byjO+JouMJLaJqV2dwnqgAahg6YKasVtv4xX9MVJR2IjIb
+Tfa0nYQxM5clwk3J78nh82Ncb2RNeYJyNmSdocnOkmTSoOGUFOxtRz1vmKUcrfwl
+yENO/qGe/sYmOv0IWJjeGQ2OZPblRumV4dJy3qTHFmOLpYwA0BGiIV5uj5Ou7QU1
+R5PY2pnJg4RXeaq95Pr50lkO9vpRyFUJHjR+P+J05M9FbjLPOQIFkpMYx/GyBg5n
+P+omyagOGW8bXfBTtUYu+rP/k+BC5AxI3Kdv/AD5vyHKi/JXhP3ycb8AYx5ENHoK
+qjA=
 -----END CERTIFICATE-----
diff --git a/tests/standalone_2/io/certificates/server_key.p12 b/tests/standalone_2/io/certificates/server_key.p12
index 204d42d..c95c46b 100644
--- a/tests/standalone_2/io/certificates/server_key.p12
+++ b/tests/standalone_2/io/certificates/server_key.p12
Binary files differ
diff --git a/tests/standalone_2/io/certificates/server_key.pem b/tests/standalone_2/io/certificates/server_key.pem
index 895b7d2..7598e59 100644
--- a/tests/standalone_2/io/certificates/server_key.pem
+++ b/tests/standalone_2/io/certificates/server_key.pem
@@ -1,29 +1,29 @@
 -----BEGIN ENCRYPTED PRIVATE KEY-----
-MIIE4zAcBgoqhkiG9w0BDAEBMA4ECBMCjlg8JYZ4AgIIAASCBMFd9cBoZ5xcTock
-AVQcg/HzYJtMceKn1gtMDdC7mmXuyN0shoxhG4BpQInHkFARL+nenesXFxEm4X5e
-L603Pcgw72/ratxVpTW7hPMjiLTEBqza0GjQm7Sarbdy+Vzdp/6XFrAcPfFl1juY
-oyYzbozPsvFHz3Re44y1KmI4HAzU/qkjJUbNTTiPPVI2cDP6iYN2XXxBb1wwp8jR
-iqdZqFG7lU/wvPEbD7BVPpmJBHWNG681zb4ea5Zn4hW8UaxpiIBiaH0/IWc2SVZd
-RliAFo3NEsGxCcsnBo/n00oudGbOJxdOp7FbH5hJpeqX2WhCyJRxIeHOWmeuMAet
-03HFriiEmJ99m2nEJN1x0A3QUUM7ji6vZAb4qb1dyq7LlX4M2aaqixRnaTcQkapf
-DOxX35DEBXSKrDpyWp6Rx4wNpUyi1TKyhaVnYgD3Gn0VfC/2w86gSFlrf9PMYGM0
-PvFxTDzTyjOuPBRa728gZOGXgDOL7qvdInU/opVew7kFeRQHXxHzFCLK5dD+Vrig
-5fS3m0++f55ODkxqHXB8gbXbd3GMmsW6MrGpU7VsCNtbVPdSMW0FalovEB0M+2lj
-1VfuvL+0F5huTe+BgZAt6xgET/CIcZXdNMRPVhraqUjqWtI9Rdk4STPCpU1rDkjG
-YDl/fo4W2T6qQWFUpiC9IvVVGkVxaqfZZ4Qu+V5xPUi6vk95QiTNkN1t+m+sCCgS
-Llkea8Um0aHMy33Lj3NsfL0LMrnpniqcAks8BvcgIZwk1VRqcj7BQVCygJSYrmAR
-DBhMpjWlXuSggnyVPuduZDtnTN+8lCHLOKL3a3bDb6ySaKX49Km6GutDLfpDtEA0
-3mQvmEG4XVm7zy+AlN72qFbtSLDRi/D/uQh2q/ZrFQLOBQBQB56TvEbKouLimUDM
-ascQA3aUyhOE7e+d02NOFIFTozwc/C//CIFeA+ZEwxyfha/3Bor6Jez7PC/eHNxZ
-w7YMXzPW9NhcCcerhYGebuCJxLwzqJ+IGdukjKsGV2ytWDoB2xZiJNu096j4RKcq
-YSJoen0R7IH8N4eDujXR8m9kAl724Uqs1OoAs4VNICvzTutbsgVZ6Z+NMOcfnPw9
-jZkFhot16w8znD+OmhBR7/bzOLpaeUhk7EhNq5M6U0NNWx3WwkDlvU/jx+6/EQe3
-iLEHptH2HYBF1xscaKGbtKNtuQsfdzgWpOX0qK2YbK3yCKvL/xIm1DQmDZDKkWdW
-VNh8oGV1H96CivWlvxhAgXKz9F/83CjMw8YXRk7RJvWR4vtNvXFAvGkFIYCN9Jv9
-p+1ukaYoxSLGBik907I6gWSHqumJiCprUyAX/bVfZfNiYh4hzeA3lhwxZSax3JG4
-7QFPvyepOmF/3AAzS/Pusx6jOZnuCMCkfQi6Wpem1o3s4x+fP7kz00Xuj01ErucM
-S10ixfIh84kXBN3dTRDtDdeCyoMsBKO0W5jDBBlWL02YfdF6Opo1Q4cPh2DYgXMh
-XEszNZSK5LB0y+f3A6Kdx/hkZzHVvMONA70OyrkoZzGyWENhcB0c7ntTJyPPD2qM
-s0HRA2VwF/0ypU3OKERM1Ua5NSkTgvnnVTlV9GO90Tkn5v4fxdl8NzIuJLyGguTP
-Xc0tRM34Lg==
+MIIE4zAcBgoqhkiG9w0BDAEBMA4ECDmmTgwIo/3yAgIIAASCBMHPUDfzHGi72H4W
+nKLepeD31Upra9tvQx6UrRQaBmf0frh5Coo4Yw3Z+IOZQ4ZwxoIv0/kty7FvXVDU
+BMdFqFeVvKKlsMm7Ub0hC5ks7A0mTVqcc9nW/aBL87W4nZsJ3LSLiPYXptBWOGRh
+kVghEsySowsK8OmYDwauLi5ZoZC/3cwy2YIaOC9/J8sbnzAq3EVEpJwI0GIQgYET
+aGGELjpariWrcPUa16dRU5vrBlFL2Sn3BVJU24DFq/8RJwsL2rpWXxg9x5QxoraW
+WPvxIGvanBphthRABjZ4A8mtQwvkKfdqMuJ7bWAA2YqcZnk7N5zh4XmARKvjlM5K
+ujpjRFu4+NjyQ65vqTfAwQptxj9l/nzaSZqV5K8ROlpa+UODNzLsL/gf4l/22zZ+
+/rnyko97NQ0Jhy/m0xPhXd620IWjmsjNZk+txYWx4K0srBTptRTqKWkQuY7DV/N0
+4xEA0y3T1kLXZmGmvoidB8VwWD7ZC4/fhuFKAKQmEccMsR9AUsI0h4bAjJ419AK2
+G1jsirQS5P1vBweddwbzCtztUNuCCFy9LHmJCLE/yJ2JMmnePi7eOiyvsjU4es6b
+yj9/ekbWQwZO5L15UkY9T/pP8kSR+gAvn/92DB+e2U4R+ZK886unDyLCCp0rGsPK
+ijdcwMkAJampirw3iO5FkXbGO4GoVggNUxTTCDnYenY8jcKePlP0YM7A9XZ+kmmS
+1gcNuNikKmfzusvUuvOX4Dt24gCOGa5dDEOeYHsC7SZT40IFogshZyVdKNzlyIxj
+yqIlr9LOGo7vL84aUYUUF2mRJ9n2+ivqRadQ9s59iH96uYjvZ12KztCjHEPVSVHk
++rwd4WJ5ByBV7MeB8370JtwN/ZfzAIB7ONfXP9rrfcP19VC+MpsIuOCYPJERlhBT
+9w/UuThPhM/cXp9YiDJepa0T2vmCRKHSz932WKGe3dZn+0saKa5ShdMSepp9CroE
+ot2aF+uU9rMh+DIeNVLmHFwa5+3UC18G6rIB9wpZCHmg6LyMDf/OwW2/yao/GKXN
+WayHbex+Z4yXrVUo+5m9rFwFgo2Hl8fVdSJhKmvp9HQKQjEgxUhUC9B46ErS5efM
+SPlMOYfWST5eOG55vr04dWI5t2AXAKWAxxowO1OBhj3J0FjCS/vtUkUiFohc91oV
+b11afVtizPQJOJ9D1xNEADemnJq6KNT1pRaeKOA94JKODwBMi4K3KmEN51l1uJZ8
+U5h1CjweXZjmq81Da2LMLtGgJuTUuAT6LWIXLSck7EX35D1mY4lGHcuMqVCQ1St1
+UvRjRFx3rd6aBEgj7M/FNsUAIlq4X6+58wdh3mx31608CYGyQ8p5kPhj26ZxziJj
+WSFW+YiVrLPBXhIn6Q9DIqvMPdTbLM/fDy9G0ZinhHZH+a41t7v+UZh2FtiT+p52
+n+hiHTbkGQgQ8SYZT0WAjiaS+1pVVvv+MRqpsYpnNPYxI5bp6orSFOudF3pdAbqQ
+f4WDOY0kGg2tPmaNpZSz+FPuuiWC7Y0J1+o3fMnrUMvY4XrUwkstFfROdnM0W9YG
+I1MsVM4NhcKPHcVxKWgsmL5yAVl92mz88rhgbsArhcpO5K4lxE1LB/giUZRdTkRP
+bKFBVqrcpg==
 -----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/standalone_2/io/certificates/server_trusted.pem b/tests/standalone_2/io/certificates/server_trusted.pem
index b943cf9..c6c2cc3 100644
--- a/tests/standalone_2/io/certificates/server_trusted.pem
+++ b/tests/standalone_2/io/certificates/server_trusted.pem
@@ -1,57 +1,58 @@
 -----BEGIN CERTIFICATE-----
 MIIDLjCCAhagAwIBAgIBAjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
-YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNVoXDTI1MTAyNDEwMjYzNVowIDEeMBwG
+YXV0aG9yaXR5MB4XDTE4MDQyMzIwMTYzM1oXDTI4MDQyMDIwMTYzM1owIDEeMBwG
 A1UEAwwVaW50ZXJtZWRpYXRlYXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEA6GndRFiXk+2q+Ig7ZOWKKGta+is8137qyXz+eVFs5sA0ajMN
-ZBAMWS0TIXw/Yks+y6fEcV/tfv91k1eUN4YXPcoxTdDF97d2hO9wxumeYOMnQeDy
-VZVDKQBZ+jFMeI+VkNpMEdmsLErpZDGob/1dC8tLEuR6RuRR8X6IDGMPOCMw1jLK
-V1bQjPtzqKadTscfjLuKxuLgspJdTrzsu6hdcl1mm8K6CjTY2HNXWxs1yYmwfuQ2
-Z4/8sOMNqFqLjN+ChD7pksTMq7IosqGiJzi2bpd5f44ek/k822Y0ATncJHk4h1Z+
-kZBnW6kgcLna1gDri9heRwSZ+M8T8nlHgIMZIQIDAQABo3sweTASBgNVHRMBAf8E
-CDAGAQH/AgEAMB0GA1UdDgQWBBS98L4T5RaIToE3DkBRsoeWPil0eDAfBgNVHSME
-GDAWgBRxD5DQHTmtpDFKDOiMf5FAi6vfbzAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
-BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAD+4KpUeV5mUPw5IG/7w
-eOXnUpeS96XFGuS1JuFo/TbgntPWSPyo+rD4GrPIkUXyoHaMCDd2UBEjyGbBIKlB
-NZA3RJOAEp7DTkLNK4RFn/OEcLwG0J5brL7kaLRO4vwvItVIdZ2XIqzypRQTc0MG
-MmF08zycnSlaN01ryM67AsMhwdHqVa+uXQPo8R8sdFGnZ33yywTYD73FeImXilQ2
-rDnFUVqmrW1fjl0Fi4rV5XI0EQiPrzKvRtmF8ZqjGATPOsRd64cwQX6V+P5hNeIR
-9pba6td7AbNGausHfacRYMyoGJWWWkFPd+7jWOCPqW7Fk1tmBgdB8GzXa3inWIRM
-RUE=
+AQ8AMIIBCgKCAQEAsSFr3/sYhGFF7gEZSn7Am8ATtPhTo5ypQqSAv/4Uy+k4zvT3
+b3OZyYpzr5Wsa6NXcEKwNipyR1GBpYwaYI/W4DSi+COdH4DQSZDQFr+hvmXRazzj
+VSsOxF6veGLcza53meLPRb4o4yVoZARd6xR5i3OUD4kezvOjpmlFT3OKNU0Di+Vq
+qeS14/at6Vt6G0rS8CluafD7Z0/5zp6vrImKwC6OWzlmmcAqBGsE/BTzrAxLdt4K
+uw3Xs3uvS3YZIAC536C1Mop1n4FBUGxeUMWH+I/llzK9ol1pmQHJrxfOD5WdFuuE
+iFfpiOmBdUfDBbEPllmIvzUBFOo5VhxVmq8EHQIDAQABo3sweTASBgNVHRMBAf8E
+CDAGAQH/AgEAMB0GA1UdDgQWBBQqU7R8m4wyfyc9ubiPQcYpHNZrmDAfBgNVHSME
+GDAWgBT0rD9lRUhqJvAg7hfBEz/ZqHCzHjAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
+BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAGjRSFvVeIrRF3iuA5vr
+SgufTCNzAyEz7+pDKflzHSQXF1fdItiOdPGv1i57gIr7HaYuxvBiEklhmnWreYye
+Tn6ghfhEHhdZHBpihDXuIvLizhtR/lg9CDZrHjuY6nukyx4JnWwUBR3TulPK5gJu
+jB9YISY8tjXrvVNqdi0a+G0T4HHnVs3v6Nd/Qdsxfp4maAB1U3HFmR3DXKTxDtBK
+mNNMqf9PpX4lw4o6UieiEwOMd+4REhmwLNTwhWrhVg5q6GKQl873Ge/7J2nXvgkH
+nUbEsncLsArqqrz201f2m32A6pinwY/j85vEeRkHwlsU0jOvVnHzAlggP0u/kFAF
+EjE=
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
-MIIC+zCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
-YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNFoXDTI1MTAyNDEwMjYzNFowGDEWMBQG
+MIIC/jCCAeagAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE4MDQyMzIwMTYzM1oXDTI4MDQyMDIwMTYzM1owGDEWMBQG
 A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAMl+dcraUM/E7E6zl7+7hK9oUJYXJLnfiMtP/TRFVbH4+2aEN8vXzPbzKdR3
-FfaHczXQTwnTCaYA4u4uSDvSOsFFEfxEwYORsdKmQEM8nGpVX2NVvKsMcGIhh8kh
-ZwJfkMIOcAxmGIHGdMhF8VghonJ8uGiuqktxdfpARq0g3fqIjDHsF9/LpfshUfk9
-wsRyTF0yr90U/dsfnE+u8l7GvVl8j2Zegp0sagAGtLaNv7tP17AibqEGg2yDBrBN
-9r9ihe4CqMjx+Q2kQ2S9Gz2V2ReO/n6vm2VQxsPRB/lV/9jh7cUcS0/9mggLYrDy
-cq1v7rLLQrWuxMz1E3gOhyCYJ38CAwEAAaNQME4wHQYDVR0OBBYEFHEPkNAdOa2k
-MUoM6Ix/kUCLq99vMB8GA1UdIwQYMBaAFHEPkNAdOa2kMUoM6Ix/kUCLq99vMAwG
-A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBABrhjnWC6b+z9Kw73C/niOwo
-9sPdufjS6tb0sCwDjt3mjvE4NdNWt+/+ZOugW6dqtvqhtqZM1q0u9pJkNwIrqgFD
-ZHcfNaf31G6Z2YE+Io7woTVw6fFobg/EFo+a/qwbvWL26McmiRL5yiSBjVjpX4a5
-kdZ+aPQUCBaLrTWwlCDqzSVIULWUQvveRWbToMFKPNID58NtEpymAx3Pgir7YjV9
-UnlU2l5vZrh1PTCqZxvC/IdRESUfW80LdHaeyizRUP+6vKxGgSz2MRuYINjbd6GO
-hGiCpWlwziW2xLV1l2qSRLko2kIafLZP18N0ThM9zKbU5ps9NgFOf//wqSGtLaE=
+ggEBALkvRWdbx9GwxePkh0nnpht4MrPW5NkZBORqfhFi7PFbQ7Rwgl39hm9iAmci
+pOWZGSJi7AaqLuSID0UEeRdG/fNFawI5XIoxP+TmdKdrk/SaTJQKKJiZ9B8+EG0z
+hV8/v6jrlwj0gq9eBBAmOInnmQiEYE4gKFNvh9xdP//gi+otBf30gmtJ4AxXOTu/
+M+XEigXelmIvy57b+B+qnonTFcGkXhSr+JfCA1l6ta7OtknQtItpV0FDr/d8hA+6
+Bn25ZSisd00GC3CUMX1tM5V8cQE6GO/W2mnpUFVvWycYx9wDyU7rlyNUf8nWeoIW
+3d3s/6KAppa07KrkLiTantIrqMUCAwEAAaNTMFEwHQYDVR0OBBYEFPSsP2VFSGom
+8CDuF8ETP9mocLMeMB8GA1UdIwQYMBaAFPSsP2VFSGom8CDuF8ETP9mocLMeMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ1VynTevPnNtwevQpUa
+zlur64N+Dx/yF4gvd4byjO+JouMJLaJqV2dwnqgAahg6YKasVtv4xX9MVJR2IjIb
+Tfa0nYQxM5clwk3J78nh82Ncb2RNeYJyNmSdocnOkmTSoOGUFOxtRz1vmKUcrfwl
+yENO/qGe/sYmOv0IWJjeGQ2OZPblRumV4dJy3qTHFmOLpYwA0BGiIV5uj5Ou7QU1
+R5PY2pnJg4RXeaq95Pr50lkO9vpRyFUJHjR+P+J05M9FbjLPOQIFkpMYx/GyBg5n
+P+omyagOGW8bXfBTtUYu+rP/k+BC5AxI3Kdv/AD5vyHKi/JXhP3ycb8AYx5ENHoK
+qjA=
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
-MIIDKjCCAhKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9jbGll
-bnRhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1WjAaMRgw
-FgYDVQQDEw9jbGllbnRhdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQCi6wJAs6nppNmTZ3e/wE9l0pAmkMtDONwB9o115XXTG3rmSKfZOxa8
-TFjSn818Pr1OYb9fPdI1Y6x4WY9PELUtQyEBlNcKjwg96vhrP4p2DhqbWsI5nASH
-DSjJsM75bQ7D7qHYzriuAl0Fk1C4LcodRj+5wmErMtvGJG0x06qFbxCCMAJ2kC+h
-SneTN955/YHSXADgxjFlt3s1T0QPnqrr+G7Ro6PrVKLPBulglq7wAeTwrGkPRUt0
-3lDGOSi6i97NbpiXwrGp5XiLUtVCiID6Ro0xKWH4sjJ4JnVjIUG8CQWERc6sFDJM
-4adgFQJagkTUoxWtDGL58+WcbcJa73XJAgMBAAGjezB5MBIGA1UdEwEB/wQIMAYB
-Af8CAQAwHQYDVR0OBBYEFLciwbnjKDIu026K0bzOwp8DokkOMB8GA1UdIwQYMBaA
-FLciwbnjKDIu026K0bzOwp8DokkOMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAK
-BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAh8rryWFoGjFdm0i4FLRktF8B
-aUqVCCpFVHIYlFcsQstznIb01X2Zq5nfSfrFxbr5STVGzGJ0HGDuFpicT8+qMnJX
-dou5AuaqubIDWeKL+oAgvI71Nt1gsesixqzFQAoCTRgUjrSGpY2fL7rElV0Ndy9b
-YepVouktP1/GULc8XbIG9ZLx70Id7YTyrITDgbH3hSnbjmmZSr9RKyKas4MXN0s8
-oKGHEgAx7KyNQRppjydz3bDeH/jVbM4W98vwL6rjKUJlOlo0Ru+3+oioFHqLMSvN
-w4f5rQEiuF260h7y8KKxRxQ8rw188gsBapZr4Rcp+y8gdQvlzJONtv3d1dap5A==
+MIIDKjCCAhKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9jbGll
+bnRhdXRob3JpdHkwHhcNMTgwNDIzMjAxNjM0WhcNMjgwNDIwMjAxNjM0WjAaMRgw
+FgYDVQQDDA9jbGllbnRhdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDckwmIcOYIRbH1jcuBCC/y1a4aiqXhvUCty59Cdqzlx0gbrhkVGmf0
+B0Tmo/PW4p9rcl0hwwxGvGoCvsxVpodHQmIxYwwn1sRl2C7Yo2ZHPMYbv9uq+D0d
+kS8SxHb5l4HvpcT7WoqUq8ZWEm0Losbp8cOcrvLiBQgo8xIOKQzKbwrXydnviQKL
+E5iBmUswzHwb7ZK84u6dS3iHbl9iPy+QTfiboT6BNMsO/dm6Nqmdj35fOPQgFUN/
+QR3NsPWL9GtzB9iZc3D7c30FqqqQO/THjaLJIyzdFdF3Fsp+omSuZw/q1d4/R8M3
+FRCcqzbWLA9Dy12kK/9asmlpf/fdHByVAgMBAAGjezB5MBIGA1UdEwEB/wQIMAYB
+Af8CAQAwHQYDVR0OBBYEFPk5T6DExD59hh1A7g+PTZvoqr8MMB8GA1UdIwQYMBaA
+FPk5T6DExD59hh1A7g+PTZvoqr8MMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAK
+BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAh4f1I0kXK88S3yC8k0zRAp4n
+RyyjnPW9Sr2nIuC27RgfH0lxWGOlAVVrFUlgifECD/RSoMuQk5yYgAJiALbnfdlP
+AutjtwClWZ6u1BXnwdUxS+ypWtq4Fb4+vz/VRSK24ZNcrI9NF3wkqKHxnjccxROA
+BratiMbHi5VxU63iec2XqAEhqi+ArWks8XJyTvv/tBYOqmmP4Fi0i/wbpzxmFJ61
+ZGUiHFifkYHKBI/HhjDazdeAhAwcFHSbVInea10+V0dkW7sOGnJFW5PyW1F/TBBe
+3dsp8Tz88+oHbSGwV7qF/Qf6U6kRxeVVctmSSCAohUbPH26xhPhk+t1TVdb3EA==
 -----END CERTIFICATE-----
diff --git a/tests/standalone_2/io/certificates/trusted_certs.p12 b/tests/standalone_2/io/certificates/trusted_certs.p12
index 76c76ec..f45af0a 100644
--- a/tests/standalone_2/io/certificates/trusted_certs.p12
+++ b/tests/standalone_2/io/certificates/trusted_certs.p12
Binary files differ
diff --git a/tests/standalone_2/io/certificates/trusted_certs.pem b/tests/standalone_2/io/certificates/trusted_certs.pem
index 8b5bf3e..dd8edb4 100644
--- a/tests/standalone_2/io/certificates/trusted_certs.pem
+++ b/tests/standalone_2/io/certificates/trusted_certs.pem
@@ -1,18 +1,19 @@
 -----BEGIN CERTIFICATE-----
-MIIC+zCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
-YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNFoXDTI1MTAyNDEwMjYzNFowGDEWMBQG
+MIIC/jCCAeagAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE4MDQyMzIwMTYzM1oXDTI4MDQyMDIwMTYzM1owGDEWMBQG
 A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAMl+dcraUM/E7E6zl7+7hK9oUJYXJLnfiMtP/TRFVbH4+2aEN8vXzPbzKdR3
-FfaHczXQTwnTCaYA4u4uSDvSOsFFEfxEwYORsdKmQEM8nGpVX2NVvKsMcGIhh8kh
-ZwJfkMIOcAxmGIHGdMhF8VghonJ8uGiuqktxdfpARq0g3fqIjDHsF9/LpfshUfk9
-wsRyTF0yr90U/dsfnE+u8l7GvVl8j2Zegp0sagAGtLaNv7tP17AibqEGg2yDBrBN
-9r9ihe4CqMjx+Q2kQ2S9Gz2V2ReO/n6vm2VQxsPRB/lV/9jh7cUcS0/9mggLYrDy
-cq1v7rLLQrWuxMz1E3gOhyCYJ38CAwEAAaNQME4wHQYDVR0OBBYEFHEPkNAdOa2k
-MUoM6Ix/kUCLq99vMB8GA1UdIwQYMBaAFHEPkNAdOa2kMUoM6Ix/kUCLq99vMAwG
-A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBABrhjnWC6b+z9Kw73C/niOwo
-9sPdufjS6tb0sCwDjt3mjvE4NdNWt+/+ZOugW6dqtvqhtqZM1q0u9pJkNwIrqgFD
-ZHcfNaf31G6Z2YE+Io7woTVw6fFobg/EFo+a/qwbvWL26McmiRL5yiSBjVjpX4a5
-kdZ+aPQUCBaLrTWwlCDqzSVIULWUQvveRWbToMFKPNID58NtEpymAx3Pgir7YjV9
-UnlU2l5vZrh1PTCqZxvC/IdRESUfW80LdHaeyizRUP+6vKxGgSz2MRuYINjbd6GO
-hGiCpWlwziW2xLV1l2qSRLko2kIafLZP18N0ThM9zKbU5ps9NgFOf//wqSGtLaE=
+ggEBALkvRWdbx9GwxePkh0nnpht4MrPW5NkZBORqfhFi7PFbQ7Rwgl39hm9iAmci
+pOWZGSJi7AaqLuSID0UEeRdG/fNFawI5XIoxP+TmdKdrk/SaTJQKKJiZ9B8+EG0z
+hV8/v6jrlwj0gq9eBBAmOInnmQiEYE4gKFNvh9xdP//gi+otBf30gmtJ4AxXOTu/
+M+XEigXelmIvy57b+B+qnonTFcGkXhSr+JfCA1l6ta7OtknQtItpV0FDr/d8hA+6
+Bn25ZSisd00GC3CUMX1tM5V8cQE6GO/W2mnpUFVvWycYx9wDyU7rlyNUf8nWeoIW
+3d3s/6KAppa07KrkLiTantIrqMUCAwEAAaNTMFEwHQYDVR0OBBYEFPSsP2VFSGom
+8CDuF8ETP9mocLMeMB8GA1UdIwQYMBaAFPSsP2VFSGom8CDuF8ETP9mocLMeMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ1VynTevPnNtwevQpUa
+zlur64N+Dx/yF4gvd4byjO+JouMJLaJqV2dwnqgAahg6YKasVtv4xX9MVJR2IjIb
+Tfa0nYQxM5clwk3J78nh82Ncb2RNeYJyNmSdocnOkmTSoOGUFOxtRz1vmKUcrfwl
+yENO/qGe/sYmOv0IWJjeGQ2OZPblRumV4dJy3qTHFmOLpYwA0BGiIV5uj5Ou7QU1
+R5PY2pnJg4RXeaq95Pr50lkO9vpRyFUJHjR+P+J05M9FbjLPOQIFkpMYx/GyBg5n
+P+omyagOGW8bXfBTtUYu+rP/k+BC5AxI3Kdv/AD5vyHKi/JXhP3ycb8AYx5ENHoK
+qjA=
 -----END CERTIFICATE-----
diff --git a/tests/standalone_2/io/certificates/untrusted_server_chain.pem b/tests/standalone_2/io/certificates/untrusted_server_chain.pem
index ff6e568..4845069 100644
--- a/tests/standalone_2/io/certificates/untrusted_server_chain.pem
+++ b/tests/standalone_2/io/certificates/untrusted_server_chain.pem
@@ -1,59 +1,60 @@
 -----BEGIN CERTIFICATE-----
 MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
-cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDE5MTE1NTEyWhcNMjUxMDE2MTE1NTEy
+cm1lZGlhdGVhdXRob3JpdHkwHhcNMTgwNDIzMTcxNTEzWhcNMjgwNDIwMTcxNTEz
 WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQDca2l3VIWhnlTqazrA07hiHjgXACUYS/nVox+a2Jar383kBz2kzN6B
-u4K7IwD2msym2IOBp1YT9OKPh9/KkSGvpPelu7ToCoehala32W+0ozh53CR8IpzQ
-tmh7J9oHtN2PcbLgEzHfAWyrY3xp9RpWUONjxoG8xXPedNsZL0Rj65Z3fKAjOypl
-+XJsgrqrNNAi3x0OMdhextMmLrYl+YQjgdND8UpykTSc8Q0vwngDZuLH/Nhx0cAA
-Ade0ZfXS6snwWVxrWke+zGF6yANoiV00gsBhq+WZZ50SmE2mz5LT9uj4t5WpcOI/
-2TlbV9HSjdOEAFD8cJIrK5FkEmz383E1AgMBAAGjgbQwgbEwPAYDVR0RBDUwM4IJ
+ggEKAoIBAQDO+XxT1pAvzkIWvAZJFGEjuIuXz1kNoCDxBHAilptAOCX5sKyLaWTc
+YvzYpDf0LOwU3T/ZtlSinkX2xCY7EXgsGJEFc1RDmhmPmSsY9Az/ewS1TNrTOkD5
+VGUwnRKpl3o+140A/aNYGQfHJRz0+BCLftv7b95HinLDq26d01eTHLOozfGqkcfA
+LfUauiwXRV817ceLiliGUtgW8DDNTVqtHA2aeKVisZZtyeEMc3BsnJDGmU6kcQ4B
+KeLHaaxCufy4bMlObwSLcdlp7R6MTudzKVEjXVz/WRLz7yZYaYDrcacUvsI8v+jX
+B7quGGkLGJH+GxDGMObFWKsAB229c9ZlAgMBAAGjgbQwgbEwPAYDVR0RBDUwM4IJ
 bG9jYWxob3N0ggkxMjcuMC4wLjGCAzo6MYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAA
-ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQO+6Atr6tkTBmPasN4oTDUlbxQ1zAf
-BgNVHSMEGDAWgBRrkK4hOni2neySWQNmMfb9imn/+DAOBgNVHQ8BAf8EBAMCA6gw
-EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBACdVUzrhfXoW
-wG0zI9aT6CxD7T0i0WK4fC6Yrx0Pqz53xnuiwBfvuAJ/PRXKYsJMxa2LuHGJKU/A
-nImCXGJHoUwL6x4Eor6fg7L9nPNqtIrQ6tzubxNtVPpLj4tK6Ps3IM+FICYUSX0b
-FLSfnv74afUp/2+0OHsoUVsL1rCTO2WgEkEShLERdJvdcvUSTWHfC5IQORS9vfzG
-+cZGOOPebfm8TY2DJxMYj/t7CHs1Sk550x590sKb/prwtJAYtQxGe7v0m9rihiM3
-dFKZiNh99yXbQ1ELYyhkFP8WAdK8ZTnynGqgAYJmV89Dg8k2uU8z+dahlE3foORD
-Y/Gn0CZE1NY=
+ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBR6zQbX0GnDCsjksKYXlzovO2yplDAf
+BgNVHSMEGDAWgBSkX16pB/ZB0hzdYIUgMhWO89CxZzAOBgNVHQ8BAf8EBAMCA6gw
+EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAIDPqZllHvJa
+XSpqOFaT7oFzKbBnV8lLMvYnbDWHL8N+23q+y803GGNRMkDJG98OalqqKMskk4/v
+ek6dhkTHKnB7hunhogIICXCcHOJGaHN67vvkxkP5mTx6AMaPT+q6NXzu2y9YBTkr
+BIw6ZUyPxqIcH4/GezVe+pokvNZHghDePBChALXEmQLBuJy+gM55w4nB5eq8pNnP
+1r9vVhlr4jqiVNd95MglwB4xLQV5SeG8gGwGvad0vvIpHljOwT9TmlofeqqGpPLf
+3LtqrBK5qdxWcn0jDxG/Qe2EfsdmzsCQ+imu5rTc1YMCGZD52mnnq4tZj0hroWLn
+Wys+JpPMdKo=
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
-MIIDLjCCAhagAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
-YXV0aG9yaXR5MB4XDTE1MTAxOTExNTUxMloXDTI1MTAxNjExNTUxMlowIDEeMBwG
+MIIDLjCCAhagAwIBAgIBAjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE4MDQyMzE3MTUxMloXDTI4MDQyMDE3MTUxMlowIDEeMBwG
 A1UEAwwVaW50ZXJtZWRpYXRlYXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEA1OV9iea75DPQ18NppXxEFW26J7IfjUvp4wVnj9m7pOhsByqd
-wwS6hpjlkpEwCyugKD/t7u/VGwp2BB+BeaX7FPj6rnYY82bOJQlyB/vvDmOZfAe2
-84ug9O7QcsQHSQ7YQFuvYKaeYCKdrGjzQPVYkoVdv2js2dYTDG3QSIxpbi305Vef
-ia6Zfs5CAW/SfL36+ETo2pXNlD1ZBGRL8H3z+mMnIEj1Tbaipf+1Npr2l3xqIs1k
-RWsM3X+9xMkWGyvsDdbLIGiTTVxM9kOF0aNLdQIKb2tZsg4jRrFIgiO+5TXwp0FW
-4ldc5/GhtaoPDcsIALyIQc7CJ/PpPm9hnxIy7QIDAQABo3sweTASBgNVHRMBAf8E
-CDAGAQH/AgEAMB0GA1UdDgQWBBRrkK4hOni2neySWQNmMfb9imn/+DAfBgNVHSME
-GDAWgBRpz+jRK9iGqijrL/4WCsGsIjxoETAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
-BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBACcwiLJUPzYGIeGIYGlo
-XlP4++adiPlXvsyTxLdGVSFWJMBV5EhtiXQXaUsOs2PyC7SWxiiUdAgE8Y2tMsF3
-Bh5LY/kKxZQXZuFa+RN1kPlhlYJWdiPyqcBziSPFBtqwudWLDUVSaVAQDhYYVB3K
-5+pFaeQKfhYmPvJKR9U2nTvukOhN1fZM8GUBnm2uaiA3giQ0wxXyQIuqC9S52qbh
-x4D4ZdbshQAgThPkHBoZVmd/NF1TNzitZZy7uaU7GpGrS1dcevN7pEUwm3+KIkIT
-AOSLB2FbFOwPUg6a/lWkFPotT3gl0tdyCaqkfneGCHzVciT0JTS/AqpdYEtuxEMe
-PJk=
+AQ8AMIIBCgKCAQEAvpFatw9XMWQDbKzWtsA5NfjQsddw5wlDpFeRYghyqo/mgWru
+Rapcz6tEpEodc3SZ/4PCwE1PmYZuxhcYnaDCM3YdmJAMPUhqi+YO+Gc7WNTbrOR0
+aJGzS2HEPxjbC4OsFG7TVuKMH1uI4rWOZxBn4rODkTmiH7epuyu65nzUJemct8GV
+OcPChjPVKvXzbHVtk8UVreD/DVyuYwsBMSAuYWiq2pgAAQV/7TKVDAQ8yRVW28J7
++QrNXqV+I6MZeMho45xgLNQmi5os9vqTuEu3oGyLFWxXz6uJ2MOFOFTjxMhHGcGn
+aICAA9BIcCeaWWRN9nZkvQuS2nysvJwBu/LROQIDAQABo3sweTASBgNVHRMBAf8E
+CDAGAQH/AgEAMB0GA1UdDgQWBBSkX16pB/ZB0hzdYIUgMhWO89CxZzAfBgNVHSME
+GDAWgBR9W+i1d5oZtiZAEjI9RDLd9SnUnDAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
+BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAIdIh5sIk9Qi2KZfzJUQ
+/DmMTv6NZzAGROJGA+o6jfrMh/plzBre7QM2vzw6iHxFokepLnsXtgrqdtr1lluO
+R6apN2QLp5AJeT8gZfn0V35Wz2iYn+fJR77Map3u57IOj08gvk/BZmJxxqMT/qH/
+1H5qpd934aFLSgqsmpGOVIzrdwHVmwOKU9SDNxOILVpvgtjQ/KWEUxftKtU7Z/dd
+WGN56Vu3Ul0gzgCFifj8mnHnHpug/wEHLl0l2hk3BD1AUrCyCK4yalvsDV7vFex7
+8+Whuh4OijTP/yomn8VGPN5lMmGT4XN8Z3h97PUHF9yF4FYGJJ/lilIhxctashk+
+HuE=
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
-MIIC+zCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
-YXV0aG9yaXR5MB4XDTE1MTAxOTExNTUxMloXDTI1MTAxNjExNTUxMlowGDEWMBQG
+MIIC/jCCAeagAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE4MDQyMzE3MTUxMloXDTI4MDQyMDE3MTUxMlowGDEWMBQG
 A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAMDzkcftGzdNJz5vXEAZSCAO2J6bCPz896pK3qtaViR/aF8I2vHZQm0IEoJc
-Y1NUMF3F50d6fMYCkEoORAkC0d7iAwTprhBdIg35+TxwGObcStrohDtEgwFmFRzg
-LtYeXiU0t0dBWOOQ9k2f9VGqbzKwZ2dbhOHSTXMTFoEcMStbeFc++oiOLY+QSq/J
-Xd/BXqvwVM3Mt+OwLvyUu45Kw18ENo77qubIPJUwoyaf+N2nFRqcc7bmNy0Wvk2Q
-StvQXy6DpN3KOoZx/sR7Ff8hYuHXcxbSsJ1hOO+tIJyOZyEJvU2BBOYVlKr4E4JU
-mkex0CM1IfIFqfcEkbvjwLjaojsCAwEAAaNQME4wHQYDVR0OBBYEFGnP6NEr2Iaq
-KOsv/hYKwawiPGgRMB8GA1UdIwQYMBaAFGnP6NEr2IaqKOsv/hYKwawiPGgRMAwG
-A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJKl4RCEaXwtosNeurZlS3b9
-owXdsXDRdnfEawcc//AbRkrS4bHCQyOJNp/3DibEKkeAXCJrJ5cvXRjE5gb3Q+rl
-0AqziLY15xuMAxUK3zv0e8Zir21PQzQ9x8zbmlucEoT/jn7KvMSSqfEoer77cXev
-BpmQDQzE3FNgKohmHIzIDoTPiU3ahv6x8IhJ1e47UmRsSPFgtqglHcdCYIEclXpY
-bHvctT6+pFZuJfIs9+BATMXPJWSX7NhlMcnyP+xdDxDKuF/nwVFy6xA+njuWnnZT
-TyiGCnx+u/VpKzOrwMfzv2DW8Db80UERoox5n6QNQLnXNWPMddUL92/p9lMzWJY=
+ggEBAMuTL5lztughNg/G/9Ge8c6EmROymW0zGTN6hRp3rG2SkpJdag08ntKAmny3
+ilpnlEoxGOk1L9jq/lJsCsiqsSETCadkLsXFNeKOG+S48nc8ThOrmJe5WV6NDNmn
+qaQeek5rjvuRSdukhyZVLzmIyTYNErwkMuo+Jk1V7IS1X2pFyTfF+SLlYrOuDQIW
+qXYfWqdMSYpI8s3onIwR/qVapGu55D0CECzNyX6ZBnqYK0cGzmRaZToT84VPsJwB
+DmALQw9WNNn1CHAIt17CwsdSSasgaKz/XDDjwgKL7CI6bFttDIWVLBt8ikrsrjZN
+6L5b8PZx/dHwJJ7QjYOMKKSUjyECAwEAAaNTMFEwHQYDVR0OBBYEFH1b6LV3mhm2
+JkASMj1EMt31KdScMB8GA1UdIwQYMBaAFH1b6LV3mhm2JkASMj1EMt31KdScMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJTJx9nh+fTJ6a0aIzPY
+FUX5tg+MdUxsAG5QA2jrwZIKCSrHa/ka0vjwLO+94EWcWgKdNDu8lt2FPnJh0nzN
+Ad/CaQNSMesihlmGOgxvLgd3ndYDVYjsCrXx3ESoRavgAWXY+/p69KR1ibVLpKF/
+yr/YURqT9SLKAlgrZt5I/syzxhWdAND62oxqiDCMzPoVR2cLswIUDNRvq5nRiCIt
+1TLPDINjG1EdmwzV2jyPxphL8esopopVm/d9wgD0xQ2Ocb2Nj6Jduuli0sm+dVBL
+3t2pldRq0hXZt/9qhu38tF41TlKSpCz2oFyx2D6ObLSX0MeFp6zXM0c1lGqSCDIM
+ubk=
 -----END CERTIFICATE-----
diff --git a/tests/standalone_2/io/certificates/untrusted_server_key.pem b/tests/standalone_2/io/certificates/untrusted_server_key.pem
index 29a9e32..b281bb3 100644
--- a/tests/standalone_2/io/certificates/untrusted_server_key.pem
+++ b/tests/standalone_2/io/certificates/untrusted_server_key.pem
@@ -1,29 +1,29 @@
 -----BEGIN ENCRYPTED PRIVATE KEY-----
-MIIE5TAcBgoqhkiG9w0BDAEBMA4ECKAry4fwmB/TAgIIAASCBMNsKbVVvIs/l6/N
-/1J9WXSiA1gnRTd2n58GJUV6mkiaRUMiWu3fK+V7iHpIi7KeLeD+JGsDeqxw0bB5
-lmS/RJy0wNBP0PL0oiI8VUe3wxTUU2b5wW9fomeOTGWOIUL5VZXHkTCf5KMcFWMY
-GMnDpIN/f/m9zvz/3FogxIZlIAxG7gKKrfEcKExIShAJ5wYDbDSFZWfNcjMODGPn
-xz3W04aRsJGf3KlOQvSuNtcBpsuwXuAXezzuFETM20xrWW3iJIsO5UmqJ1OJcdet
-A+k5k0K+1/WwLkceWJYSd19O+7LNULsZhKUJ515ZSO1TJGgfd5DznkgRXYUx5ucS
-tvJLYvShGbaYulsVKn8q2nkIxnQCov3my1hIRk/qCKb+uOvRD9dIkjSlNubqaRb6
-geEOfTh1g5PCeKPlSTkVueLQqWxKMye4eWYqUxExkUNuGJ0d2ndBGJRo6bulnc7I
-kt44DzEufV5OLvyTufimpohqRm3Yzq87DWSSThCKOGkhfGutn8B7cJR8ZPrG2euT
-J7Bv4EuFjhpKDieqDi8yoXgIkWSgyzFNMsewV4lxFNP/wbvoKPFrKsU4ny6jRfzy
-WTjMN1UOTBvsyZbVvjLII79cBKLqlowHAZQ7YwuxtbjeB9FRH+ZwkzYeyn4GNHdf
-QoVwOMKAiOMjzAK9qdW7isVXy/7v9EXaZplRmwMRhCZevC9zeY2Rueahq8qpHpH1
-GPjrew5elPkBRQhxX6IiL7kI7upE65UI5hnnTnrdrZkRmMYOFEZLyLbTU4wMCxui
-4BmEiGp6qCWe3UND1b8YhG+gsRYzHK5oEJV+Ck7m+e9iU3/axggUfAhZeBmdlgqd
-bUajlzcgbtfaSgZ08XXU1YPw0aLlmJGzb+oWMFwBJHAUYpOV2uqDHiXZZt4SoAF9
-gJQaXvqMGzY8JyP5ZQauljVtPGcopA+jbix3Rbwf97lLqJHSpWoHpcCa6FrfaMqG
-dx8oQsO67WN0gm5DIN3kB2jHOj9Nf7kr3HGjyC5tPq8s1+aT6baZcHWzVfyVr10c
-9X13Pz5XzEa1oiaO7JDPkzb9T7aPJZwskATNB8h6tWfqdGyUY5eURtsCnVrtG/1p
-pAXyY/0vAksfDPjMChKLKxZ7rBbscoNzr2f7Vw4CTnIpaxA4eLEx6UdpG4/5RzYJ
-0YuR+SzCkuNti7uZGi9DCGkZkYl6VndatW+Pk/+JVBexdKt6MsER6aVsS8ev9UbW
-JG+2C8bjMlfKy21644KwYOtZbVcE9jwlsz8w+e6YbOzBvbwiPmoCi0xcMxRJPa2y
-cKMrs2hSKmhUP6uIH0b0qNcHEPA32mVzGC0MToC5R+yb6OdyvoEsisqS7tEAMfTJ
-0yowcZr2lPehaMr4efSB8JY6DuofitfgI6X6bmiIPQ9v//djxhkxkRAbpTRGmFZx
-1YIKDa72S8jUxHWlVvmoqTWI8T+jltF2pYBctS6IMKEot/CcBCHb5l1zfMyo5a0x
-73ooh5tq+vRWJGaLRMj66VVSWGQoJmfAGwWpjBpTLa0UQoHO0/J1IbfjFOj5HV3J
-bscmoGWhVwuJM5ActB0MOvXGQe9mf2X4p/1Rp+yBuipH1SJzFEzbOZ3kE50Z6aXH
-CoJJOKkcuf43
+MIIE5TAcBgoqhkiG9w0BDAEBMA4ECI8YmURjepD4AgIIAASCBMMwp7gfo4FvSVuR
+5w7+OcjkXNQmvrwTRFDaMWV3ORgVFMQx02Q325SnoQsmulB+dk19uj2Piel5j/+j
+xHLvC0rBQC8BjHg/uLmN/f9yW6qolDthmeJEad/L8slB7rziilOGmlPh7H1voJgr
+94uoTn6L2tE9GfoPDsksedRtGIlgSOM3UmLvCkCMcZBqrDi4uqzbhrW3bIbqdoeo
+1lbNsvFuNzF+P3cBHyUUZpPGwCZ8M/XCsCAB+9eH7TM2FJnbuffA6BfkanpQR0ul
+PLo5KDjcS5lQ4YUkI2+lYMSZMiIf50Y8eHP0QnDAuYunA2cPLd90rPpdBCgNtQqk
+aUI7FHvtLFZsTJ1s8EPnZhZOZq1LYUTFQuimMWz+nvC0oQy925brwyjfnrm44KS7
+xpJqsYMBHYflDCwE4LbxjFSeneOy4wwNMurupSdcLCm02Sm1wUMrzRrNsAy3jxP6
+TfJjHRBSt3XEDwDG3olQoK/Ewa1qP0JhAZOd7SrKw9eLQltH+djy0iDUblf5uIHj
+pDC+T1pY9tTwSVxhsJI5a0qxXYNgdaxhr0Fv8BbdScd8Tzdw7g4AByjvgCKArlNJ
+alR1ZaJP/JYuzb3VH8uXEO4b6Tjqw9O4tkZGrc8He5HTAOnSZKbclDxyRH8hkDy+
+apIJUjbE3Gc1mCbyo2nc6WDrGfQNrXDWAVIz4/lb8e8P5k1Rex4rVNhb/VA0Vh4m
+T2BSQ3pvZtKTFedvWgIFIk85rVaYyuB7Icb0YLs2cPppMCfbv+6bOMkJ4hVk5tbX
+AGk6FOjgqsQSY/gzDo9ReCJooETP2AmvHEi2b7LKs+M0Pw+CfvKD/dOkQp62WMpt
+vZJVSXIQ2bHarbhxmUxcT//G+i3QBgkM2xTRvARfRMBiCoBh0Ta3gd4/GJDwv8pr
+pkJi3Q6u88NfGG0eyYyHz+kqTtptqJj1hbAFPdt6d6sFL/wpwhK/L5MOECQ3m100
+N3/aGT7yizM0w/m6PSycSbXycRafRF3XNMBXsUWeFpSWxpJV9GH+T3z8k46GrsM6
+c3YrLG6nvmersDI2AuS9KuhIQQvp+sgwjt3HeURsDv3X4edgCILRTjv3nVuU+DGD
+Xd8CuPYmRei4eJ4nkzxY6fM7ticuArnyE+INVtA0T8yL4UbRxQV/f9jOZWJ1LXLr
+caxCOZP9YcDVG9JUK4WGUC3LVWfhJW+i51cLJk9iGZ8qDLSvgJhj+/7Ajsg6/4xO
+IPon0DVMD9jgMSWLdfpCPawyY+VLVH2CXB2z83c2818gAs85QGUlsW+xLkELSTIU
+6p+mtTF5B2IhsjEdMDAWOpAp/Gj/U9OKapTyE1sGxn66jG/UvxcgYqZo3JGjNaDE
+rMnBhOH4VQQ+FxCA6lXKYCcU1UEze5BuCzJCA7gmCceMlMe+1Car2F+nJCuLNtzB
+uJhlXDbIVhMb5cZBBd3LSjmuRZ/gWbMvV3UqoCROBXqLzVGTufpcn/MgYQKYYHkp
+I+vKDypj0a4IPovDdxg8aMKNn59mtvmMDyrt0716H9DP4SCU/nuxVSeT/HywRBo/
+53fxqtdH3hTAUXqcOLzHnvLUENiABKMeJOtGTV9MFCxgGsnzgYNXnB9hDhm84+IX
+JQdMjj+BNFE6
 -----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/standalone/io/create_sample_certificates.sh b/tests/standalone_2/io/create_sample_certificates.sh
similarity index 87%
rename from tests/standalone/io/create_sample_certificates.sh
rename to tests/standalone_2/io/create_sample_certificates.sh
index cabe747..c2060c1 100755
--- a/tests/standalone/io/create_sample_certificates.sh
+++ b/tests/standalone_2/io/create_sample_certificates.sh
@@ -43,6 +43,9 @@
 openssl req -subj /CN=localhost -batch -verbose -passout $password -new \
     -keyout localhost_key.pem -out localhost_request.pem
 
+openssl req -subj /CN=badlocalhost -batch -verbose -passout $password -new \
+    -keyout badlocalhost_key.pem -out badlocalhost_request.pem
+
 # Sign the server certificate with the intermediate authority.  Add the
 # certificate extensions for SubjectAltName and that it is not a CA itself.
 openssl x509 -req -in localhost_request.pem -out localhost.pem -set_serial 1 \
@@ -50,6 +53,11 @@
     -passin $password -extfile ../sample_certificate_v3_extensions \
     -extensions localhost -days 3650
 
+openssl x509 -req -in badlocalhost_request.pem -out badlocalhost.pem -set_serial 1 \
+    -CA intermediate_authority.pem -CAkey intermediate_authority_key.pem \
+    -passin $password -extfile ../sample_certificate_v3_extensions \
+    -extensions badlocalhost -days 3650
+
 # Create a self-signed client certificate authority.
 openssl req -subj /CN=clientauthority -set_serial 1 -batch -verbose \
     -passout $password -new -x509 -keyout client_authority_key.pem \
@@ -72,30 +80,35 @@
     -passin $password -extfile ../sample_certificate_v3_extensions \
     -extensions client_certificate -days 3650
 
-# Delete all the signing keys for the authorities, so testers that add
-# them as trusted are less vulnerable: only the sample server certificate
-# and client certificates will be signed by them. No more certificates
-# will ever be signed.
-rm root_authority_key.pem
-rm intermediate_authority.pem
-rm client_authority_key.pem
-
 # Copy the certificates we will use to the 'certificates' directory.
 CERTS=../certificates
 cat localhost.pem intermediate_authority.pem root_authority.pem \
     > $CERTS/server_chain.pem
 
+cat badlocalhost.pem intermediate_authority.pem root_authority.pem \
+    > $CERTS/bad_server_chain.pem
+
 cat intermediate_authority.pem root_authority.pem client_authority.pem \
     > $CERTS/server_trusted.pem
 
 # BoringSSL only accepts private keys signed with the PBE-SHA1-RC4-128 cipher.
 openssl pkcs8 -in localhost_key.pem -out $CERTS/server_key.pem \
     -topk8 -v1 PBE-SHA1-RC4-128 -passin $password -passout $password
+openssl pkcs8 -in badlocalhost_key.pem -out $CERTS/bad_server_key.pem \
+    -topk8 -v1 PBE-SHA1-RC4-128 -passin $password -passout $password
 openssl pkcs8 -in client1_key.pem -out $CERTS/client1_key.pem \
     -topk8 -v1 PBE-SHA1-RC4-128 -passin $password -passout $password
 openssl pkcs8 -in client2_key.pem -out $CERTS/client2_key.pem \
     -topk8 -v1 PBE-SHA1-RC4-128 -passin $password -passout $password
 
+# Delete all the signing keys for the authorities, so testers that add
+# them as trusted are less vulnerable: only the sample server certificate
+# and client certificates will be signed by them. No more certificates
+# will ever be signed.
+rm root_authority_key.pem
+rm intermediate_authority.pem
+rm client_authority_key.pem
+
 cp root_authority.pem $CERTS/trusted_certs.pem
 cp client_authority.pem $CERTS
 cp client1.pem $CERTS
diff --git a/tests/standalone_2/io/http_server_test.dart b/tests/standalone_2/io/http_server_test.dart
index fa3b1ea7..1a9829d 100644
--- a/tests/standalone_2/io/http_server_test.dart
+++ b/tests/standalone_2/io/http_server_test.dart
@@ -137,13 +137,13 @@
 
 void testHttpServerZone() {
   asyncStart();
-  Expect.equals(Zone.ROOT, Zone.current);
+  Expect.equals(Zone.root, Zone.current);
   runZoned(() {
-    Expect.notEquals(Zone.ROOT, Zone.current);
+    Expect.notEquals(Zone.root, Zone.current);
     HttpServer.bind("127.0.0.1", 0).then((server) {
-      Expect.notEquals(Zone.ROOT, Zone.current);
+      Expect.notEquals(Zone.root, Zone.current);
       server.listen((request) {
-        Expect.notEquals(Zone.ROOT, Zone.current);
+        Expect.notEquals(Zone.root, Zone.current);
         request.response.close();
         server.close();
       });
@@ -158,15 +158,15 @@
 
 void testHttpServerZoneError() {
   asyncStart();
-  Expect.equals(Zone.ROOT, Zone.current);
+  Expect.equals(Zone.root, Zone.current);
   runZoned(() {
-    Expect.notEquals(Zone.ROOT, Zone.current);
+    Expect.notEquals(Zone.root, Zone.current);
     HttpServer.bind("127.0.0.1", 0).then((server) {
-      Expect.notEquals(Zone.ROOT, Zone.current);
+      Expect.notEquals(Zone.root, Zone.current);
       server.listen((request) {
-        Expect.notEquals(Zone.ROOT, Zone.current);
+        Expect.notEquals(Zone.root, Zone.current);
         request.listen((_) {}, onError: (error) {
-          Expect.notEquals(Zone.ROOT, Zone.current);
+          Expect.notEquals(Zone.root, Zone.current);
           server.close();
           throw error;
         });
diff --git a/tests/standalone/io/sample_certificate_v3_extensions b/tests/standalone_2/io/sample_certificate_v3_extensions
similarity index 85%
rename from tests/standalone/io/sample_certificate_v3_extensions
rename to tests/standalone_2/io/sample_certificate_v3_extensions
index f9e741e..f17764d 100644
--- a/tests/standalone/io/sample_certificate_v3_extensions
+++ b/tests/standalone_2/io/sample_certificate_v3_extensions
@@ -25,6 +25,13 @@
 IP.1 = 127.0.0.1
 IP.2 = ::1
 
+[badlocalhost]
+basicConstraints = critical,CA:false
+subjectKeyIdentifier = hash
+authorityKeyIdentifier=keyid,issuer
+keyUsage=critical, digitalSignature, keyEncipherment, keyAgreement
+extendedKeyUsage=serverAuth
+
 [intermediate_authority]
 basicConstraints = critical, CA:true, pathlen:0
 subjectKeyIdentifier=hash
diff --git a/tests/standalone_2/io/secure_bad_certificate_test.dart b/tests/standalone_2/io/secure_bad_certificate_test.dart
index 60a2623..e002313 100644
--- a/tests/standalone_2/io/secure_bad_certificate_test.dart
+++ b/tests/standalone_2/io/secure_bad_certificate_test.dart
@@ -4,6 +4,8 @@
 
 // OtherResources=certificates/server_chain.pem
 // OtherResources=certificates/server_key.pem
+// OtherResources=certificates/bad_server_chain.pem
+// OtherResources=certificates/bad_server_key.pem
 // OtherResources=certificates/trusted_certs.pem
 
 // This test verifies that the bad certificate callback works.
@@ -22,6 +24,11 @@
   ..usePrivateKey(localFile('certificates/server_key.pem'),
       password: 'dartdart');
 
+SecurityContext badServerContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/bad_server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/bad_server_key.pem'),
+      password: 'dartdart');
+
 class CustomException {}
 
 main() async {
@@ -35,6 +42,15 @@
     if (e is! HandshakeException) throw e;
   });
 
+  var badServer = await SecureServerSocket.bind(HOST_NAME, 0, badServerContext);
+  badServer.listen((SecureSocket socket) {
+    socket.listen((_) {}, onDone: () {
+      socket.close();
+    });
+  }, onError: (e) {
+    if (e is! HandshakeException) throw e;
+  });
+
   SecurityContext goodContext = new SecurityContext()
     ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
   SecurityContext badContext = new SecurityContext();
@@ -52,14 +68,18 @@
   await runClient(server.port, defaultContext, false, 'fail');
   await runClient(server.port, defaultContext, 'fisk', 'fail');
   await runClient(server.port, defaultContext, 'exception', 'throw');
+
+  await runClient(badServer.port, goodContext, false, 'fail');
+
   server.close();
+  badServer.close();
 }
 
 Future runClient(
     int port, SecurityContext context, callbackReturns, result) async {
   bool badCertificateCallback(X509Certificate certificate) {
-    Expect.isTrue(certificate.subject.contains('rootauthority'));
-    Expect.isTrue(certificate.issuer.contains('rootauthority'));
+    Expect.isNotNull(certificate.subject);
+    Expect.isNotNull(certificate.issuer);
     // Throw exception if one is requested.
     if (callbackReturns == 'exception') throw new CustomException();
     if (callbackReturns is bool) return callbackReturns;
diff --git a/tools/VERSION b/tools/VERSION
index 4229ed2..5c6fbcc 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 0
 PATCH 0
-PRERELEASE 49
+PRERELEASE 50
 PRERELEASE_PATCH 0
diff --git a/tools/apps/update_homebrew/lib/update_homebrew.dart b/tools/apps/update_homebrew/lib/update_homebrew.dart
index 477ddb0..0d2fcbb 100644
--- a/tools/apps/update_homebrew/lib/update_homebrew.dart
+++ b/tools/apps/update_homebrew/lib/update_homebrew.dart
@@ -185,10 +185,6 @@
   def caveats; <<~EOS
     Please note the path to the Dart SDK:
       #{opt_libexec}
-
-    --with-dartium:
-      To use with IntelliJ, set the Dartium execute home to:
-        #{opt_prefix}/Chromium.app
     EOS
   end