Version 1.14.0-dev.6.0

Merge commit 'dcb021c5d99ae5c1cd7dc96ba4f839101944f327' into dev
diff --git a/DEPS b/DEPS
index aa5c78c..e041804 100644
--- a/DEPS
+++ b/DEPS
@@ -7,13 +7,6 @@
   # simply sdk, but if using special gclient specs it can be different.
   "dart_root": "sdk",
 
-  # The svn location to pull out dependencies from
-  "third_party": "http://dart.googlecode.com/svn/third_party",
-
-  # Use this googlecode_url variable only if there is an internal mirror for it.
-  # If you do not know, use the full path while defining your new deps entry.
-  "googlecode_url": "http://%s.googlecode.com/svn",
-
   # We use mirrors of all github repos to guarantee reproducibility and
   # consistency between what users see and what the bots see.
   # We need the mirrors to not have 100+ bots pulling github constantly.
@@ -30,18 +23,15 @@
 
   "gyp_rev": "@6ee91ad8659871916f9aa840d42e1513befdf638",
   "co19_rev": "@3ed795ea02e022ef19c77cf1b6095b7c8f5584d0",
-  "chromium_url": "http://src.chromium.org/svn",
   "chromium_git": "https://chromium.googlesource.com",
 
   # Revisions of /third_party/* dependencies.
-  "7zip_rev" : "@19997",
   "args_tag": "@0.13.0",
   "async_tag": "@1.4.0",
   "barback_tag" : "@0.15.2+7",
   "boringssl_rev" : "@daeafc22c66ad48f6b32fc8d3362eb9ba31b774e",
   "charcode_tag": "@1.1.0",
   "chrome_rev" : "@19997",
-  "clang_rev" : "@28450",
   "cli_util_tag" : "@0.0.1+2",
   "collection_rev": "@f6135e6350c63eb3f4dd12953b8d4363faff16fc",
   "convert_tag": "@1.0.0",
@@ -52,11 +42,9 @@
   "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
   "dart_style_tag": "@0.2.2",
   "dev_compiler_rev": "@0.1.9",
-  "firefox_jsshell_rev" : "@45554",
   "glob_rev": "@704cf75e4f26b417505c5c611bdaacd8808467dd",
-  "gsutil_rev" : "@33376",
   "html_tag" : "@0.12.1+1",
-  "http_rev" : "@9b93e1542c753090c50b46ef1592d44bc858bfe7",
+  "http_tag" : "@0.11.3+3",
   "http_multi_server_tag" : "@2.0.0",
   "http_parser_tag" : "@1.1.0",
   "http_throttle_rev" : "@a81f08be942cdd608883c7b67795c12226abc235",
@@ -76,7 +64,6 @@
   "observatory_pub_packages_rev": "@cf90eb9077177d3d6b3fd5e8289477c2385c026a",
   "package_config_rev": "@0.1.3",
   "path_tag": "@1.3.6",
-  "petitparser_rev" : "@37878",
   "ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
   "plugin_tag": "@0.1.0",
   "pool_tag": "@1.2.1",
@@ -86,7 +73,7 @@
   "quiver_tag": "@0.21.4",
   "root_certificates_rev": "@c3a41df63afacec62fcb8135196177e35fe72f71",
   "scheduled_test_tag": "@0.12.4+2",
-  "shelf_tag": "@0.6.2+1",
+  "shelf_tag": "@0.6.4+3",
   "smoke_rev" : "@f3361191cc2a85ebc1e4d4c33aec672d7915aba9",
   "source_maps_tag": "@0.10.1",
   "shelf_static_tag": "@0.2.3+1",
@@ -105,7 +92,7 @@
   "when_tag": "@0.2.0+2",
   "which_tag": "@0.1.3+1",
   "web_components_rev": "@0e636b534d9b12c9e96f841e6679398e91a986ec",
-  "WebCore_rev" : "@44061",
+  "WebCore_rev": "@4f90b41b0165f23f412cecdba07b7d81d3fbb5b5",
   "yaml_tag": "@2.1.5",
   "zlib_rev": "@c3d0a6190f2f8c924a05ab6cc97b8f975bddd33f",
   "barback-0.13.0_rev": "@34853",
@@ -146,20 +133,8 @@
       Var("chromium_git") + "/chromium/src/tools/idl_parser.git" +
       Var("idl_parser_rev"),
 
-  Var("dart_root") + "/third_party/7zip":
-     Var("third_party") + "/7zip" + Var("7zip_rev"),
-  Var("dart_root") + "/third_party/firefox_jsshell":
-      Var("third_party") + "/firefox_jsshell" + Var("firefox_jsshell_rev"),
-  Var("dart_root") + "/third_party/gsutil":
-      Var("third_party") + "/gsutil" + Var("gsutil_rev"),
-  Var("dart_root") + "/third_party/pkg/petitparser":
-      Var("third_party") + "/petitparser" + Var("petitparser_rev"),
   Var("dart_root") + "/third_party/WebCore":
-      Var("third_party") + "/WebCore" + Var("WebCore_rev"),
-
-  Var("dart_root") + "/third_party/dart-services":
-      (Var("github_mirror") % "dart-services") +
-      Var("dart_services_rev"),
+      "https://github.com/dart-lang/webcore.git" + Var("WebCore_rev"),
 
   Var("dart_root") + "/third_party/pkg/args":
       (Var("github_mirror") % "args") + Var("args_tag"),
@@ -179,6 +154,9 @@
       (Var("github_mirror") % "crypto") + Var("crypto_rev"),
   Var("dart_root") + "/third_party/pkg/csslib":
       (Var("github_mirror") % "csslib") + Var("csslib_tag"),
+  Var("dart_root") + "/third_party/dart-services":
+      (Var("github_mirror") % "dart-services") +
+      Var("dart_services_rev"),
   Var("dart_root") + "/third_party/pkg_tested/dart_style":
       (Var("github_mirror") % "dart_style") + Var("dart_style_tag"),
   Var("dart_root") + "/third_party/pkg/dart2js_info":
@@ -192,7 +170,7 @@
   Var("dart_root") + "/third_party/pkg/html":
       (Var("github_mirror") % "html") + Var("html_tag"),
   Var("dart_root") + "/third_party/pkg/http":
-      (Var("github_mirror") % "http") + Var("http_rev"),
+      (Var("github_mirror") % "http") + Var("http_tag"),
   Var("dart_root") + "/third_party/pkg/http_multi_server":
       (Var("github_mirror") % "http_multi_server") +
       Var("http_multi_server_tag"),
@@ -307,13 +285,6 @@
     Var("dart_root") + "/third_party/cygwin":
       Var("chromium_git") + "/chromium/deps/cygwin.git" +
       "@c89e446b273697fadf3a10ff1007a97c0b7de6df",
-    Var("dart_root") + "/third_party/drt_resources":
-      Var("chromium_url") +
-      "/trunk/src/webkit/tools/test_shell/resources@157099",
-  },
-  "unix": {
-    Var("dart_root") + "/third_party/clang":
-      Var("third_party") + "/clang" + Var("clang_rev"),
   },
 }
 
@@ -368,4 +339,92 @@
       Var('dart_root') + "/tools/sdks",
     ],
   },
+  {
+    "name": "firefox_jsshell",
+    "pattern": ".",
+    "action": [
+      "download_from_google_storage",
+      "--no_auth",
+      "--no_resume",
+      "--bucket",
+      "dart-dependencies",
+      "--recursive",
+      "--auto_platform",
+      "--extract",
+      "--directory",
+      Var('dart_root') + "/third_party/firefox_jsshell",
+    ],
+  },
+  {
+    "name": "drt_resources",
+    "pattern": ".",
+    "action": [
+      "download_from_google_storage",
+      "--no_auth",
+      "--no_resume",
+      "--bucket",
+      "dart-dependencies",
+      "--platform=win32",
+      "--directory",
+      Var('dart_root') + "/third_party/drt_resources",
+    ],
+  },
+  {
+    "name": "petitparser",
+    "pattern": ".",
+    "action": [
+      "download_from_google_storage",
+      "--no_auth",
+      "--no_resume",
+      "--bucket",
+      "dart-dependencies",
+      "--extract",
+      "-s",
+      Var('dart_root') + "/third_party/pkg/petitparser.tar.gz.sha1",
+    ],
+  },
+  {
+    "name": "7zip",
+    "pattern": ".",
+    "action": [
+      "download_from_google_storage",
+      "--no_auth",
+      "--no_resume",
+      "--bucket",
+      "dart-dependencies",
+      "--platform=win32",
+      "--extract",
+      "-s",
+      Var('dart_root') + "/third_party/7zip.tar.gz.sha1",
+    ],
+  },
+  {
+    "name": "gsutil",
+    "pattern": ".",
+    "action": [
+      "download_from_google_storage",
+      "--no_auth",
+      "--no_resume",
+      "--bucket",
+      "dart-dependencies",
+      "--extract",
+      "-s",
+      Var('dart_root') + "/third_party/gsutil.tar.gz.sha1",
+    ],
+  },
+  {
+    "name": "clang",
+    "pattern": ".",
+    "action": [
+      "download_from_google_storage",
+      "--no_auth",
+      "--no_resume",
+      "--bucket",
+      "dart-dependencies",
+      "--platform=linux*",
+      "--extract",
+      "-s",
+      Var('dart_root') + "/third_party/clang.tar.gz.sha1",
+    ],
+  },
 ]
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 653d509..8810ff6 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -9,18 +9,12 @@
 import 'package:analysis_server/plugin/protocol/protocol.dart';
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/constants.dart';
-import 'package:analysis_server/src/context_manager.dart';
-import 'package:analysis_server/src/provisional/completion/completion_core.dart'
-    show CompletionRequest, CompletionResult;
+import 'package:analysis_server/src/provisional/completion/completion_core.dart';
 import 'package:analysis_server/src/services/completion/completion_core.dart';
-import 'package:analysis_server/src/services/completion/completion_manager.dart';
-import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analysis_server/src/services/completion/completion_performance.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 
-export 'package:analysis_server/src/services/completion/completion_manager.dart'
-    show CompletionPerformance, CompletionRequest, OperationPerformance;
-
 /**
  * Instances of the class [CompletionDomainHandler] implement a [RequestHandler]
  * that handles requests in the search domain.
@@ -37,27 +31,11 @@
   final AnalysisServer server;
 
   /**
-   * The [SearchEngine] for this server.
-   */
-  SearchEngine searchEngine;
-
-  /**
    * The next completion response id.
    */
   int _nextCompletionId = 0;
 
   /**
-   * The completion manager for most recent [Source] and [AnalysisContext],
-   * or `null` if none.
-   */
-  CompletionManager _manager;
-
-  /**
-   * The subscription for the cached context's source change stream.
-   */
-  StreamSubscription<SourcesChangedEvent> _sourcesChangedSubscription;
-
-  /**
    * Code completion performance for the last completion operation.
    */
   CompletionPerformance performance;
@@ -77,60 +55,44 @@
   /**
    * Initialize a new request handler for the given [server].
    */
-  CompletionDomainHandler(this.server) {
-    server.onContextsChanged.listen(contextsChanged);
-    server.onPriorityChange.listen(priorityChanged);
-    searchEngine = server.searchEngine;
-  }
+  CompletionDomainHandler(this.server);
 
   /**
-   * Return the completion manager for most recent [Source] and [AnalysisContext],
-   * or `null` if none.
+   * Compute completion results for the given reqeust and append them to the stream.
+   * Clients should not call this method directly as it is automatically called
+   * when a client listens to the stream returned by [results].
+   * Subclasses should override this method, append at least one result
+   * to the [controller], and close the controller stream once complete.
    */
-  CompletionManager get manager => _manager;
+  Future<CompletionResult> computeSuggestions(
+      CompletionRequestImpl request) async {
+    Iterable<CompletionContributor> newContributors =
+        server.serverPlugin.completionContributors;
+    List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
 
-  /**
-   * Return the [CompletionManager] for the given [context] and [source],
-   * creating a new manager or returning an existing manager as necessary.
-   */
-  CompletionManager completionManagerFor(
-      AnalysisContext context, Source source) {
-    if (_manager != null) {
-      if (_manager.context == context && _manager.source == source) {
-        return _manager;
-      }
-      _discardManager();
-    }
-    _manager = createCompletionManager(server, context, source);
-    if (context != null) {
-      _sourcesChangedSubscription =
-          context.onSourcesChanged.listen(sourcesChanged);
-    }
-    return _manager;
-  }
+    const COMPUTE_SUGGESTIONS_TAG = 'computeSuggestions';
+    performance.logStartTime(COMPUTE_SUGGESTIONS_TAG);
 
-  /**
-   * If the context associated with the cache has changed or been removed
-   * then discard the cache.
-   */
-  void contextsChanged(ContextsChangedEvent event) {
-    if (_manager != null) {
-      AnalysisContext context = _manager.context;
-      if (event.changed.contains(context) || event.removed.contains(context)) {
-        _discardManager();
-      }
+    for (CompletionContributor contributor in newContributors) {
+      String contributorTag = 'computeSuggestions - ${contributor.runtimeType}';
+      performance.logStartTime(contributorTag);
+      suggestions.addAll(await contributor.computeSuggestions(request));
+      performance.logElapseTime(contributorTag);
     }
-  }
 
-  CompletionManager createCompletionManager(
-      AnalysisServer server, AnalysisContext context, Source source) {
-    return new CompletionManager.create(context, source, server.searchEngine,
-        server.serverPlugin.completionContributors);
+    performance.logElapseTime(COMPUTE_SUGGESTIONS_TAG);
+
+    // TODO (danrubel) if request is obsolete
+    // (processAnalysisRequest returns false)
+    // then send empty results
+
+    return new CompletionResult(
+        request.replacementOffset, request.replacementLength, suggestions);
   }
 
   @override
   Response handleRequest(Request request) {
-    if (searchEngine == null) {
+    if (server.searchEngine == null) {
       return new Response.noIndexGenerated(request);
     }
     return runZoned(() {
@@ -152,34 +114,9 @@
   }
 
   /**
-   * If the set the priority files has changed, then pre-cache completion
-   * information related to the first priority file.
-   */
-  void priorityChanged(PriorityChangeEvent event) {
-    Source source = event.firstSource;
-    CompletionPerformance performance = new CompletionPerformance();
-    computeCachePerformance = performance;
-    if (source == null) {
-      performance.complete('priorityChanged caching: no source');
-      return;
-    }
-    performance.source = source;
-    AnalysisContext context = server.getAnalysisContextForSource(source);
-    if (context != null) {
-      String computeTag = 'computeCache';
-      performance.logStartTime(computeTag);
-      CompletionManager manager = completionManagerFor(context, source);
-      manager.computeCache().catchError((_) => false).then((bool success) {
-        performance.logElapseTime(computeTag);
-        performance.complete('priorityChanged caching: $success');
-      });
-    }
-  }
-
-  /**
    * Process a `completion.getSuggestions` request.
    */
-  Response processRequest(Request request, [CompletionManager manager]) {
+  Response processRequest(Request request) {
     performance = new CompletionPerformance();
 
     // extract and validate params
@@ -200,32 +137,32 @@
           ' but found ${params.offset}');
     }
 
-    // schedule completion analysis
     recordRequest(performance, context, source, params.offset);
-    if (manager == null) {
-      manager = completionManagerFor(context, source);
-    }
-    CompletionRequest completionRequest = new CompletionRequestImpl(context,
-        server.resourceProvider, server.searchEngine, source, params.offset);
-    int notificationCount = 0;
+
+    CompletionRequest completionRequest = new CompletionRequestImpl(
+        context,
+        server.resourceProvider,
+        server.searchEngine,
+        source,
+        params.offset,
+        performance);
     String completionId = (_nextCompletionId++).toString();
-    manager.results(completionRequest).listen((CompletionResult result) {
-      ++notificationCount;
-      bool isLast = result is CompletionResultImpl ? result.isLast : true;
-      performance.logElapseTime("notification $notificationCount send", () {
-        sendCompletionNotification(completionId, result.replacementOffset,
-            result.replacementLength, result.suggestions, isLast);
-      });
-      if (notificationCount == 1) {
-        performance.logFirstNotificationComplete('notification 1 complete');
-        performance.suggestionCountFirst = result.suggestions.length;
-      }
-      if (isLast) {
-        performance.notificationCount = notificationCount;
-        performance.suggestionCountLast = result.suggestions.length;
-        performance.complete();
-      }
+
+    // Compute suggestions in the background
+    computeSuggestions(completionRequest).then((CompletionResult result) {
+      const SEND_NOTIFICATION_TAG = 'send notification';
+      performance.logStartTime(SEND_NOTIFICATION_TAG);
+      sendCompletionNotification(completionId, result.replacementOffset,
+          result.replacementLength, result.suggestions);
+      performance.logElapseTime(SEND_NOTIFICATION_TAG);
+
+      performance.notificationCount = 1;
+      performance.logFirstNotificationComplete('notification 1 complete');
+      performance.suggestionCountFirst = result.suggestions.length;
+      performance.suggestionCountLast = result.suggestions.length;
+      performance.complete();
     });
+
     // initial response without results
     return new CompletionGetSuggestionsResult(completionId)
         .toResponse(request.id);
@@ -255,51 +192,38 @@
   /**
    * Send completion notification results.
    */
-  void sendCompletionNotification(
-      String completionId,
-      int replacementOffset,
-      int replacementLength,
-      Iterable<CompletionSuggestion> results,
-      bool isLast) {
+  void sendCompletionNotification(String completionId, int replacementOffset,
+      int replacementLength, Iterable<CompletionSuggestion> results) {
     server.sendNotification(new CompletionResultsParams(
-            completionId, replacementOffset, replacementLength, results, isLast)
+            completionId, replacementOffset, replacementLength, results, true)
         .toNotification());
   }
+}
+
+/**
+ * The result of computing suggestions for code completion.
+ */
+class CompletionResult {
+  /**
+   * The length of the text to be replaced if the remainder of the identifier
+   * containing the cursor is to be replaced when the suggestion is applied
+   * (that is, the number of characters in the existing identifier).
+   */
+  final int replacementLength;
 
   /**
-   * Discard the cache if a source other than the source referenced by
-   * the cache changes or if any source is added, removed, or deleted.
+   * The offset of the start of the text to be replaced. This will be different
+   * than the offset used to request the completion suggestions if there was a
+   * portion of an identifier before the original offset. In particular, the
+   * replacementOffset will be the offset of the beginning of said identifier.
    */
-  void sourcesChanged(SourcesChangedEvent event) {
-    bool shouldDiscardManager(SourcesChangedEvent event) {
-      if (_manager == null) {
-        return false;
-      }
-      if (event.wereSourcesAdded || event.wereSourcesRemovedOrDeleted) {
-        return true;
-      }
-      var changedSources = event.changedSources;
-      return changedSources.length > 2 ||
-          (changedSources.length == 1 &&
-              !changedSources.contains(_manager.source));
-    }
-
-    if (shouldDiscardManager(event)) {
-      _discardManager();
-    }
-  }
+  final int replacementOffset;
 
   /**
-   * Discard the sourcesChanged subscription if any
+   * The suggested completions.
    */
-  void _discardManager() {
-    if (_sourcesChangedSubscription != null) {
-      _sourcesChangedSubscription.cancel();
-      _sourcesChangedSubscription = null;
-    }
-    if (_manager != null) {
-      _manager.dispose();
-      _manager = null;
-    }
-  }
+  final List<CompletionSuggestion> suggestions;
+
+  CompletionResult(
+      this.replacementOffset, this.replacementLength, this.suggestions);
 }
diff --git a/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart b/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
index bdebfcc..9a585dd 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
@@ -71,34 +71,3 @@
    */
   Source get source;
 }
-
-/**
- * The result of computing suggestions for code completion.
- *
- * Clients may implement this class when implementing plugins.
- */
-abstract class CompletionResult {
-  /**
-   * Return the length of the text to be replaced. This will be zero (0) if the
-   * suggestion is to be inserted, otherwise it will be greater than zero. For
-   * example, if the remainder of the identifier containing the cursor is to be
-   * replaced when the suggestion is applied, in which case the length will be
-   * the number of characters in the existing identifier.
-   */
-  int get replacementLength;
-
-  /**
-   * Return the offset of the start of the text to be replaced. This will be
-   * different than the offset used to request the completion suggestions if
-   * there was a portion of text that needs to be replaced. For example, if a
-   * partial identifier is immediately before the original offset, in which case
-   * the replacementOffset will be the offset of the beginning of the
-   * identifier.
-   */
-  int get replacementOffset;
-
-  /**
-   * Return the list of suggestions being contributed by the contributor.
-   */
-  List<CompletionSuggestion> get suggestions;
-}
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_core.dart b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
index 7048a6e..e0635aa 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
@@ -5,6 +5,7 @@
 library analysis_server.src.services.completion.completion_core;
 
 import 'package:analysis_server/src/provisional/completion/completion_core.dart';
+import 'package:analysis_server/src/services/completion/completion_performance.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -25,9 +26,9 @@
 
   /**
    * The offset of the start of the text to be replaced.
-   * This will be different than the offset used to request the completion
+   * This will be different than the [offset] used to request the completion
    * suggestions if there was a portion of an identifier before the original
-   * offset. In particular, the replacementOffset will be the offset of the
+   * [offset]. In particular, the [replacementOffset] will be the offset of the
    * beginning of said identifier.
    */
   int replacementOffset;
@@ -36,6 +37,8 @@
    * The length of the text to be replaced if the remainder of the identifier
    * containing the cursor is to be replaced when the suggestion is applied
    * (that is, the number of characters in the existing identifier).
+   * This will be different than the [replacementOffset] - [offset]
+   * if the [offset] is in the middle of an existing identifier.
    */
   int replacementLength;
 
@@ -45,11 +48,13 @@
   @override
   final SearchEngine searchEngine;
 
+  final CompletionPerformance performance;
+
   /**
    * Initialize a newly created completion request based on the given arguments.
    */
   CompletionRequestImpl(this.context, this.resourceProvider, this.searchEngine,
-      this.source, this.offset) {
+      this.source, this.offset, this.performance) {
     replacementOffset = offset;
     replacementLength = 0;
   }
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/completion_manager.dart
deleted file mode 100644
index 5cb8bab..0000000
--- a/pkg/analysis_server/lib/src/services/completion/completion_manager.dart
+++ /dev/null
@@ -1,262 +0,0 @@
-// 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.
-
-library services.completion.manager;
-
-import 'dart:async';
-
-import 'package:analysis_server/plugin/protocol/protocol.dart';
-import 'package:analysis_server/src/provisional/completion/completion_core.dart'
-    show CompletionContributor, CompletionContributorFactory, CompletionRequest, CompletionResult;
-import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
-import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-
-/**
- * Manages completion contributors for a given completion request.
- */
-abstract class CompletionManager {
-  /**
-   * The context in which the completion was computed.
-   */
-  final AnalysisContext context;
-
-  /**
-   * The source in which the completion was computed.
-   */
-  final Source source;
-
-  /**
-   * The controller used for returning completion results.
-   */
-  StreamController<CompletionResult> controller;
-
-  CompletionManager(this.context, this.source);
-
-  /**
-   * Create a manager for the given request.
-   */
-  factory CompletionManager.create(
-      AnalysisContext context,
-      Source source,
-      SearchEngine searchEngine,
-      Iterable<CompletionContributor> newContributors) {
-    if (context != null) {
-      if (AnalysisEngine.isDartFileName(source.shortName)) {
-        return new DartCompletionManager.create(
-            context, searchEngine, source, newContributors);
-      }
-    }
-    return new NoOpCompletionManager(source);
-  }
-
-  /**
-   * Compute and cache information in preparation for a possible code
-   * completion request sometime in the future. The default implementation
-   * of this method does nothing. Subclasses may override but should not
-   * count on this method being called before [computeSuggestions].
-   * Return a future that completes when the cache is computed with a bool
-   * indicating success.
-   */
-  Future<bool> computeCache() {
-    return new Future.value(true);
-  }
-
-  /**
-   * Compute completion results for the given reqeust and append them to the stream.
-   * Clients should not call this method directly as it is automatically called
-   * when a client listens to the stream returned by [results].
-   * Subclasses should override this method, append at least one result
-   * to the [controller], and close the controller stream once complete.
-   */
-  void computeSuggestions(CompletionRequest request);
-
-  /**
-   * Discard any pending operations.
-   * Subclasses may override but should call super.dispose
-   */
-  void dispose() {}
-
-  /**
-   * Generate a stream of code completion results.
-   */
-  Stream<CompletionResult> results(CompletionRequest request) {
-    controller = new StreamController<CompletionResult>(onListen: () {
-      scheduleMicrotask(() {
-        computeSuggestions(request);
-      });
-    });
-    return controller.stream;
-  }
-}
-
-/**
- * Overall performance of a code completion operation.
- */
-class CompletionPerformance {
-  final DateTime start = new DateTime.now();
-  final Map<String, Duration> _startTimes = new Map<String, Duration>();
-  final Stopwatch _stopwatch = new Stopwatch();
-  final List<OperationPerformance> operations = <OperationPerformance>[];
-
-  Source source;
-  String snippet = '';
-  int notificationCount = -1;
-  int suggestionCountFirst = -1;
-  int suggestionCountLast = -1;
-  Duration _firstNotification;
-
-  CompletionPerformance() {
-    _stopwatch.start();
-  }
-
-  int get elapsedInMilliseconds =>
-      operations.length > 0 ? operations.last.elapsed.inMilliseconds : 0;
-
-  int get firstNotificationInMilliseconds =>
-      _firstNotification != null ? _firstNotification.inMilliseconds : 0;
-
-  String get startTimeAndMs => '${start.millisecondsSinceEpoch} - $start';
-
-  String get suggestionCount {
-    if (notificationCount < 1) return '';
-    if (notificationCount == 1) return '$suggestionCountFirst';
-    return '$suggestionCountFirst,  $suggestionCountLast';
-  }
-
-  void complete([String tag = null]) {
-    _stopwatch.stop();
-    _logDuration(tag != null ? tag : 'total time', _stopwatch.elapsed);
-  }
-
-  logElapseTime(String tag, [f() = null]) {
-    Duration start;
-    Duration end = _stopwatch.elapsed;
-    var result;
-    if (f == null) {
-      start = _startTimes[tag];
-      if (start == null) {
-        _logDuration(tag, null);
-        return null;
-      }
-    } else {
-      result = f();
-      start = end;
-      end = _stopwatch.elapsed;
-    }
-    _logDuration(tag, end - start);
-    return result;
-  }
-
-  void logFirstNotificationComplete(String tag) {
-    _firstNotification = _stopwatch.elapsed;
-    _logDuration(tag, _firstNotification);
-  }
-
-  void logStartTime(String tag) {
-    _startTimes[tag] = _stopwatch.elapsed;
-  }
-
-  void setContentsAndOffset(String contents, int offset) {
-    snippet = _computeSnippet(contents, offset);
-  }
-
-  void _logDuration(String tag, Duration elapsed) {
-    operations.add(new OperationPerformance(tag, elapsed));
-  }
-
-  static String _computeSnippet(String contents, int offset) {
-    if (contents == null ||
-        offset == null ||
-        offset < 0 ||
-        contents.length < offset) {
-      return '???';
-    }
-    int start = offset;
-    while (start > 0) {
-      String ch = contents[start - 1];
-      if (ch == '\r' || ch == '\n') {
-        break;
-      }
-      --start;
-    }
-    int end = offset;
-    while (end < contents.length) {
-      String ch = contents[end];
-      if (ch == '\r' || ch == '\n') {
-        break;
-      }
-      ++end;
-    }
-    String prefix = contents.substring(start, offset);
-    String suffix = contents.substring(offset, end);
-    return '$prefix^$suffix';
-  }
-}
-
-/**
- * Code completion result generated by an [CompletionManager].
- */
-class CompletionResultImpl implements CompletionResult {
-  /**
-   * The length of the text to be replaced if the remainder of the identifier
-   * containing the cursor is to be replaced when the suggestion is applied
-   * (that is, the number of characters in the existing identifier).
-   */
-  final int replacementLength;
-
-  /**
-   * The offset of the start of the text to be replaced. This will be different
-   * than the offset used to request the completion suggestions if there was a
-   * portion of an identifier before the original offset. In particular, the
-   * replacementOffset will be the offset of the beginning of said identifier.
-   */
-  final int replacementOffset;
-
-  /**
-   * The suggested completions.
-   */
-  final List<CompletionSuggestion> suggestions;
-
-  /**
-   * `true` if this is that last set of results that will be returned
-   * for the indicated completion.
-   */
-  final bool last;
-
-  CompletionResultImpl(this.replacementOffset, this.replacementLength,
-      this.suggestions, this.last);
-
-  /**
-   * Return `true` if this is the last completion result that will be produced.
-   */
-  bool get isLast => last;
-}
-
-class NoOpCompletionManager extends CompletionManager {
-  NoOpCompletionManager(Source source) : super(null, source);
-
-  @override
-  void computeSuggestions(CompletionRequest request) {
-    controller.add(new CompletionResultImpl(request.offset, 0, [], true));
-  }
-}
-
-/**
- * The performance of an operation when computing code completion.
- */
-class OperationPerformance {
-  /**
-   * The name of the operation
-   */
-  final String name;
-
-  /**
-   * The elapse time or `null` if undefined.
-   */
-  final Duration elapsed;
-
-  OperationPerformance(this.name, this.elapsed);
-}
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_performance.dart b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
new file mode 100644
index 0000000..0272fb8
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
@@ -0,0 +1,119 @@
+// 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.
+
+library services.completion.manager;
+
+import 'package:analyzer/src/generated/source.dart';
+
+/**
+ * Overall performance of a code completion operation.
+ */
+class CompletionPerformance {
+  final DateTime start = new DateTime.now();
+  final Map<String, Duration> _startTimes = new Map<String, Duration>();
+  final Stopwatch _stopwatch = new Stopwatch();
+  final List<OperationPerformance> operations = <OperationPerformance>[];
+
+  Source source;
+  String snippet = '';
+  int notificationCount = -1;
+  int suggestionCountFirst = -1;
+  int suggestionCountLast = -1;
+  Duration _firstNotification;
+
+  CompletionPerformance() {
+    _stopwatch.start();
+  }
+
+  int get elapsedInMilliseconds =>
+      operations.length > 0 ? operations.last.elapsed.inMilliseconds : 0;
+
+  int get firstNotificationInMilliseconds =>
+      _firstNotification != null ? _firstNotification.inMilliseconds : 0;
+
+  String get startTimeAndMs => '${start.millisecondsSinceEpoch} - $start';
+
+  String get suggestionCount {
+    if (notificationCount < 1) return '';
+    if (notificationCount == 1) return '$suggestionCountFirst';
+    return '$suggestionCountFirst,  $suggestionCountLast';
+  }
+
+  void complete([String tag = null]) {
+    _stopwatch.stop();
+    _logDuration(tag != null ? tag : 'total time', _stopwatch.elapsed);
+  }
+
+  void logElapseTime(String tag) {
+    Duration end = _stopwatch.elapsed;
+    Duration start = _startTimes[tag];
+    if (start == null) {
+      _logDuration(tag, null);
+      return null;
+    }
+    _logDuration(tag, end - start);
+  }
+
+  void logFirstNotificationComplete(String tag) {
+    _firstNotification = _stopwatch.elapsed;
+    _logDuration(tag, _firstNotification);
+  }
+
+  void logStartTime(String tag) {
+    _startTimes[tag] = _stopwatch.elapsed;
+  }
+
+  void setContentsAndOffset(String contents, int offset) {
+    snippet = _computeSnippet(contents, offset);
+  }
+
+  void _logDuration(String tag, Duration elapsed) {
+    operations.add(new OperationPerformance(tag, elapsed));
+  }
+
+  static String _computeSnippet(String contents, int offset) {
+    if (contents == null ||
+        offset == null ||
+        offset < 0 ||
+        contents.length < offset) {
+      return '???';
+    }
+    int start = offset;
+    while (start > 0) {
+      String ch = contents[start - 1];
+      if (ch == '\r' || ch == '\n') {
+        break;
+      }
+      --start;
+    }
+    int end = offset;
+    while (end < contents.length) {
+      String ch = contents[end];
+      if (ch == '\r' || ch == '\n') {
+        break;
+      }
+      ++end;
+    }
+    String prefix = contents.substring(start, offset);
+    String suffix = contents.substring(offset, end);
+    return '$prefix^$suffix';
+  }
+}
+
+/**
+ * The performance of an operation when computing code completion.
+ */
+class OperationPerformance {
+  /**
+   * The name of the operation
+   */
+  final String name;
+
+  /**
+   * The elapse time or `null` if undefined.
+   */
+  final Duration elapsed;
+
+  OperationPerformance(this.name, this.elapsed);
+}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index 2289a92..cfe0ca7 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -13,7 +13,10 @@
 import 'package:analysis_server/src/provisional/completion/dart/completion_plugin.dart';
 import 'package:analysis_server/src/provisional/completion/dart/completion_target.dart';
 import 'package:analysis_server/src/services/completion/completion_core.dart';
-import 'package:analysis_server/src/services/completion/optype.dart';
+import 'package:analysis_server/src/services/completion/completion_performance.dart';
+import 'package:analysis_server/src/services/completion/dart/common_usage_sorter.dart';
+import 'package:analysis_server/src/services/completion/dart/contribution_sorter.dart';
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -22,12 +25,10 @@
     show AnalysisFutureHelper, AnalysisContextImpl;
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart' hide AnalysisContextImpl;
+import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/task/dart.dart';
-import 'package:analyzer/src/generated/scanner.dart';
-import 'package:analysis_server/src/services/completion/dart/contribution_sorter.dart';
-import 'package:analysis_server/src/services/completion/dart/common_usage_sorter.dart';
 
 /**
  * [DartCompletionManager] determines if a completion request is Dart specific
@@ -47,26 +48,36 @@
       return EMPTY_LIST;
     }
 
+    CompletionPerformance performance =
+        (request as CompletionRequestImpl).performance;
+    const BUILD_REQUEST_TAG = 'build DartCompletionRequestImpl';
+    performance.logStartTime(BUILD_REQUEST_TAG);
     DartCompletionRequestImpl dartRequest =
         await DartCompletionRequestImpl.from(request);
-    ReplacementRange range =
-        new ReplacementRange.compute(dartRequest.offset, dartRequest.target);
-    (request as CompletionRequestImpl)
-      ..replacementOffset = range.offset
-      ..replacementLength = range.length;
+    performance.logElapseTime(BUILD_REQUEST_TAG);
 
     // Don't suggest in comments.
     if (dartRequest.target.isCommentText) {
       return EMPTY_LIST;
     }
 
+    ReplacementRange range =
+        new ReplacementRange.compute(dartRequest.offset, dartRequest.target);
+    (request as CompletionRequestImpl)
+      ..replacementOffset = range.offset
+      ..replacementLength = range.length;
+
     // Request Dart specific completions from each contributor
     Map<String, CompletionSuggestion> suggestionMap =
         <String, CompletionSuggestion>{};
     for (DartCompletionContributor contributor
         in dartCompletionPlugin.contributors) {
+      String contributorTag =
+          'DartCompletionManager - ${contributor.runtimeType}';
+      performance.logStartTime(contributorTag);
       List<CompletionSuggestion> contributorSuggestions =
           await contributor.computeSuggestions(dartRequest);
+      performance.logElapseTime(contributorTag);
 
       for (CompletionSuggestion newSuggestion in contributorSuggestions) {
         var oldSuggestion = suggestionMap.putIfAbsent(
@@ -80,7 +91,10 @@
 
     // Adjust suggestion relevance before returning
     List<CompletionSuggestion> suggestions = suggestionMap.values.toList();
+    const SORT_TAG = 'DartCompletionManager - sort';
+    performance.logStartTime(SORT_TAG);
     await contributionSorter.sort(dartRequest, suggestions);
+    performance.logElapseTime(SORT_TAG);
     return suggestions;
   }
 }
@@ -88,8 +102,31 @@
 /**
  * The information about a requested list of completions within a Dart file.
  */
-class DartCompletionRequestImpl extends CompletionRequestImpl
-    implements DartCompletionRequest {
+class DartCompletionRequestImpl implements DartCompletionRequest {
+  @override
+  final AnalysisContext context;
+
+  @override
+  final Source source;
+
+  @override
+  final int offset;
+
+  @override
+  Expression dotTarget;
+
+  @override
+  Source librarySource;
+
+  @override
+  final ResourceProvider resourceProvider;
+
+  @override
+  final SearchEngine searchEngine;
+
+  @override
+  CompletionTarget target;
+
   /**
    * The [LibraryElement] representing dart:core
    */
@@ -100,26 +137,19 @@
    */
   InterfaceType _objectType;
 
-  @override
-  Expression dotTarget;
-
-  @override
-  Source librarySource;
-
   OpType _opType;
 
-  @override
-  CompletionTarget target;
+  final CompletionPerformance performance;
 
   DartCompletionRequestImpl._(
-      AnalysisContext context,
-      ResourceProvider resourceProvider,
-      SearchEngine searchEngine,
+      this.context,
+      this.resourceProvider,
+      this.searchEngine,
       this.librarySource,
-      Source source,
-      int offset,
-      CompilationUnit unit)
-      : super(context, resourceProvider, searchEngine, source, offset) {
+      this.source,
+      this.offset,
+      CompilationUnit unit,
+      this.performance) {
     _updateTargets(unit);
   }
 
@@ -178,11 +208,14 @@
       libUnit = target.unit;
     } else if (librarySource != null) {
       // TODO(danrubel) only resolve the directives
+      const RESOLVE_DIRECTIVES_TAG = 'resolve directives';
+      performance.logStartTime(RESOLVE_DIRECTIVES_TAG);
       libUnit = await new AnalysisFutureHelper<CompilationUnit>(
               context,
               new LibrarySpecificUnit(librarySource, librarySource),
               RESOLVED_UNIT3)
           .computeAsync();
+      performance.logElapseTime(RESOLVE_DIRECTIVES_TAG);
     }
     return libUnit?.directives;
   }
@@ -202,10 +235,13 @@
     // Resolve declarations in the target unit
     // TODO(danrubel) resolve the expression or containing method
     // rather than the entire complilation unit
+    const RESOLVE_EXPRESSION_TAG = 'resolve expression';
+    performance.logStartTime(RESOLVE_EXPRESSION_TAG);
     CompilationUnit resolvedUnit =
         await new AnalysisFutureHelper<CompilationUnit>(context,
                 new LibrarySpecificUnit(librarySource, source), RESOLVED_UNIT)
             .computeAsync();
+    performance.logElapseTime(RESOLVE_EXPRESSION_TAG);
 
     // TODO(danrubel) determine if the underlying source has been modified
     // in a way that invalidates the completion request
@@ -254,9 +290,18 @@
    * based on the given [request].
    */
   static Future<DartCompletionRequest> from(CompletionRequest request) async {
+    CompletionPerformance performance =
+        (request as CompletionRequestImpl).performance;
+    const BUILD_REQUEST_TAG = 'build DartCompletionRequest';
+    performance.logStartTime(BUILD_REQUEST_TAG);
+
     Source source = request.source;
     AnalysisContext context = request.context;
+
+    const PARSE_TAG = 'parse unit';
+    performance.logStartTime(PARSE_TAG);
     CompilationUnit unit = request.context.computeResult(source, PARSED_UNIT);
+    performance.logElapseTime(PARSE_TAG);
 
     Source libSource;
     if (unit.directives.any((d) => d is PartOfDirective)) {
@@ -270,9 +315,12 @@
 
     // Most (all?) contributors need declarations in scope to be resolved
     if (libSource != null) {
+      const RESOLVE_DECLARATIONS_TAG = 'resolve declarations';
+      performance.logStartTime(RESOLVE_DECLARATIONS_TAG);
       unit = await new AnalysisFutureHelper<CompilationUnit>(context,
               new LibrarySpecificUnit(libSource, source), RESOLVED_UNIT3)
           .computeAsync();
+      performance.logElapseTime(RESOLVE_DECLARATIONS_TAG);
     }
 
     DartCompletionRequestImpl dartRequest = new DartCompletionRequestImpl._(
@@ -282,7 +330,8 @@
         libSource,
         request.source,
         request.offset,
-        unit);
+        unit,
+        performance);
 
     // Resolve the expression in which the completion occurs
     // to properly determine if identifiers should be suggested
@@ -290,10 +339,14 @@
     if (dartRequest.target.maybeFunctionalArgument()) {
       AstNode node = dartRequest.target.containingNode.parent;
       if (node is Expression) {
+        const FUNCTIONAL_ARG_TAG = 'resolve expression for isFunctionalArg';
+        performance.logStartTime(FUNCTIONAL_ARG_TAG);
         await dartRequest.resolveExpression(node);
+        performance.logElapseTime(FUNCTIONAL_ARG_TAG);
       }
     }
 
+    performance.logElapseTime(BUILD_REQUEST_TAG);
     return dartRequest;
   }
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
index e25dc18..736f2a0 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
@@ -9,7 +9,7 @@
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/dart/local_library_contributor.dart';
-import 'package:analysis_server/src/services/completion/optype.dart';
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
 
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
index 40f0af7..bf1633e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
@@ -9,8 +9,8 @@
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/provisional/completion/dart/completion_target.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
-import 'package:analysis_server/src/services/completion/optype.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
 
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
index 296f03b..014d4ee 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
@@ -13,7 +13,7 @@
     show DartCompletionRequestImpl;
 import 'package:analysis_server/src/services/completion/dart/local_declaration_visitor.dart'
     show LocalDeclarationVisitor;
-import 'package:analysis_server/src/services/completion/optype.dart';
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
index 9b4bca9..d8d4e36 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
@@ -13,8 +13,8 @@
     show DartCompletionRequestImpl;
 import 'package:analysis_server/src/services/completion/dart/local_declaration_visitor.dart'
     show LocalDeclarationVisitor;
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
-import 'package:analysis_server/src/services/completion/optype.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/scanner.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
index 02878a0..9469154 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
@@ -8,9 +8,9 @@
 
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart'
     show createSuggestion, ElementSuggestionBuilder;
-import 'package:analysis_server/src/services/completion/optype.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
 
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
index 4fb7c97..966f1d9 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
@@ -13,7 +13,7 @@
     show DartCompletionRequestImpl;
 import 'package:analysis_server/src/services/completion/dart/local_declaration_visitor.dart'
     show LocalDeclarationVisitor;
-import 'package:analysis_server/src/services/completion/optype.dart';
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
 import 'package:analysis_server/src/services/correction/strings.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/scanner.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/optype.dart b/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
similarity index 100%
rename from pkg/analysis_server/lib/src/services/completion/optype.dart
rename to pkg/analysis_server/lib/src/services/completion/dart/optype.dart
diff --git a/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
deleted file mode 100644
index 92bd9b0..0000000
--- a/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
+++ /dev/null
@@ -1,200 +0,0 @@
-// 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.
-
-library services.completion.dart;
-
-import 'dart:async';
-
-import 'package:analysis_server/plugin/protocol/protocol.dart';
-import 'package:analysis_server/src/provisional/completion/completion_core.dart'
-    show AnalysisRequest, CompletionContributor, CompletionRequest;
-import 'package:analysis_server/src/services/completion/completion_core.dart';
-import 'package:analysis_server/src/services/completion/completion_manager.dart';
-import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-
-/**
- * The base class for contributing code completion suggestions.
- */
-abstract class DartCompletionContributor {
-  /**
-   * Computes the initial set of [CompletionSuggestion]s based on
-   * the given completion context. The compilation unit and completion node
-   * in the given completion context may not be resolved.
-   * This method should execute quickly and not block waiting for any analysis.
-   * Returns `true` if the contributor's work is complete
-   * or `false` if [computeFull] should be called to complete the work.
-   */
-  bool computeFast(DartCompletionRequest request);
-
-  /**
-   * Computes the complete set of [CompletionSuggestion]s based on
-   * the given completion context.  The compilation unit and completion node
-   * in the given completion context are resolved.
-   * Returns `true` if the receiver modified the list of suggestions.
-   */
-  Future<bool> computeFull(DartCompletionRequest request);
-}
-
-/**
- * Manages code completion for a given Dart file completion request.
- */
-class DartCompletionManager extends CompletionManager {
-  final SearchEngine searchEngine;
-  Iterable<CompletionContributor> newContributors;
-
-  DartCompletionManager(
-      AnalysisContext context, this.searchEngine, Source source,
-      [this.newContributors])
-      : super(context, source) {
-    if (newContributors == null) {
-      newContributors = <CompletionContributor>[];
-    }
-  }
-
-  /**
-   * Create a new initialized Dart source completion manager
-   */
-  factory DartCompletionManager.create(
-      AnalysisContext context,
-      SearchEngine searchEngine,
-      Source source,
-      Iterable<CompletionContributor> newContributors) {
-    return new DartCompletionManager(
-        context, searchEngine, source, newContributors);
-  }
-
-  /**
-   * Compute suggestions based upon cached information only
-   * then send an initial response to the client.
-   * Return a list of contributors for which [computeFull] should be called
-   */
-  List<DartCompletionContributor> computeFast(
-      DartCompletionRequest request, CompletionPerformance performance) {
-    return [];
-  }
-
-  /**
-   * If there is remaining work to be done, then wait for the unit to be
-   * resolved and request that each remaining contributor finish their work.
-   * Return a [Future] that completes when the last notification has been sent.
-   */
-  Future computeFull(
-      DartCompletionRequest request,
-      CompletionPerformance performance,
-      List<DartCompletionContributor> todo) async {
-    // Compute suggestions using the new API
-    performance.logStartTime('computeSuggestions');
-    for (CompletionContributor contributor in newContributors) {
-      String contributorTag = 'computeSuggestions - ${contributor.runtimeType}';
-      performance.logStartTime(contributorTag);
-      List<CompletionSuggestion> newSuggestions =
-          await contributor.computeSuggestions(request);
-      for (CompletionSuggestion suggestion in newSuggestions) {
-        request.addSuggestion(suggestion);
-      }
-      performance.logElapseTime(contributorTag);
-    }
-    performance.logElapseTime('computeSuggestions');
-    performance.logStartTime('waitForAnalysis');
-
-    // TODO (danrubel) if request is obsolete
-    // (processAnalysisRequest returns false)
-    // then send empty results
-    sendResults(request, true);
-    return new Future.value();
-  }
-
-  @override
-  void computeSuggestions(CompletionRequest completionRequest) {
-    DartCompletionRequest request =
-        new DartCompletionRequest.from(completionRequest);
-    CompletionPerformance performance = new CompletionPerformance();
-    performance.logElapseTime('compute', () {
-      List<DartCompletionContributor> todo = computeFast(request, performance);
-      computeFull(request, performance, todo);
-    });
-  }
-
-  /**
-   * Send the current list of suggestions to the client.
-   */
-  void sendResults(DartCompletionRequest request, bool last) {
-    if (controller == null || controller.isClosed) {
-      return;
-    }
-    controller.add(new CompletionResultImpl(request.replacementOffset,
-        request.replacementLength, request.suggestions, last));
-    if (last) {
-      controller.close();
-    }
-  }
-
-  /**
-   * Return a future that either (a) completes with the resolved compilation
-   * unit when analysis is complete, or (b) completes with null if the
-   * compilation unit is never going to be resolved.
-   */
-  Future<CompilationUnit> waitForAnalysis() {
-    List<Source> libraries = context.getLibrariesContaining(source);
-    assert(libraries != null);
-    if (libraries.length == 0) {
-      return new Future.value(null);
-    }
-    Source libSource = libraries[0];
-    assert(libSource != null);
-    return context
-        .computeResolvedCompilationUnitAsync(source, libSource)
-        .catchError((_) {
-      // This source file is not scheduled for analysis, so a resolved
-      // compilation unit is never going to get computed.
-      return null;
-    }, test: (e) => e is AnalysisNotScheduledError);
-  }
-}
-
-/**
- * The context in which the completion is requested.
- */
-class DartCompletionRequest extends CompletionRequestImpl {
-  /**
-   * The list of suggestions to be sent to the client.
-   */
-  final List<CompletionSuggestion> _suggestions = <CompletionSuggestion>[];
-
-  /**
-   * The set of completions used to prevent duplicates
-   */
-  final Set<String> _completions = new Set<String>();
-
-  DartCompletionRequest(
-      AnalysisContext context,
-      ResourceProvider resourceProvider,
-      SearchEngine searchEngine,
-      Source source,
-      int offset)
-      : super(context, resourceProvider, searchEngine, source, offset);
-
-  factory DartCompletionRequest.from(CompletionRequestImpl request) =>
-      new DartCompletionRequest(request.context, request.resourceProvider,
-          request.searchEngine, request.source, request.offset);
-
-  /**
-   * The list of suggestions to be sent to the client.
-   */
-  Iterable<CompletionSuggestion> get suggestions => _suggestions;
-
-  /**
-   * Add the given suggestion to the list that is returned to the client as long
-   * as a suggestion with an identical completion has not already been added.
-   */
-  void addSuggestion(CompletionSuggestion suggestion) {
-    if (_completions.add(suggestion.completion)) {
-      _suggestions.add(suggestion);
-    }
-  }
-}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index a9c4918..7525b74f 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -169,6 +169,8 @@
       const FixKind('MAKE_CLASS_ABSTRACT', 50, "Make class '{0}' abstract");
   static const REMOVE_DEAD_CODE =
       const FixKind('REMOVE_DEAD_CODE', 50, "Remove dead code");
+  static const MAKE_FIELD_NOT_FINAL =
+      const FixKind('MAKE_FIELD_NOT_FINAL', 50, "Make field '{0}' not final");
   static const REMOVE_PARAMETERS_IN_GETTER_DECLARATION = const FixKind(
       'REMOVE_PARAMETERS_IN_GETTER_DECLARATION',
       50,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 50d437c..fa16435 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -230,6 +230,9 @@
     if (errorCode == ParserErrorCode.VAR_AS_TYPE_NAME) {
       _addFix_replaceVarWithDynamic();
     }
+    if (errorCode == StaticWarningCode.ASSIGNMENT_TO_FINAL) {
+      _addFix_makeFieldNotFinal();
+    }
     if (errorCode == StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER) {
       _addFix_makeEnclosingClassAbstract();
     }
@@ -1590,6 +1593,41 @@
     _addFix(DartFixKind.MAKE_CLASS_ABSTRACT, [className]);
   }
 
+  void _addFix_makeFieldNotFinal() {
+    AstNode node = this.node;
+    if (node is SimpleIdentifier &&
+        node.bestElement is PropertyAccessorElement) {
+      PropertyAccessorElement getter = node.bestElement;
+      if (getter.isGetter &&
+          getter.isSynthetic &&
+          !getter.variable.isSynthetic &&
+          getter.variable.setter == null &&
+          getter.enclosingElement is ClassElement) {
+        AstNode variable = getter.variable.computeNode();
+        if (variable is VariableDeclaration &&
+            variable.parent is VariableDeclarationList &&
+            variable.parent.parent is FieldDeclaration) {
+          VariableDeclarationList declarationList = variable.parent;
+          Token keywordToken = declarationList.keyword;
+          if (declarationList.variables.length == 1 &&
+              keywordToken is KeywordToken &&
+              keywordToken.keyword == Keyword.FINAL) {
+            if (declarationList.type != null) {
+              SourceRange range =
+                  rf.rangeStartStart(keywordToken, declarationList.type);
+              _addRemoveEdit(range);
+            } else {
+              SourceRange range = rf.rangeStartStart(keywordToken, variable);
+              _addReplaceEdit(range, 'var ');
+            }
+            String fieldName = getter.variable.displayName;
+            _addFix(DartFixKind.MAKE_FIELD_NOT_FINAL, [fieldName]);
+          }
+        }
+      }
+    }
+  }
+
   void _addFix_nonBoolCondition_addNotNull() {
     _addInsertEdit(error.offset + error.length, ' != null');
     _addFix(DartFixKind.ADD_NE_NULL, []);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
index ca90fd2..a17bfda 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
@@ -230,10 +230,30 @@
         new NodeLocator(selectionRange.offset, selectionRange.end)
             .searchWithin(unit);
     // compute covering expressions
-    for (AstNode node = coveringNode;
-        node is Expression || node is ArgumentList;
-        node = node.parent) {
+    for (AstNode node = coveringNode; node != null; node = node.parent) {
       AstNode parent = node.parent;
+      // skip some nodes
+      if (node is ArgumentList ||
+          node is AssignmentExpression ||
+          node is NamedExpression ||
+          node is TypeArgumentList) {
+        continue;
+      }
+      if (node is ConstructorName || node is Label || node is TypeName) {
+        rootExpression = null;
+        coveringExpressionOffsets.clear();
+        coveringExpressionLengths.clear();
+        continue;
+      }
+      // cannot extract the name part of a property access
+      if (parent is PrefixedIdentifier && parent.identifier == node ||
+          parent is PropertyAccess && parent.propertyName == node) {
+        continue;
+      }
+      // stop if not an Expression
+      if (node is! Expression) {
+        break;
+      }
       // stop at void method invocations
       if (node is MethodInvocation) {
         MethodInvocation invocation = node;
@@ -249,19 +269,6 @@
           break;
         }
       }
-      // skip ArgumentList
-      if (node is ArgumentList) {
-        continue;
-      }
-      // skip AssignmentExpression
-      if (node is AssignmentExpression) {
-        continue;
-      }
-      // cannot extract the name part of a property access
-      if (parent is PrefixedIdentifier && parent.identifier == node ||
-          parent is PropertyAccess && parent.propertyName == node) {
-        continue;
-      }
       // fatal selection problems
       if (coveringExpressionOffsets.isEmpty) {
         if (node is SimpleIdentifier) {
diff --git a/pkg/analysis_server/lib/src/status/get_handler.dart b/pkg/analysis_server/lib/src/status/get_handler.dart
index 360ad0d..0f4fc15 100644
--- a/pkg/analysis_server/lib/src/status/get_handler.dart
+++ b/pkg/analysis_server/lib/src/status/get_handler.dart
@@ -18,6 +18,7 @@
 import 'package:analysis_server/src/operation/operation.dart';
 import 'package:analysis_server/src/operation/operation_analysis.dart';
 import 'package:analysis_server/src/operation/operation_queue.dart';
+import 'package:analysis_server/src/services/completion/completion_performance.dart';
 import 'package:analysis_server/src/services/index/index.dart';
 import 'package:analysis_server/src/services/index/local_index.dart';
 import 'package:analysis_server/src/services/index/store/split_store.dart';
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index e9a1663..14d9fd6 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -337,7 +337,7 @@
     channel.notificationsReceived.clear();
     server.updateContent(
         '0', {bar.path: new AddContentOverlay('library bar; void f() {}')});
-    await pumpEventQueue(500);
+    await pumpEventQueue(1000);
     expect(server.statusAnalyzing, isFalse);
     expect(channel.notificationsReceived, isNotEmpty);
     Set<String> notificationTypesReceived = new Set<String>();
diff --git a/pkg/analysis_server/test/completion_test_support.dart b/pkg/analysis_server/test/completion_test_support.dart
index 0f00d1e..c2fb7a1 100644
--- a/pkg/analysis_server/test/completion_test_support.dart
+++ b/pkg/analysis_server/test/completion_test_support.dart
@@ -16,7 +16,7 @@
 /**
  * A base class for classes containing completion tests.
  */
-class CompletionTestCase extends CompletionTest {
+class CompletionTestCase extends CompletionDomainHandlerTest {
   static const String CURSOR_MARKER = '!';
 
   List get suggestedCompletions => suggestions
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index a3e956a..acff007 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -7,277 +7,26 @@
 import 'dart:async';
 
 import 'package:analysis_server/plugin/protocol/protocol.dart';
-import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analysis_server/src/channel/channel.dart';
-import 'package:analysis_server/src/constants.dart';
-import 'package:analysis_server/src/context_manager.dart';
-import 'package:analysis_server/src/domain_analysis.dart';
 import 'package:analysis_server/src/domain_completion.dart';
-import 'package:analysis_server/src/plugin/server_plugin.dart';
-import 'package:analysis_server/src/provisional/completion/completion_core.dart'
-    show AnalysisRequest, CompletionRequest, CompletionResult;
+import 'package:analysis_server/src/provisional/completion/completion_core.dart';
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
-import 'package:analysis_server/src/services/completion/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/dart/contribution_sorter.dart';
-import 'package:analysis_server/src/services/index/index.dart' show Index;
-import 'package:analysis_server/src/services/index/local_memory_index.dart';
-import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/source/pub_package_map_provider.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:plugin/manager.dart';
-import 'package:plugin/plugin.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 import 'package:unittest/unittest.dart';
 
 import 'analysis_abstract.dart';
 import 'domain_completion_util.dart';
-import 'mock_sdk.dart';
-import 'mocks.dart';
 import 'utils.dart';
 
 main() {
   initializeTestEnvironment();
-  defineReflectiveTests(CompletionManagerTest);
-  defineReflectiveTests(CompletionTest);
+  defineReflectiveTests(CompletionDomainHandlerTest);
   defineReflectiveTests(_NoSearchEngine);
 }
 
 @reflectiveTest
-class CompletionManagerTest extends AbstractAnalysisTest {
-  AnalysisDomainHandler analysisDomain;
-  Test_CompletionDomainHandler completionDomain;
-  Request request;
-  int requestCount = 0;
-  String testFile2 = '/project/bin/test2.dart';
-
-  AnalysisServer createAnalysisServer(Index index) {
-    //
-    // Collect plugins
-    //
-    ServerPlugin serverPlugin = new ServerPlugin();
-    List<Plugin> plugins = <Plugin>[];
-    plugins.addAll(AnalysisEngine.instance.requiredPlugins);
-    plugins.add(serverPlugin);
-    addServerPlugins(plugins);
-    //
-    // Process plugins
-    //
-    ExtensionManager manager = new ExtensionManager();
-    manager.processPlugins(plugins);
-    //
-    // Create the server
-    //
-    return new Test_AnalysisServer(
-        super.serverChannel,
-        super.resourceProvider,
-        super.packageMapProvider,
-        index,
-        serverPlugin,
-        new AnalysisServerOptions(),
-        new MockSdk(),
-        InstrumentationService.NULL_SERVICE);
-  }
-
-  @override
-  Index createIndex() {
-    return createLocalMemoryIndex();
-  }
-
-  void sendRequest(String path) {
-    String id = (++requestCount).toString();
-    request = new CompletionGetSuggestionsParams(path, 0).toRequest(id);
-    Response response = handler.handleRequest(request);
-    expect(response, isResponseSuccess(id));
-  }
-
-  @override
-  void setUp() {
-    super.setUp();
-    createProject();
-    analysisDomain = handler;
-    completionDomain = new Test_CompletionDomainHandler(server);
-    handler = completionDomain;
-    addTestFile('^library A; cl');
-    addFile(testFile2, 'library B; cl');
-  }
-
-  void tearDown() {
-    super.tearDown();
-    analysisDomain = null;
-    completionDomain = null;
-  }
-
-  /**
-   * Assert different managers are used for different sources
-   */
-  test_2_requests_different_sources() {
-    expect(completionDomain.manager, isNull);
-    sendRequest(testFile);
-    expect(completionDomain.manager, isNotNull);
-    MockCompletionManager expectedManager = completionDomain.manager;
-    expect(expectedManager.disposeCallCount, 0);
-    expect(completionDomain.mockContext.mockStream.listenCount, 1);
-    expect(completionDomain.mockContext.mockStream.cancelCount, 0);
-    return pumpEventQueue().then((_) {
-      expect(completionDomain.manager, expectedManager);
-      expect(completionDomain.mockManager.computeCallCount, 1);
-      sendRequest(testFile2);
-      expect(completionDomain.manager, isNotNull);
-      expect(completionDomain.manager, isNot(expectedManager));
-      expect(expectedManager.disposeCallCount, 1);
-      expectedManager = completionDomain.manager;
-      expect(completionDomain.mockContext.mockStream.listenCount, 2);
-      expect(completionDomain.mockContext.mockStream.cancelCount, 1);
-      return pumpEventQueue();
-    }).then((_) {
-      expect(completionDomain.manager, expectedManager);
-      expect(completionDomain.mockContext.mockStream.listenCount, 2);
-      expect(completionDomain.mockContext.mockStream.cancelCount, 1);
-      expect(completionDomain.mockManager.computeCallCount, 1);
-    });
-  }
-
-  /**
-   * Assert same manager is used for multiple requests on same source
-   */
-  test_2_requests_same_source() {
-    expect(completionDomain.manager, isNull);
-    sendRequest(testFile);
-    expect(completionDomain.manager, isNotNull);
-    expect(completionDomain.manager.source, isNotNull);
-    CompletionManager expectedManager = completionDomain.manager;
-    expect(completionDomain.mockContext.mockStream.listenCount, 1);
-    expect(completionDomain.mockContext.mockStream.cancelCount, 0);
-    return pumpEventQueue().then((_) {
-      expect(completionDomain.manager, expectedManager);
-      expect(completionDomain.mockManager.computeCallCount, 1);
-      sendRequest(testFile);
-      expect(completionDomain.manager, expectedManager);
-      expect(completionDomain.mockContext.mockStream.listenCount, 1);
-      expect(completionDomain.mockContext.mockStream.cancelCount, 0);
-      return pumpEventQueue();
-    }).then((_) {
-      expect(completionDomain.manager, expectedManager);
-      expect(completionDomain.mockContext.mockStream.listenCount, 1);
-      expect(completionDomain.mockContext.mockStream.cancelCount, 0);
-      expect(completionDomain.mockManager.computeCallCount, 2);
-    });
-  }
-
-  /**
-   * Assert manager is NOT cleared when context NOT associated with manager changes.
-   */
-  test_contextsChanged_different() {
-    sendRequest(testFile);
-    CompletionManager expectedManager;
-    return pumpEventQueue().then((_) {
-      expect(completionDomain.manager, isNotNull);
-      expectedManager = completionDomain.manager;
-      completionDomain.contextsChangedRaw(
-          new ContextsChangedEvent(changed: [new MockContext()]));
-      return pumpEventQueue();
-    }).then((_) {
-      expect(completionDomain.manager, expectedManager);
-    });
-  }
-
-  /**
-   * Assert manager is cleared when context associated with manager changes.
-   */
-  test_contextsChanged_same() {
-    sendRequest(testFile);
-    return pumpEventQueue().then((_) {
-      expect(completionDomain.manager, isNotNull);
-      completionDomain.contextsChangedRaw(
-          new ContextsChangedEvent(changed: [completionDomain.mockContext]));
-      return pumpEventQueue();
-    }).then((_) {
-      expect(completionDomain.manager, isNull);
-    });
-  }
-
-  /**
-   * Assert manager is cleared when analysis roots are set
-   */
-  test_setAnalysisRoots() {
-    sendRequest(testFile);
-    return pumpEventQueue().then((_) {
-      expect(completionDomain.manager, isNotNull);
-      request = new AnalysisSetAnalysisRootsParams([], []).toRequest('7');
-      Response response = analysisDomain.handleRequest(request);
-      expect(response, isResponseSuccess('7'));
-      return pumpEventQueue();
-    }).then((_) {
-      expect(completionDomain.manager, isNull);
-    });
-  }
-
-  /**
-   * Assert manager is cleared when source NOT associated with manager is changed.
-   */
-  test_sourcesChanged_different_source_changed() {
-    sendRequest(testFile);
-    return pumpEventQueue().then((_) {
-      expect(completionDomain.manager, isNotNull);
-      ContextSourcePair contextSource = server.getContextSourcePair(testFile2);
-      ChangeSet changeSet = new ChangeSet();
-      changeSet.changedSource(contextSource.source);
-      completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
-      expect(completionDomain.manager, isNull);
-    });
-  }
-
-  /**
-   * Assert manager is NOT cleared when source associated with manager is changed.
-   */
-  test_sourcesChanged_same_source_changed() {
-    sendRequest(testFile);
-    return pumpEventQueue().then((_) {
-      expect(completionDomain.manager, isNotNull);
-      CompletionManager expectedManager = completionDomain.manager;
-      ChangeSet changeSet = new ChangeSet();
-      changeSet.changedSource(completionDomain.manager.source);
-      completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
-      expect(completionDomain.manager, expectedManager);
-    });
-  }
-
-  /**
-   * Assert manager is cleared when source is deleted
-   */
-  test_sourcesChanged_source_deleted() {
-    sendRequest(testFile);
-    return pumpEventQueue().then((_) {
-      expect(completionDomain.manager, isNotNull);
-      ChangeSet changeSet = new ChangeSet();
-      changeSet.deletedSource(completionDomain.manager.source);
-      completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
-      expect(completionDomain.manager, isNull);
-    });
-  }
-
-  /**
-   * Assert manager is cleared when source is removed
-   */
-  test_sourcesChanged_source_removed() {
-    sendRequest(testFile);
-    return pumpEventQueue().then((_) {
-      expect(completionDomain.manager, isNotNull);
-      ChangeSet changeSet = new ChangeSet();
-      changeSet.removedSource(completionDomain.manager.source);
-      completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
-      expect(completionDomain.manager, isNull);
-    });
-  }
-}
-
-@reflectiveTest
-class CompletionTest extends AbstractCompletionDomainTest {
+class CompletionDomainHandlerTest extends AbstractCompletionDomainTest {
   test_html() {
     testFile = '/project/web/test.html';
     addTestFile('''
@@ -694,74 +443,6 @@
   }
 }
 
-class MockCompletionManager implements CompletionManager {
-  final AnalysisContext context;
-  final Source source;
-  final SearchEngine searchEngine;
-  StreamController<CompletionResult> controller;
-  int computeCallCount = 0;
-  int disposeCallCount = 0;
-
-  MockCompletionManager(this.context, this.source, this.searchEngine);
-
-  @override
-  Future<bool> computeCache() {
-    return new Future.value(true);
-  }
-
-  @override
-  void computeSuggestions(CompletionRequest request) {
-    ++computeCallCount;
-    CompletionResult result = new CompletionResultImpl(0, 0, [], true);
-    controller.add(result);
-  }
-
-  @override
-  void dispose() {
-    ++disposeCallCount;
-  }
-
-  @override
-  Stream<CompletionResult> results(CompletionRequest request) {
-    controller = new StreamController<CompletionResult>(onListen: () {
-      scheduleMicrotask(() {
-        computeSuggestions(request);
-      });
-    });
-    return controller.stream;
-  }
-}
-
-/**
- * Mock [AnaysisContext] for tracking usage of onSourcesChanged.
- */
-class MockContext implements AnalysisContext {
-  static final SourceFactory DEFAULT_SOURCE_FACTORY = new SourceFactory([]);
-
-  MockStream<SourcesChangedEvent> mockStream;
-
-  SourceFactory sourceFactory = DEFAULT_SOURCE_FACTORY;
-
-  MockContext() {
-    mockStream = new MockStream<SourcesChangedEvent>();
-  }
-
-  @override
-  Stream<SourcesChangedEvent> get onSourcesChanged => mockStream;
-
-  @override
-  bool exists(Source source) {
-    return source != null && source.exists();
-  }
-
-  @override
-  TimestampedData<String> getContents(Source source) {
-    return source.contents;
-  }
-
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
 class MockRelevancySorter implements DartContributionSorter {
   bool enabled = true;
 
@@ -775,101 +456,6 @@
   }
 }
 
-/**
- * Mock stream for tracking calls to listen and subscription.cancel.
- */
-class MockStream<E> implements Stream<E> {
-  MockSubscription<E> mockSubscription = new MockSubscription<E>();
-  int listenCount = 0;
-
-  int get cancelCount => mockSubscription.cancelCount;
-
-  @override
-  StreamSubscription<E> listen(void onData(E event),
-      {Function onError, void onDone(), bool cancelOnError}) {
-    ++listenCount;
-    return mockSubscription;
-  }
-
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
-/**
- * Mock subscription for tracking calls to subscription.cancel.
- */
-class MockSubscription<E> implements StreamSubscription<E> {
-  int cancelCount = 0;
-
-  Future cancel() {
-    ++cancelCount;
-    return new Future.value(true);
-  }
-
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
-class Test_AnalysisServer extends AnalysisServer {
-  final MockContext mockContext = new MockContext();
-
-  Test_AnalysisServer(
-      ServerCommunicationChannel channel,
-      ResourceProvider resourceProvider,
-      PubPackageMapProvider packageMapProvider,
-      Index index,
-      ServerPlugin serverPlugin,
-      AnalysisServerOptions analysisServerOptions,
-      DartSdk defaultSdk,
-      InstrumentationService instrumentationService)
-      : super(
-            channel,
-            resourceProvider,
-            packageMapProvider,
-            index,
-            serverPlugin,
-            analysisServerOptions,
-            defaultSdk,
-            instrumentationService);
-
-  @override
-  AnalysisContext getAnalysisContext(String path) {
-    return mockContext;
-  }
-
-  @override
-  ContextSourcePair getContextSourcePair(String path) {
-    ContextSourcePair pair = super.getContextSourcePair(path);
-    return new ContextSourcePair(mockContext, pair.source);
-  }
-}
-
-/**
- * A [CompletionDomainHandler] subclass that returns a mock completion manager
- * so that the domain handler cache management can be tested.
- */
-class Test_CompletionDomainHandler extends CompletionDomainHandler {
-  Test_CompletionDomainHandler(Test_AnalysisServer server) : super(server);
-
-  MockContext get mockContext => (server as Test_AnalysisServer).mockContext;
-
-  MockCompletionManager get mockManager => manager;
-
-  void contextsChanged(ContextsChangedEvent event) {
-    contextsChangedRaw(new ContextsChangedEvent(
-        added: event.added.length > 0 ? [mockContext] : [],
-        changed: event.changed.length > 0 ? [mockContext] : [],
-        removed: event.removed.length > 0 ? [mockContext] : []));
-  }
-
-  void contextsChangedRaw(ContextsChangedEvent newEvent) {
-    super.contextsChanged(newEvent);
-  }
-
-  CompletionManager createCompletionManager(
-      AnalysisServer server, AnalysisContext context, Source source) {
-    return new MockCompletionManager(mockContext, source, searchEngine);
-  }
-}
-
 @reflectiveTest
 class _NoSearchEngine extends AbstractAnalysisTest {
   @override
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index d76f15c1..28c6a09 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -23,6 +23,7 @@
 import 'package:unittest/unittest.dart';
 
 import '../../../abstract_context.dart';
+import 'package:analysis_server/src/services/completion/completion_performance.dart';
 
 int suggestionComparator(CompletionSuggestion s1, CompletionSuggestion s2) {
   String c1 = s1.completion.toLowerCase();
@@ -436,7 +437,12 @@
 
   Future computeSuggestions([int times = 200]) async {
     CompletionRequestImpl baseRequest = new CompletionRequestImpl(
-        context, provider, searchEngine, testSource, completionOffset);
+        context,
+        provider,
+        searchEngine,
+        testSource,
+        completionOffset,
+        new CompletionPerformance());
 
     // Build the request
     Completer<DartCompletionRequest> requestCompleter =
diff --git a/pkg/analysis_server/test/services/completion/optype_test.dart b/pkg/analysis_server/test/services/completion/dart/optype_test.dart
similarity index 99%
rename from pkg/analysis_server/test/services/completion/optype_test.dart
rename to pkg/analysis_server/test/services/completion/dart/optype_test.dart
index 8fb29bf..9ed569e 100644
--- a/pkg/analysis_server/test/services/completion/optype_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/optype_test.dart
@@ -4,8 +4,9 @@
 
 library test.services.completion.contributor.dart.optype;
 
+import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/provisional/completion/dart/completion_target.dart';
-import 'package:analysis_server/src/services/completion/optype.dart';
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -13,9 +14,8 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 import 'package:unittest/unittest.dart';
 
-import '../../abstract_context.dart';
-import '../../utils.dart';
-import 'package:analysis_server/src/protocol_server.dart';
+import '../../../abstract_context.dart';
+import '../../../utils.dart';
 
 main() {
   initializeTestEnvironment();
diff --git a/pkg/analysis_server/test/services/completion/dart/test_all.dart b/pkg/analysis_server/test/services/completion/dart/test_all.dart
index 482780f..c12f8de 100644
--- a/pkg/analysis_server/test/services/completion/dart/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/dart/test_all.dart
@@ -22,6 +22,7 @@
 import 'local_library_contributor_test.dart' as local_lib_test;
 import 'local_reference_contributor_test.dart' as local_ref_test;
 import 'named_constructor_contributor_test.dart' as named_contributor_test;
+import 'optype_test.dart' as optype_test;
 import 'override_contributor_test.dart' as override_contributor_test;
 import 'static_member_contributor_test.dart' as static_contributor_test;
 import 'type_member_contributor_test.dart' as type_member_contributor_test;
@@ -46,6 +47,7 @@
     local_lib_test.main();
     local_ref_test.main();
     named_contributor_test.main();
+    optype_test.main();
     override_contributor_test.main();
     static_contributor_test.main();
     type_member_contributor_test.main();
diff --git a/pkg/analysis_server/test/services/completion/test_all.dart b/pkg/analysis_server/test/services/completion/test_all.dart
index d6b119e..f219dda 100644
--- a/pkg/analysis_server/test/services/completion/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/test_all.dart
@@ -9,7 +9,6 @@
 import '../../utils.dart';
 import 'completion_target_test.dart' as completion_target_test;
 import 'dart/test_all.dart' as dart_contributor_tests;
-import 'optype_test.dart' as optype_test;
 
 /// Utility for manually running all tests.
 main() {
@@ -17,6 +16,5 @@
   group('completion', () {
     completion_target_test.main();
     dart_contributor_tests.main();
-    optype_test.main();
   });
 }
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index a6ec27a..7ce9b90 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -3278,6 +3278,48 @@
 ''');
   }
 
+  test_makeFieldNotFinal_hasType() async {
+    resolveTestUnit('''
+class A {
+  final int fff = 1;
+  main() {
+    fff = 2;
+  }
+}
+''');
+    await assertHasFix(
+        DartFixKind.MAKE_FIELD_NOT_FINAL,
+        '''
+class A {
+  int fff = 1;
+  main() {
+    fff = 2;
+  }
+}
+''');
+  }
+
+  test_makeFieldNotFinal_noType() async {
+    resolveTestUnit('''
+class A {
+  final fff = 1;
+  main() {
+    fff = 2;
+  }
+}
+''');
+    await assertHasFix(
+        DartFixKind.MAKE_FIELD_NOT_FINAL,
+        '''
+class A {
+  var fff = 1;
+  main() {
+    fff = 2;
+  }
+}
+''');
+  }
+
   test_noException_1() async {
     resolveTestUnit('''
 main(p) {
diff --git a/pkg/analysis_server/test/services/refactoring/extract_local_test.dart b/pkg/analysis_server/test/services/refactoring/extract_local_test.dart
index cac1c16..0ced288 100644
--- a/pkg/analysis_server/test/services/refactoring/extract_local_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/extract_local_test.dart
@@ -426,7 +426,21 @@
     expect(subExpressions, ['111', '111 + 222']);
   }
 
-  test_coveringExpressions_skipAssignments() async {
+  test_coveringExpressions_namedExpression_value() async {
+    indexTestUnit('''
+main() {
+  foo(ppp: 42);
+}
+int foo({int ppp: 0}) => ppp + 1;
+''');
+    _createRefactoring(testCode.indexOf('42'), 0);
+    // check conditions
+    await refactoring.checkInitialConditions();
+    List<String> subExpressions = _getCoveringExpressions();
+    expect(subExpressions, ['42', 'foo(ppp: 42)']);
+  }
+
+  test_coveringExpressions_skip_assignment() async {
     indexTestUnit('''
 main() {
   int v;
@@ -441,6 +455,80 @@
     expect(subExpressions, ['111', '111 + 222', 'foo(v = 111 + 222)']);
   }
 
+  test_coveringExpressions_skip_constructorName() async {
+    indexTestUnit('''
+class AAA {
+  AAA.name() {}
+}
+main() {
+  int v = new AAA.name();
+}
+''');
+    _createRefactoring(testCode.indexOf('AA.name();'), 5);
+    // check conditions
+    await refactoring.checkInitialConditions();
+    List<String> subExpressions = _getCoveringExpressions();
+    expect(subExpressions, ['new AAA.name()']);
+  }
+
+  test_coveringExpressions_skip_constructorName_name() async {
+    indexTestUnit('''
+class A {
+  A.name() {}
+}
+main() {
+  int v = new A.name();
+}
+''');
+    _createRefactoring(testCode.indexOf('ame();'), 0);
+    // check conditions
+    await refactoring.checkInitialConditions();
+    List<String> subExpressions = _getCoveringExpressions();
+    expect(subExpressions, ['new A.name()']);
+  }
+
+  test_coveringExpressions_skip_constructorName_type() async {
+    indexTestUnit('''
+class A {}
+main() {
+  int v = new A();
+}
+''');
+    _createRefactoring(testCode.indexOf('A();'), 0);
+    // check conditions
+    await refactoring.checkInitialConditions();
+    List<String> subExpressions = _getCoveringExpressions();
+    expect(subExpressions, ['new A()']);
+  }
+
+  test_coveringExpressions_skip_constructorName_typeArgument() async {
+    indexTestUnit('''
+class A<T> {}
+main() {
+  int v = new A<String>();
+}
+''');
+    _createRefactoring(testCode.indexOf('ring>'), 0);
+    // check conditions
+    await refactoring.checkInitialConditions();
+    List<String> subExpressions = _getCoveringExpressions();
+    expect(subExpressions, ['new A<String>()']);
+  }
+
+  test_coveringExpressions_skip_namedExpression() async {
+    indexTestUnit('''
+main() {
+  foo(ppp: 42);
+}
+int foo({int ppp: 0}) => ppp + 1;
+''');
+    _createRefactoring(testCode.indexOf('pp: 42'), 0);
+    // check conditions
+    await refactoring.checkInitialConditions();
+    List<String> subExpressions = _getCoveringExpressions();
+    expect(subExpressions, ['foo(ppp: 42)']);
+  }
+
   test_fragmentExpression() {
     indexTestUnit('''
 main() {
diff --git a/pkg/analysis_server/tool/spec/generate_files b/pkg/analysis_server/tool/spec/generate_files
index 0c992fa..85092ea 100755
--- a/pkg/analysis_server/tool/spec/generate_files
+++ b/pkg/analysis_server/tool/spec/generate_files
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # 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.
diff --git a/pkg/analyzer/lib/dart/ast/visitor.dart b/pkg/analyzer/lib/dart/ast/visitor.dart
new file mode 100644
index 0000000..c9b345a
--- /dev/null
+++ b/pkg/analyzer/lib/dart/ast/visitor.dart
@@ -0,0 +1,1884 @@
+// 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.
+
+library analyzer.dart.ast.visitor;
+
+import 'dart:collection';
+
+import 'package:analyzer/src/generated/ast.dart';
+
+/**
+ * An AST visitor that will recursively visit all of the nodes in an AST
+ * structure, similar to [GeneralizingAstVisitor]. This visitor uses a
+ * breadth-first ordering rather than the depth-first ordering of
+ * [GeneralizingAstVisitor].
+ *
+ * Subclasses that override a visit method must either invoke the overridden
+ * visit method or explicitly invoke the more general visit method. Failure to
+ * do so will cause the visit methods for superclasses of the node to not be
+ * invoked and will cause the children of the visited node to not be visited.
+ *
+ * In addition, subclasses should <b>not</b> explicitly visit the children of a
+ * node, but should ensure that the method [visitNode] is used to visit the
+ * children (either directly or indirectly). Failure to do will break the order
+ * in which nodes are visited.
+ *
+ * Note that, unlike other visitors that begin to visit a structure of nodes by
+ * asking the root node in the structure to accept the visitor, this visitor
+ * requires that clients start the visit by invoking the method [visitAllNodes]
+ * defined on the visitor with the root node as the argument:
+ *
+ *     visitor.visitAllNodes(rootNode);
+ *
+ * Clients may extend or implement this class.
+ */
+class BreadthFirstVisitor<R> extends GeneralizingAstVisitor<R> {
+  /**
+   * A queue holding the nodes that have not yet been visited in the order in
+   * which they ought to be visited.
+   */
+  Queue<AstNode> _queue = new Queue<AstNode>();
+
+  /**
+   * A visitor, used to visit the children of the current node, that will add
+   * the nodes it visits to the [_queue].
+   */
+  _BreadthFirstChildVisitor _childVisitor;
+
+  /**
+   * Initialize a newly created visitor.
+   */
+  BreadthFirstVisitor() {
+    _childVisitor = new _BreadthFirstChildVisitor(this);
+  }
+
+  /**
+   * Visit all nodes in the tree starting at the given [root] node, in
+   * breadth-first order.
+   */
+  void visitAllNodes(AstNode root) {
+    _queue.add(root);
+    while (!_queue.isEmpty) {
+      AstNode next = _queue.removeFirst();
+      next.accept(this);
+    }
+  }
+
+  @override
+  R visitNode(AstNode node) {
+    node.visitChildren(_childVisitor);
+    return null;
+  }
+}
+
+/**
+ * An AST visitor that will recursively visit all of the nodes in an AST
+ * structure (like instances of the class [RecursiveAstVisitor]). In addition,
+ * when a node of a specific type is visited not only will the visit method for
+ * that specific type of node be invoked, but additional methods for the
+ * superclasses of that node will also be invoked. For example, using an
+ * instance of this class to visit a [Block] will cause the method [visitBlock]
+ * to be invoked but will also cause the methods [visitStatement] and
+ * [visitNode] to be subsequently invoked. This allows visitors to be written
+ * that visit all statements without needing to override the visit method for
+ * each of the specific subclasses of [Statement].
+ *
+ * Subclasses that override a visit method must either invoke the overridden
+ * visit method or explicitly invoke the more general visit method. Failure to
+ * do so will cause the visit methods for superclasses of the node to not be
+ * invoked and will cause the children of the visited node to not be visited.
+ *
+ * Clients may extend or implement this class.
+ */
+class GeneralizingAstVisitor<R> implements AstVisitor<R> {
+  @override
+  R visitAdjacentStrings(AdjacentStrings node) => visitStringLiteral(node);
+
+  R visitAnnotatedNode(AnnotatedNode node) => visitNode(node);
+
+  @override
+  R visitAnnotation(Annotation node) => visitNode(node);
+
+  @override
+  R visitArgumentList(ArgumentList node) => visitNode(node);
+
+  @override
+  R visitAsExpression(AsExpression node) => visitExpression(node);
+
+  @override
+  R visitAssertStatement(AssertStatement node) => visitStatement(node);
+
+  @override
+  R visitAssignmentExpression(AssignmentExpression node) =>
+      visitExpression(node);
+
+  @override
+  R visitAwaitExpression(AwaitExpression node) => visitExpression(node);
+
+  @override
+  R visitBinaryExpression(BinaryExpression node) => visitExpression(node);
+
+  @override
+  R visitBlock(Block node) => visitStatement(node);
+
+  @override
+  R visitBlockFunctionBody(BlockFunctionBody node) => visitFunctionBody(node);
+
+  @override
+  R visitBooleanLiteral(BooleanLiteral node) => visitLiteral(node);
+
+  @override
+  R visitBreakStatement(BreakStatement node) => visitStatement(node);
+
+  @override
+  R visitCascadeExpression(CascadeExpression node) => visitExpression(node);
+
+  @override
+  R visitCatchClause(CatchClause node) => visitNode(node);
+
+  @override
+  R visitClassDeclaration(ClassDeclaration node) =>
+      visitNamedCompilationUnitMember(node);
+
+  R visitClassMember(ClassMember node) => visitDeclaration(node);
+
+  @override
+  R visitClassTypeAlias(ClassTypeAlias node) => visitTypeAlias(node);
+
+  R visitCombinator(Combinator node) => visitNode(node);
+
+  @override
+  R visitComment(Comment node) => visitNode(node);
+
+  @override
+  R visitCommentReference(CommentReference node) => visitNode(node);
+
+  @override
+  R visitCompilationUnit(CompilationUnit node) => visitNode(node);
+
+  R visitCompilationUnitMember(CompilationUnitMember node) =>
+      visitDeclaration(node);
+
+  @override
+  R visitConditionalExpression(ConditionalExpression node) =>
+      visitExpression(node);
+
+  @override
+  R visitConfiguration(Configuration node) => visitNode(node);
+
+  @override
+  R visitConstructorDeclaration(ConstructorDeclaration node) =>
+      visitClassMember(node);
+
+  @override
+  R visitConstructorFieldInitializer(ConstructorFieldInitializer node) =>
+      visitConstructorInitializer(node);
+
+  R visitConstructorInitializer(ConstructorInitializer node) => visitNode(node);
+
+  @override
+  R visitConstructorName(ConstructorName node) => visitNode(node);
+
+  @override
+  R visitContinueStatement(ContinueStatement node) => visitStatement(node);
+
+  R visitDeclaration(Declaration node) => visitAnnotatedNode(node);
+
+  @override
+  R visitDeclaredIdentifier(DeclaredIdentifier node) => visitDeclaration(node);
+
+  @override
+  R visitDefaultFormalParameter(DefaultFormalParameter node) =>
+      visitFormalParameter(node);
+
+  R visitDirective(Directive node) => visitAnnotatedNode(node);
+
+  @override
+  R visitDoStatement(DoStatement node) => visitStatement(node);
+
+  @override
+  R visitDottedName(DottedName node) => visitNode(node);
+
+  @override
+  R visitDoubleLiteral(DoubleLiteral node) => visitLiteral(node);
+
+  @override
+  R visitEmptyFunctionBody(EmptyFunctionBody node) => visitFunctionBody(node);
+
+  @override
+  R visitEmptyStatement(EmptyStatement node) => visitStatement(node);
+
+  @override
+  R visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
+      visitDeclaration(node);
+
+  @override
+  R visitEnumDeclaration(EnumDeclaration node) =>
+      visitNamedCompilationUnitMember(node);
+
+  @override
+  R visitExportDirective(ExportDirective node) => visitNamespaceDirective(node);
+
+  R visitExpression(Expression node) => visitNode(node);
+
+  @override
+  R visitExpressionFunctionBody(ExpressionFunctionBody node) =>
+      visitFunctionBody(node);
+
+  @override
+  R visitExpressionStatement(ExpressionStatement node) => visitStatement(node);
+
+  @override
+  R visitExtendsClause(ExtendsClause node) => visitNode(node);
+
+  @override
+  R visitFieldDeclaration(FieldDeclaration node) => visitClassMember(node);
+
+  @override
+  R visitFieldFormalParameter(FieldFormalParameter node) =>
+      visitNormalFormalParameter(node);
+
+  @override
+  R visitForEachStatement(ForEachStatement node) => visitStatement(node);
+
+  R visitFormalParameter(FormalParameter node) => visitNode(node);
+
+  @override
+  R visitFormalParameterList(FormalParameterList node) => visitNode(node);
+
+  @override
+  R visitForStatement(ForStatement node) => visitStatement(node);
+
+  R visitFunctionBody(FunctionBody node) => visitNode(node);
+
+  @override
+  R visitFunctionDeclaration(FunctionDeclaration node) =>
+      visitNamedCompilationUnitMember(node);
+
+  @override
+  R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) =>
+      visitStatement(node);
+
+  @override
+  R visitFunctionExpression(FunctionExpression node) => visitExpression(node);
+
+  @override
+  R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) =>
+      visitExpression(node);
+
+  @override
+  R visitFunctionTypeAlias(FunctionTypeAlias node) => visitTypeAlias(node);
+
+  @override
+  R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) =>
+      visitNormalFormalParameter(node);
+
+  @override
+  R visitHideCombinator(HideCombinator node) => visitCombinator(node);
+
+  R visitIdentifier(Identifier node) => visitExpression(node);
+
+  @override
+  R visitIfStatement(IfStatement node) => visitStatement(node);
+
+  @override
+  R visitImplementsClause(ImplementsClause node) => visitNode(node);
+
+  @override
+  R visitImportDirective(ImportDirective node) => visitNamespaceDirective(node);
+
+  @override
+  R visitIndexExpression(IndexExpression node) => visitExpression(node);
+
+  @override
+  R visitInstanceCreationExpression(InstanceCreationExpression node) =>
+      visitExpression(node);
+
+  @override
+  R visitIntegerLiteral(IntegerLiteral node) => visitLiteral(node);
+
+  R visitInterpolationElement(InterpolationElement node) => visitNode(node);
+
+  @override
+  R visitInterpolationExpression(InterpolationExpression node) =>
+      visitInterpolationElement(node);
+
+  @override
+  R visitInterpolationString(InterpolationString node) =>
+      visitInterpolationElement(node);
+
+  @override
+  R visitIsExpression(IsExpression node) => visitExpression(node);
+
+  @override
+  R visitLabel(Label node) => visitNode(node);
+
+  @override
+  R visitLabeledStatement(LabeledStatement node) => visitStatement(node);
+
+  @override
+  R visitLibraryDirective(LibraryDirective node) => visitDirective(node);
+
+  @override
+  R visitLibraryIdentifier(LibraryIdentifier node) => visitIdentifier(node);
+
+  @override
+  R visitListLiteral(ListLiteral node) => visitTypedLiteral(node);
+
+  R visitLiteral(Literal node) => visitExpression(node);
+
+  @override
+  R visitMapLiteral(MapLiteral node) => visitTypedLiteral(node);
+
+  @override
+  R visitMapLiteralEntry(MapLiteralEntry node) => visitNode(node);
+
+  @override
+  R visitMethodDeclaration(MethodDeclaration node) => visitClassMember(node);
+
+  @override
+  R visitMethodInvocation(MethodInvocation node) => visitExpression(node);
+
+  R visitNamedCompilationUnitMember(NamedCompilationUnitMember node) =>
+      visitCompilationUnitMember(node);
+
+  @override
+  R visitNamedExpression(NamedExpression node) => visitExpression(node);
+
+  R visitNamespaceDirective(NamespaceDirective node) =>
+      visitUriBasedDirective(node);
+
+  @override
+  R visitNativeClause(NativeClause node) => visitNode(node);
+
+  @override
+  R visitNativeFunctionBody(NativeFunctionBody node) => visitFunctionBody(node);
+
+  R visitNode(AstNode node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  R visitNormalFormalParameter(NormalFormalParameter node) =>
+      visitFormalParameter(node);
+
+  @override
+  R visitNullLiteral(NullLiteral node) => visitLiteral(node);
+
+  @override
+  R visitParenthesizedExpression(ParenthesizedExpression node) =>
+      visitExpression(node);
+
+  @override
+  R visitPartDirective(PartDirective node) => visitUriBasedDirective(node);
+
+  @override
+  R visitPartOfDirective(PartOfDirective node) => visitDirective(node);
+
+  @override
+  R visitPostfixExpression(PostfixExpression node) => visitExpression(node);
+
+  @override
+  R visitPrefixedIdentifier(PrefixedIdentifier node) => visitIdentifier(node);
+
+  @override
+  R visitPrefixExpression(PrefixExpression node) => visitExpression(node);
+
+  @override
+  R visitPropertyAccess(PropertyAccess node) => visitExpression(node);
+
+  @override
+  R visitRedirectingConstructorInvocation(
+          RedirectingConstructorInvocation node) =>
+      visitConstructorInitializer(node);
+
+  @override
+  R visitRethrowExpression(RethrowExpression node) => visitExpression(node);
+
+  @override
+  R visitReturnStatement(ReturnStatement node) => visitStatement(node);
+
+  @override
+  R visitScriptTag(ScriptTag scriptTag) => visitNode(scriptTag);
+
+  @override
+  R visitShowCombinator(ShowCombinator node) => visitCombinator(node);
+
+  @override
+  R visitSimpleFormalParameter(SimpleFormalParameter node) =>
+      visitNormalFormalParameter(node);
+
+  @override
+  R visitSimpleIdentifier(SimpleIdentifier node) => visitIdentifier(node);
+
+  @override
+  R visitSimpleStringLiteral(SimpleStringLiteral node) =>
+      visitSingleStringLiteral(node);
+
+  R visitSingleStringLiteral(SingleStringLiteral node) =>
+      visitStringLiteral(node);
+
+  R visitStatement(Statement node) => visitNode(node);
+
+  @override
+  R visitStringInterpolation(StringInterpolation node) =>
+      visitSingleStringLiteral(node);
+
+  R visitStringLiteral(StringLiteral node) => visitLiteral(node);
+
+  @override
+  R visitSuperConstructorInvocation(SuperConstructorInvocation node) =>
+      visitConstructorInitializer(node);
+
+  @override
+  R visitSuperExpression(SuperExpression node) => visitExpression(node);
+
+  @override
+  R visitSwitchCase(SwitchCase node) => visitSwitchMember(node);
+
+  @override
+  R visitSwitchDefault(SwitchDefault node) => visitSwitchMember(node);
+
+  R visitSwitchMember(SwitchMember node) => visitNode(node);
+
+  @override
+  R visitSwitchStatement(SwitchStatement node) => visitStatement(node);
+
+  @override
+  R visitSymbolLiteral(SymbolLiteral node) => visitLiteral(node);
+
+  @override
+  R visitThisExpression(ThisExpression node) => visitExpression(node);
+
+  @override
+  R visitThrowExpression(ThrowExpression node) => visitExpression(node);
+
+  @override
+  R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) =>
+      visitCompilationUnitMember(node);
+
+  @override
+  R visitTryStatement(TryStatement node) => visitStatement(node);
+
+  R visitTypeAlias(TypeAlias node) => visitNamedCompilationUnitMember(node);
+
+  @override
+  R visitTypeArgumentList(TypeArgumentList node) => visitNode(node);
+
+  R visitTypedLiteral(TypedLiteral node) => visitLiteral(node);
+
+  @override
+  R visitTypeName(TypeName node) => visitNode(node);
+
+  @override
+  R visitTypeParameter(TypeParameter node) => visitNode(node);
+
+  @override
+  R visitTypeParameterList(TypeParameterList node) => visitNode(node);
+
+  R visitUriBasedDirective(UriBasedDirective node) => visitDirective(node);
+
+  @override
+  R visitVariableDeclaration(VariableDeclaration node) =>
+      visitDeclaration(node);
+
+  @override
+  R visitVariableDeclarationList(VariableDeclarationList node) =>
+      visitNode(node);
+
+  @override
+  R visitVariableDeclarationStatement(VariableDeclarationStatement node) =>
+      visitStatement(node);
+
+  @override
+  R visitWhileStatement(WhileStatement node) => visitStatement(node);
+
+  @override
+  R visitWithClause(WithClause node) => visitNode(node);
+
+  @override
+  R visitYieldStatement(YieldStatement node) => visitStatement(node);
+}
+
+/**
+ * An AST visitor that will recursively visit all of the nodes in an AST
+ * structure. For example, using an instance of this class to visit a [Block]
+ * will also cause all of the statements in the block to be visited.
+ *
+ * Subclasses that override a visit method must either invoke the overridden
+ * visit method or must explicitly ask the visited node to visit its children.
+ * Failure to do so will cause the children of the visited node to not be
+ * visited.
+ *
+ * Clients may extend or implement this class.
+ */
+class RecursiveAstVisitor<R> implements AstVisitor<R> {
+  @override
+  R visitAdjacentStrings(AdjacentStrings node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitAnnotation(Annotation node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitArgumentList(ArgumentList node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitAsExpression(AsExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitAssertStatement(AssertStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitAssignmentExpression(AssignmentExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitAwaitExpression(AwaitExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitBinaryExpression(BinaryExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitBlock(Block node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitBlockFunctionBody(BlockFunctionBody node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitBooleanLiteral(BooleanLiteral node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitBreakStatement(BreakStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitCascadeExpression(CascadeExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitCatchClause(CatchClause node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitClassDeclaration(ClassDeclaration node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitClassTypeAlias(ClassTypeAlias node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitComment(Comment node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitCommentReference(CommentReference node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitCompilationUnit(CompilationUnit node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitConditionalExpression(ConditionalExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitConfiguration(Configuration node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitConstructorDeclaration(ConstructorDeclaration node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitConstructorName(ConstructorName node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitContinueStatement(ContinueStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitDeclaredIdentifier(DeclaredIdentifier node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitDefaultFormalParameter(DefaultFormalParameter node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitDoStatement(DoStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitDottedName(DottedName node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitDoubleLiteral(DoubleLiteral node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitEmptyFunctionBody(EmptyFunctionBody node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitEmptyStatement(EmptyStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitEnumDeclaration(EnumDeclaration node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitExportDirective(ExportDirective node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitExpressionFunctionBody(ExpressionFunctionBody node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitExpressionStatement(ExpressionStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitExtendsClause(ExtendsClause node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitFieldDeclaration(FieldDeclaration node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitFieldFormalParameter(FieldFormalParameter node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitForEachStatement(ForEachStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitFormalParameterList(FormalParameterList node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitForStatement(ForStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitFunctionDeclaration(FunctionDeclaration node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitFunctionExpression(FunctionExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitFunctionTypeAlias(FunctionTypeAlias node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitHideCombinator(HideCombinator node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitIfStatement(IfStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitImplementsClause(ImplementsClause node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitImportDirective(ImportDirective node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitIndexExpression(IndexExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitInstanceCreationExpression(InstanceCreationExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitIntegerLiteral(IntegerLiteral node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitInterpolationExpression(InterpolationExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitInterpolationString(InterpolationString node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitIsExpression(IsExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitLabel(Label node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitLabeledStatement(LabeledStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitLibraryDirective(LibraryDirective node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitLibraryIdentifier(LibraryIdentifier node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitListLiteral(ListLiteral node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitMapLiteral(MapLiteral node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitMapLiteralEntry(MapLiteralEntry node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitMethodDeclaration(MethodDeclaration node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitMethodInvocation(MethodInvocation node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitNamedExpression(NamedExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitNativeClause(NativeClause node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitNativeFunctionBody(NativeFunctionBody node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitNullLiteral(NullLiteral node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitParenthesizedExpression(ParenthesizedExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitPartDirective(PartDirective node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitPartOfDirective(PartOfDirective node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitPostfixExpression(PostfixExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitPrefixedIdentifier(PrefixedIdentifier node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitPrefixExpression(PrefixExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitPropertyAccess(PropertyAccess node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitRedirectingConstructorInvocation(
+      RedirectingConstructorInvocation node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitRethrowExpression(RethrowExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitReturnStatement(ReturnStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitScriptTag(ScriptTag node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitShowCombinator(ShowCombinator node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitSimpleFormalParameter(SimpleFormalParameter node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitSimpleIdentifier(SimpleIdentifier node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitSimpleStringLiteral(SimpleStringLiteral node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitStringInterpolation(StringInterpolation node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitSuperExpression(SuperExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitSwitchCase(SwitchCase node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitSwitchDefault(SwitchDefault node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitSwitchStatement(SwitchStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitSymbolLiteral(SymbolLiteral node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitThisExpression(ThisExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitThrowExpression(ThrowExpression node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitTryStatement(TryStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitTypeArgumentList(TypeArgumentList node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitTypeName(TypeName node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitTypeParameter(TypeParameter node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitTypeParameterList(TypeParameterList node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitVariableDeclaration(VariableDeclaration node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitVariableDeclarationList(VariableDeclarationList node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitWhileStatement(WhileStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitWithClause(WithClause node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitYieldStatement(YieldStatement node) {
+    node.visitChildren(this);
+    return null;
+  }
+}
+
+/**
+ * An AST visitor that will do nothing when visiting an AST node. It is intended
+ * to be a superclass for classes that use the visitor pattern primarily as a
+ * dispatch mechanism (and hence don't need to recursively visit a whole
+ * structure) and that only need to visit a small number of node types.
+ *
+ * Clients may extend or implement this class.
+ */
+class SimpleAstVisitor<R> implements AstVisitor<R> {
+  @override
+  R visitAdjacentStrings(AdjacentStrings node) => null;
+
+  @override
+  R visitAnnotation(Annotation node) => null;
+
+  @override
+  R visitArgumentList(ArgumentList node) => null;
+
+  @override
+  R visitAsExpression(AsExpression node) => null;
+
+  @override
+  R visitAssertStatement(AssertStatement node) => null;
+
+  @override
+  R visitAssignmentExpression(AssignmentExpression node) => null;
+
+  @override
+  R visitAwaitExpression(AwaitExpression node) => null;
+
+  @override
+  R visitBinaryExpression(BinaryExpression node) => null;
+
+  @override
+  R visitBlock(Block node) => null;
+
+  @override
+  R visitBlockFunctionBody(BlockFunctionBody node) => null;
+
+  @override
+  R visitBooleanLiteral(BooleanLiteral node) => null;
+
+  @override
+  R visitBreakStatement(BreakStatement node) => null;
+
+  @override
+  R visitCascadeExpression(CascadeExpression node) => null;
+
+  @override
+  R visitCatchClause(CatchClause node) => null;
+
+  @override
+  R visitClassDeclaration(ClassDeclaration node) => null;
+
+  @override
+  R visitClassTypeAlias(ClassTypeAlias node) => null;
+
+  @override
+  R visitComment(Comment node) => null;
+
+  @override
+  R visitCommentReference(CommentReference node) => null;
+
+  @override
+  R visitCompilationUnit(CompilationUnit node) => null;
+
+  @override
+  R visitConditionalExpression(ConditionalExpression node) => null;
+
+  @override
+  R visitConfiguration(Configuration node) => null;
+
+  @override
+  R visitConstructorDeclaration(ConstructorDeclaration node) => null;
+
+  @override
+  R visitConstructorFieldInitializer(ConstructorFieldInitializer node) => null;
+
+  @override
+  R visitConstructorName(ConstructorName node) => null;
+
+  @override
+  R visitContinueStatement(ContinueStatement node) => null;
+
+  @override
+  R visitDeclaredIdentifier(DeclaredIdentifier node) => null;
+
+  @override
+  R visitDefaultFormalParameter(DefaultFormalParameter node) => null;
+
+  @override
+  R visitDoStatement(DoStatement node) => null;
+
+  @override
+  R visitDottedName(DottedName node) => null;
+
+  @override
+  R visitDoubleLiteral(DoubleLiteral node) => null;
+
+  @override
+  R visitEmptyFunctionBody(EmptyFunctionBody node) => null;
+
+  @override
+  R visitEmptyStatement(EmptyStatement node) => null;
+
+  @override
+  R visitEnumConstantDeclaration(EnumConstantDeclaration node) => null;
+
+  @override
+  R visitEnumDeclaration(EnumDeclaration node) => null;
+
+  @override
+  R visitExportDirective(ExportDirective node) => null;
+
+  @override
+  R visitExpressionFunctionBody(ExpressionFunctionBody node) => null;
+
+  @override
+  R visitExpressionStatement(ExpressionStatement node) => null;
+
+  @override
+  R visitExtendsClause(ExtendsClause node) => null;
+
+  @override
+  R visitFieldDeclaration(FieldDeclaration node) => null;
+
+  @override
+  R visitFieldFormalParameter(FieldFormalParameter node) => null;
+
+  @override
+  R visitForEachStatement(ForEachStatement node) => null;
+
+  @override
+  R visitFormalParameterList(FormalParameterList node) => null;
+
+  @override
+  R visitForStatement(ForStatement node) => null;
+
+  @override
+  R visitFunctionDeclaration(FunctionDeclaration node) => null;
+
+  @override
+  R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) =>
+      null;
+
+  @override
+  R visitFunctionExpression(FunctionExpression node) => null;
+
+  @override
+  R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) =>
+      null;
+
+  @override
+  R visitFunctionTypeAlias(FunctionTypeAlias node) => null;
+
+  @override
+  R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) =>
+      null;
+
+  @override
+  R visitHideCombinator(HideCombinator node) => null;
+
+  @override
+  R visitIfStatement(IfStatement node) => null;
+
+  @override
+  R visitImplementsClause(ImplementsClause node) => null;
+
+  @override
+  R visitImportDirective(ImportDirective node) => null;
+
+  @override
+  R visitIndexExpression(IndexExpression node) => null;
+
+  @override
+  R visitInstanceCreationExpression(InstanceCreationExpression node) => null;
+
+  @override
+  R visitIntegerLiteral(IntegerLiteral node) => null;
+
+  @override
+  R visitInterpolationExpression(InterpolationExpression node) => null;
+
+  @override
+  R visitInterpolationString(InterpolationString node) => null;
+
+  @override
+  R visitIsExpression(IsExpression node) => null;
+
+  @override
+  R visitLabel(Label node) => null;
+
+  @override
+  R visitLabeledStatement(LabeledStatement node) => null;
+
+  @override
+  R visitLibraryDirective(LibraryDirective node) => null;
+
+  @override
+  R visitLibraryIdentifier(LibraryIdentifier node) => null;
+
+  @override
+  R visitListLiteral(ListLiteral node) => null;
+
+  @override
+  R visitMapLiteral(MapLiteral node) => null;
+
+  @override
+  R visitMapLiteralEntry(MapLiteralEntry node) => null;
+
+  @override
+  R visitMethodDeclaration(MethodDeclaration node) => null;
+
+  @override
+  R visitMethodInvocation(MethodInvocation node) => null;
+
+  @override
+  R visitNamedExpression(NamedExpression node) => null;
+
+  @override
+  R visitNativeClause(NativeClause node) => null;
+
+  @override
+  R visitNativeFunctionBody(NativeFunctionBody node) => null;
+
+  @override
+  R visitNullLiteral(NullLiteral node) => null;
+
+  @override
+  R visitParenthesizedExpression(ParenthesizedExpression node) => null;
+
+  @override
+  R visitPartDirective(PartDirective node) => null;
+
+  @override
+  R visitPartOfDirective(PartOfDirective node) => null;
+
+  @override
+  R visitPostfixExpression(PostfixExpression node) => null;
+
+  @override
+  R visitPrefixedIdentifier(PrefixedIdentifier node) => null;
+
+  @override
+  R visitPrefixExpression(PrefixExpression node) => null;
+
+  @override
+  R visitPropertyAccess(PropertyAccess node) => null;
+
+  @override
+  R visitRedirectingConstructorInvocation(
+          RedirectingConstructorInvocation node) =>
+      null;
+
+  @override
+  R visitRethrowExpression(RethrowExpression node) => null;
+
+  @override
+  R visitReturnStatement(ReturnStatement node) => null;
+
+  @override
+  R visitScriptTag(ScriptTag node) => null;
+
+  @override
+  R visitShowCombinator(ShowCombinator node) => null;
+
+  @override
+  R visitSimpleFormalParameter(SimpleFormalParameter node) => null;
+
+  @override
+  R visitSimpleIdentifier(SimpleIdentifier node) => null;
+
+  @override
+  R visitSimpleStringLiteral(SimpleStringLiteral node) => null;
+
+  @override
+  R visitStringInterpolation(StringInterpolation node) => null;
+
+  @override
+  R visitSuperConstructorInvocation(SuperConstructorInvocation node) => null;
+
+  @override
+  R visitSuperExpression(SuperExpression node) => null;
+
+  @override
+  R visitSwitchCase(SwitchCase node) => null;
+
+  @override
+  R visitSwitchDefault(SwitchDefault node) => null;
+
+  @override
+  R visitSwitchStatement(SwitchStatement node) => null;
+
+  @override
+  R visitSymbolLiteral(SymbolLiteral node) => null;
+
+  @override
+  R visitThisExpression(ThisExpression node) => null;
+
+  @override
+  R visitThrowExpression(ThrowExpression node) => null;
+
+  @override
+  R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) => null;
+
+  @override
+  R visitTryStatement(TryStatement node) => null;
+
+  @override
+  R visitTypeArgumentList(TypeArgumentList node) => null;
+
+  @override
+  R visitTypeName(TypeName node) => null;
+
+  @override
+  R visitTypeParameter(TypeParameter node) => null;
+
+  @override
+  R visitTypeParameterList(TypeParameterList node) => null;
+
+  @override
+  R visitVariableDeclaration(VariableDeclaration node) => null;
+
+  @override
+  R visitVariableDeclarationList(VariableDeclarationList node) => null;
+
+  @override
+  R visitVariableDeclarationStatement(VariableDeclarationStatement node) =>
+      null;
+
+  @override
+  R visitWhileStatement(WhileStatement node) => null;
+
+  @override
+  R visitWithClause(WithClause node) => null;
+
+  @override
+  R visitYieldStatement(YieldStatement node) => null;
+}
+
+/**
+ * An AST visitor that will recursively visit all of the nodes in an AST
+ * structure (like instances of the class [RecursiveAstVisitor]). In addition,
+ * every node will also be visited by using a single unified [visitNode] method.
+ *
+ * Subclasses that override a visit method must either invoke the overridden
+ * visit method or explicitly invoke the more general [visitNode] method.
+ * Failure to do so will cause the children of the visited node to not be
+ * visited.
+ *
+ * Clients may extend or implement this class.
+ */
+class UnifyingAstVisitor<R> implements AstVisitor<R> {
+  @override
+  R visitAdjacentStrings(AdjacentStrings node) => visitNode(node);
+
+  @override
+  R visitAnnotation(Annotation node) => visitNode(node);
+
+  @override
+  R visitArgumentList(ArgumentList node) => visitNode(node);
+
+  @override
+  R visitAsExpression(AsExpression node) => visitNode(node);
+
+  @override
+  R visitAssertStatement(AssertStatement node) => visitNode(node);
+
+  @override
+  R visitAssignmentExpression(AssignmentExpression node) => visitNode(node);
+
+  @override
+  R visitAwaitExpression(AwaitExpression node) => visitNode(node);
+
+  @override
+  R visitBinaryExpression(BinaryExpression node) => visitNode(node);
+
+  @override
+  R visitBlock(Block node) => visitNode(node);
+
+  @override
+  R visitBlockFunctionBody(BlockFunctionBody node) => visitNode(node);
+
+  @override
+  R visitBooleanLiteral(BooleanLiteral node) => visitNode(node);
+
+  @override
+  R visitBreakStatement(BreakStatement node) => visitNode(node);
+
+  @override
+  R visitCascadeExpression(CascadeExpression node) => visitNode(node);
+
+  @override
+  R visitCatchClause(CatchClause node) => visitNode(node);
+
+  @override
+  R visitClassDeclaration(ClassDeclaration node) => visitNode(node);
+
+  @override
+  R visitClassTypeAlias(ClassTypeAlias node) => visitNode(node);
+
+  @override
+  R visitComment(Comment node) => visitNode(node);
+
+  @override
+  R visitCommentReference(CommentReference node) => visitNode(node);
+
+  @override
+  R visitCompilationUnit(CompilationUnit node) => visitNode(node);
+
+  @override
+  R visitConditionalExpression(ConditionalExpression node) => visitNode(node);
+
+  @override
+  R visitConfiguration(Configuration node) => visitNode(node);
+
+  @override
+  R visitConstructorDeclaration(ConstructorDeclaration node) => visitNode(node);
+
+  @override
+  R visitConstructorFieldInitializer(ConstructorFieldInitializer node) =>
+      visitNode(node);
+
+  @override
+  R visitConstructorName(ConstructorName node) => visitNode(node);
+
+  @override
+  R visitContinueStatement(ContinueStatement node) => visitNode(node);
+
+  @override
+  R visitDeclaredIdentifier(DeclaredIdentifier node) => visitNode(node);
+
+  @override
+  R visitDefaultFormalParameter(DefaultFormalParameter node) => visitNode(node);
+
+  @override
+  R visitDoStatement(DoStatement node) => visitNode(node);
+
+  @override
+  R visitDottedName(DottedName node) => visitNode(node);
+
+  @override
+  R visitDoubleLiteral(DoubleLiteral node) => visitNode(node);
+
+  @override
+  R visitEmptyFunctionBody(EmptyFunctionBody node) => visitNode(node);
+
+  @override
+  R visitEmptyStatement(EmptyStatement node) => visitNode(node);
+
+  @override
+  R visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
+      visitNode(node);
+
+  @override
+  R visitEnumDeclaration(EnumDeclaration node) => visitNode(node);
+
+  @override
+  R visitExportDirective(ExportDirective node) => visitNode(node);
+
+  @override
+  R visitExpressionFunctionBody(ExpressionFunctionBody node) => visitNode(node);
+
+  @override
+  R visitExpressionStatement(ExpressionStatement node) => visitNode(node);
+
+  @override
+  R visitExtendsClause(ExtendsClause node) => visitNode(node);
+
+  @override
+  R visitFieldDeclaration(FieldDeclaration node) => visitNode(node);
+
+  @override
+  R visitFieldFormalParameter(FieldFormalParameter node) => visitNode(node);
+
+  @override
+  R visitForEachStatement(ForEachStatement node) => visitNode(node);
+
+  @override
+  R visitFormalParameterList(FormalParameterList node) => visitNode(node);
+
+  @override
+  R visitForStatement(ForStatement node) => visitNode(node);
+
+  @override
+  R visitFunctionDeclaration(FunctionDeclaration node) => visitNode(node);
+
+  @override
+  R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) =>
+      visitNode(node);
+
+  @override
+  R visitFunctionExpression(FunctionExpression node) => visitNode(node);
+
+  @override
+  R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) =>
+      visitNode(node);
+
+  @override
+  R visitFunctionTypeAlias(FunctionTypeAlias node) => visitNode(node);
+
+  @override
+  R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) =>
+      visitNode(node);
+
+  @override
+  R visitHideCombinator(HideCombinator node) => visitNode(node);
+
+  @override
+  R visitIfStatement(IfStatement node) => visitNode(node);
+
+  @override
+  R visitImplementsClause(ImplementsClause node) => visitNode(node);
+
+  @override
+  R visitImportDirective(ImportDirective node) => visitNode(node);
+
+  @override
+  R visitIndexExpression(IndexExpression node) => visitNode(node);
+
+  @override
+  R visitInstanceCreationExpression(InstanceCreationExpression node) =>
+      visitNode(node);
+
+  @override
+  R visitIntegerLiteral(IntegerLiteral node) => visitNode(node);
+
+  @override
+  R visitInterpolationExpression(InterpolationExpression node) =>
+      visitNode(node);
+
+  @override
+  R visitInterpolationString(InterpolationString node) => visitNode(node);
+
+  @override
+  R visitIsExpression(IsExpression node) => visitNode(node);
+
+  @override
+  R visitLabel(Label node) => visitNode(node);
+
+  @override
+  R visitLabeledStatement(LabeledStatement node) => visitNode(node);
+
+  @override
+  R visitLibraryDirective(LibraryDirective node) => visitNode(node);
+
+  @override
+  R visitLibraryIdentifier(LibraryIdentifier node) => visitNode(node);
+
+  @override
+  R visitListLiteral(ListLiteral node) => visitNode(node);
+
+  @override
+  R visitMapLiteral(MapLiteral node) => visitNode(node);
+
+  @override
+  R visitMapLiteralEntry(MapLiteralEntry node) => visitNode(node);
+
+  @override
+  R visitMethodDeclaration(MethodDeclaration node) => visitNode(node);
+
+  @override
+  R visitMethodInvocation(MethodInvocation node) => visitNode(node);
+
+  @override
+  R visitNamedExpression(NamedExpression node) => visitNode(node);
+
+  @override
+  R visitNativeClause(NativeClause node) => visitNode(node);
+
+  @override
+  R visitNativeFunctionBody(NativeFunctionBody node) => visitNode(node);
+
+  R visitNode(AstNode node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R visitNullLiteral(NullLiteral node) => visitNode(node);
+
+  @override
+  R visitParenthesizedExpression(ParenthesizedExpression node) =>
+      visitNode(node);
+
+  @override
+  R visitPartDirective(PartDirective node) => visitNode(node);
+
+  @override
+  R visitPartOfDirective(PartOfDirective node) => visitNode(node);
+
+  @override
+  R visitPostfixExpression(PostfixExpression node) => visitNode(node);
+
+  @override
+  R visitPrefixedIdentifier(PrefixedIdentifier node) => visitNode(node);
+
+  @override
+  R visitPrefixExpression(PrefixExpression node) => visitNode(node);
+
+  @override
+  R visitPropertyAccess(PropertyAccess node) => visitNode(node);
+
+  @override
+  R visitRedirectingConstructorInvocation(
+          RedirectingConstructorInvocation node) =>
+      visitNode(node);
+
+  @override
+  R visitRethrowExpression(RethrowExpression node) => visitNode(node);
+
+  @override
+  R visitReturnStatement(ReturnStatement node) => visitNode(node);
+
+  @override
+  R visitScriptTag(ScriptTag scriptTag) => visitNode(scriptTag);
+
+  @override
+  R visitShowCombinator(ShowCombinator node) => visitNode(node);
+
+  @override
+  R visitSimpleFormalParameter(SimpleFormalParameter node) => visitNode(node);
+
+  @override
+  R visitSimpleIdentifier(SimpleIdentifier node) => visitNode(node);
+
+  @override
+  R visitSimpleStringLiteral(SimpleStringLiteral node) => visitNode(node);
+
+  @override
+  R visitStringInterpolation(StringInterpolation node) => visitNode(node);
+
+  @override
+  R visitSuperConstructorInvocation(SuperConstructorInvocation node) =>
+      visitNode(node);
+
+  @override
+  R visitSuperExpression(SuperExpression node) => visitNode(node);
+
+  @override
+  R visitSwitchCase(SwitchCase node) => visitNode(node);
+
+  @override
+  R visitSwitchDefault(SwitchDefault node) => visitNode(node);
+
+  @override
+  R visitSwitchStatement(SwitchStatement node) => visitNode(node);
+
+  @override
+  R visitSymbolLiteral(SymbolLiteral node) => visitNode(node);
+
+  @override
+  R visitThisExpression(ThisExpression node) => visitNode(node);
+
+  @override
+  R visitThrowExpression(ThrowExpression node) => visitNode(node);
+
+  @override
+  R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) =>
+      visitNode(node);
+
+  @override
+  R visitTryStatement(TryStatement node) => visitNode(node);
+
+  @override
+  R visitTypeArgumentList(TypeArgumentList node) => visitNode(node);
+
+  @override
+  R visitTypeName(TypeName node) => visitNode(node);
+
+  @override
+  R visitTypeParameter(TypeParameter node) => visitNode(node);
+
+  @override
+  R visitTypeParameterList(TypeParameterList node) => visitNode(node);
+
+  @override
+  R visitVariableDeclaration(VariableDeclaration node) => visitNode(node);
+
+  @override
+  R visitVariableDeclarationList(VariableDeclarationList node) =>
+      visitNode(node);
+
+  @override
+  R visitVariableDeclarationStatement(VariableDeclarationStatement node) =>
+      visitNode(node);
+
+  @override
+  R visitWhileStatement(WhileStatement node) => visitNode(node);
+
+  @override
+  R visitWithClause(WithClause node) => visitNode(node);
+
+  @override
+  R visitYieldStatement(YieldStatement node) => visitNode(node);
+}
+
+/**
+ * A helper class used to implement the correct order of visits for a
+ * [BreadthFirstVisitor].
+ */
+class _BreadthFirstChildVisitor extends UnifyingAstVisitor<Object> {
+  /**
+   * The [BreadthFirstVisitor] being helped by this visitor.
+   */
+  final BreadthFirstVisitor outerVisitor;
+
+  /**
+   * Initialize a newly created visitor to help the [outerVisitor].
+   */
+  _BreadthFirstChildVisitor(this.outerVisitor);
+
+  @override
+  Object visitNode(AstNode node) {
+    outerVisitor._queue.add(node);
+    return null;
+  }
+}
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index e0efffc..ab468ed 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -558,13 +558,6 @@
   String get displayName;
 
   /**
-   * Return the content of the documentation comment (including delimiters) for
-   * this element, or `null` if this element does not or cannot have
-   * documentation.
-   */
-  String get documentationComment;
-
-  /**
    * Return the source range of the documentation comment for this element,
    * or `null` if this element does not or cannot have a documentation.
    *
@@ -574,6 +567,13 @@
   SourceRange get docRange;
 
   /**
+   * Return the content of the documentation comment (including delimiters) for
+   * this element, or `null` if this element does not or cannot have
+   * documentation.
+   */
+  String get documentationComment;
+
+  /**
    * Return the element that either physically or logically encloses this
    * element. This will be `null` if this element is a library because libraries
    * are the top-level elements in the model.
@@ -1153,7 +1153,8 @@
  *
  * Clients may not extend, implement or mix-in this class.
  */
-abstract class FunctionTypeAliasElement implements FunctionTypedElement {
+abstract class FunctionTypeAliasElement
+    implements FunctionTypedElement, TypeDefiningElement {
   /**
    * An empty array of type alias elements.
    */
@@ -1177,8 +1178,7 @@
  *
  * Clients may not extend, implement or mix-in this class.
  */
-abstract class FunctionTypedElement
-    implements TypeDefiningElement, TypeParameterizedElement {
+abstract class FunctionTypedElement implements TypeParameterizedElement {
   /**
    * Return a list containing all of the parameters defined by this executable
    * element.
@@ -1192,7 +1192,9 @@
    */
   DartType get returnType;
 
-  @override
+  /**
+   * The type of this element, which will be a function type.
+   */
   FunctionType get type;
 }
 
diff --git a/pkg/analyzer/lib/source/error_processor.dart b/pkg/analyzer/lib/source/error_processor.dart
index b20716a..8e369aa 100644
--- a/pkg/analyzer/lib/source/error_processor.dart
+++ b/pkg/analyzer/lib/source/error_processor.dart
@@ -54,20 +54,16 @@
     }
   }
 
-  ErrorSeverity _toSeverity(String severity) {
-    switch (severity) {
-      case 'error':
-        return ErrorSeverity.ERROR;
-      case 'info':
-        return ErrorSeverity.INFO;
-      case 'warning':
-        return ErrorSeverity.WARNING;
-    }
-    return null;
-  }
-
+  ErrorSeverity _toSeverity(String severity) => severityMap[severity];
 }
 
+/// String identifiers mapped to associated severities.
+const Map<String, ErrorSeverity> severityMap = const {
+  'error': ErrorSeverity.ERROR,
+  'info': ErrorSeverity.INFO,
+  'warning': ErrorSeverity.WARNING
+};
+
 /// Process errors by filtering or changing associated [ErrorSeverity].
 class ErrorProcessor {
   /// The code name of the associated error.
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index c9604ef..ac3ace6 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -485,6 +485,31 @@
   }
 
   @override
+  bool aboutToComputeResult(CacheEntry entry, ResultDescriptor result) {
+    AnalysisTarget target = entry.target;
+    // TYPE_PROVIDER
+    if (target is AnalysisContextTarget && result == TYPE_PROVIDER) {
+      DartSdk dartSdk = sourceFactory.dartSdk;
+      if (dartSdk != null) {
+        AnalysisContext sdkContext = dartSdk.context;
+        if (!identical(sdkContext, this) &&
+            sdkContext is InternalAnalysisContext) {
+          return sdkContext.aboutToComputeResult(entry, result);
+        }
+      }
+    }
+    // A result for a Source.
+    Source source = target.source;
+    if (source != null) {
+      InternalAnalysisContext context = _cache.getContextFor(source);
+      if (!identical(context, this)) {
+        return context.aboutToComputeResult(entry, result);
+      }
+    }
+    return false;
+  }
+
+  @override
   void addListener(AnalysisListener listener) {
     if (!_listeners.contains(listener)) {
       _listeners.add(listener);
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
new file mode 100644
index 0000000..f0435eb
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -0,0 +1,6272 @@
+// 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.
+
+library analyzer.src.generated.ast;
+
+import 'dart:collection';
+
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
+import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/utilities_collection.dart' show TokenMap;
+import 'package:analyzer/src/generated/utilities_dart.dart';
+
+/**
+ * An AST visitor that will clone any AST structure that it visits. The cloner
+ * will only clone the structure, it will not preserve any resolution results or
+ * properties associated with the nodes.
+ */
+class AstCloner implements AstVisitor<AstNode> {
+  /**
+   * A flag indicating whether tokens should be cloned while cloning an AST
+   * structure.
+   */
+  final bool cloneTokens;
+
+  /**
+   * Initialize a newly created AST cloner to optionally clone tokens while
+   * cloning AST nodes if [cloneTokens] is `true`.
+   */
+  AstCloner(
+      [this.cloneTokens =
+          false]); // TODO(brianwilkerson) Change this to be a named parameter.
+
+  /**
+   * Return a clone of the given [node].
+   */
+  AstNode cloneNode(AstNode node) {
+    if (node == null) {
+      return null;
+    }
+    return node.accept(this) as AstNode;
+  }
+
+  /**
+   * Return a list containing cloned versions of the nodes in the given list of
+   * [nodes].
+   */
+  List<AstNode> cloneNodeList(NodeList nodes) {
+    int count = nodes.length;
+    List clonedNodes = new List();
+    for (int i = 0; i < count; i++) {
+      clonedNodes.add((nodes[i]).accept(this) as AstNode);
+    }
+    return clonedNodes;
+  }
+
+  /**
+   * Clone the given [token] if tokens are supposed to be cloned.
+   */
+  Token cloneToken(Token token) {
+    if (cloneTokens) {
+      return (token == null ? null : token.copy());
+    } else {
+      return token;
+    }
+  }
+
+  /**
+   * Clone the given [tokens] if tokens are supposed to be cloned.
+   */
+  List<Token> cloneTokenList(List<Token> tokens) {
+    if (cloneTokens) {
+      return tokens.map((Token token) => token.copy()).toList();
+    }
+    return tokens;
+  }
+
+  @override
+  AdjacentStrings visitAdjacentStrings(AdjacentStrings node) =>
+      new AdjacentStrings(cloneNodeList(node.strings));
+
+  @override
+  Annotation visitAnnotation(Annotation node) => new Annotation(
+      cloneToken(node.atSign),
+      cloneNode(node.name),
+      cloneToken(node.period),
+      cloneNode(node.constructorName),
+      cloneNode(node.arguments));
+
+  @override
+  ArgumentList visitArgumentList(ArgumentList node) => new ArgumentList(
+      cloneToken(node.leftParenthesis),
+      cloneNodeList(node.arguments),
+      cloneToken(node.rightParenthesis));
+
+  @override
+  AsExpression visitAsExpression(AsExpression node) => new AsExpression(
+      cloneNode(node.expression),
+      cloneToken(node.asOperator),
+      cloneNode(node.type));
+
+  @override
+  AstNode visitAssertStatement(AssertStatement node) => new AssertStatement(
+      cloneToken(node.assertKeyword),
+      cloneToken(node.leftParenthesis),
+      cloneNode(node.condition),
+      cloneToken(node.comma),
+      cloneNode(node.message),
+      cloneToken(node.rightParenthesis),
+      cloneToken(node.semicolon));
+
+  @override
+  AssignmentExpression visitAssignmentExpression(AssignmentExpression node) =>
+      new AssignmentExpression(cloneNode(node.leftHandSide),
+          cloneToken(node.operator), cloneNode(node.rightHandSide));
+
+  @override
+  AwaitExpression visitAwaitExpression(AwaitExpression node) =>
+      new AwaitExpression(
+          cloneToken(node.awaitKeyword), cloneNode(node.expression));
+
+  @override
+  BinaryExpression visitBinaryExpression(BinaryExpression node) =>
+      new BinaryExpression(cloneNode(node.leftOperand),
+          cloneToken(node.operator), cloneNode(node.rightOperand));
+
+  @override
+  Block visitBlock(Block node) => new Block(cloneToken(node.leftBracket),
+      cloneNodeList(node.statements), cloneToken(node.rightBracket));
+
+  @override
+  BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) =>
+      new BlockFunctionBody(cloneToken(node.keyword), cloneToken(node.star),
+          cloneNode(node.block));
+
+  @override
+  BooleanLiteral visitBooleanLiteral(BooleanLiteral node) =>
+      new BooleanLiteral(cloneToken(node.literal), node.value);
+
+  @override
+  BreakStatement visitBreakStatement(BreakStatement node) => new BreakStatement(
+      cloneToken(node.breakKeyword),
+      cloneNode(node.label),
+      cloneToken(node.semicolon));
+
+  @override
+  CascadeExpression visitCascadeExpression(CascadeExpression node) =>
+      new CascadeExpression(
+          cloneNode(node.target), cloneNodeList(node.cascadeSections));
+
+  @override
+  CatchClause visitCatchClause(CatchClause node) => new CatchClause(
+      cloneToken(node.onKeyword),
+      cloneNode(node.exceptionType),
+      cloneToken(node.catchKeyword),
+      cloneToken(node.leftParenthesis),
+      cloneNode(node.exceptionParameter),
+      cloneToken(node.comma),
+      cloneNode(node.stackTraceParameter),
+      cloneToken(node.rightParenthesis),
+      cloneNode(node.body));
+
+  @override
+  ClassDeclaration visitClassDeclaration(ClassDeclaration node) {
+    ClassDeclaration copy = new ClassDeclaration(
+        cloneNode(node.documentationComment),
+        cloneNodeList(node.metadata),
+        cloneToken(node.abstractKeyword),
+        cloneToken(node.classKeyword),
+        cloneNode(node.name),
+        cloneNode(node.typeParameters),
+        cloneNode(node.extendsClause),
+        cloneNode(node.withClause),
+        cloneNode(node.implementsClause),
+        cloneToken(node.leftBracket),
+        cloneNodeList(node.members),
+        cloneToken(node.rightBracket));
+    copy.nativeClause = cloneNode(node.nativeClause);
+    return copy;
+  }
+
+  @override
+  ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) => new ClassTypeAlias(
+      cloneNode(node.documentationComment),
+      cloneNodeList(node.metadata),
+      cloneToken(node.typedefKeyword),
+      cloneNode(node.name),
+      cloneNode(node.typeParameters),
+      cloneToken(node.equals),
+      cloneToken(node.abstractKeyword),
+      cloneNode(node.superclass),
+      cloneNode(node.withClause),
+      cloneNode(node.implementsClause),
+      cloneToken(node.semicolon));
+
+  @override
+  Comment visitComment(Comment node) {
+    if (node.isDocumentation) {
+      return Comment.createDocumentationCommentWithReferences(
+          cloneTokenList(node.tokens), cloneNodeList(node.references));
+    } else if (node.isBlock) {
+      return Comment.createBlockComment(cloneTokenList(node.tokens));
+    }
+    return Comment.createEndOfLineComment(cloneTokenList(node.tokens));
+  }
+
+  @override
+  CommentReference visitCommentReference(CommentReference node) =>
+      new CommentReference(
+          cloneToken(node.newKeyword), cloneNode(node.identifier));
+
+  @override
+  CompilationUnit visitCompilationUnit(CompilationUnit node) {
+    CompilationUnit clone = new CompilationUnit(
+        cloneToken(node.beginToken),
+        cloneNode(node.scriptTag),
+        cloneNodeList(node.directives),
+        cloneNodeList(node.declarations),
+        cloneToken(node.endToken));
+    clone.lineInfo = node.lineInfo;
+    return clone;
+  }
+
+  @override
+  ConditionalExpression visitConditionalExpression(
+          ConditionalExpression node) =>
+      new ConditionalExpression(
+          cloneNode(node.condition),
+          cloneToken(node.question),
+          cloneNode(node.thenExpression),
+          cloneToken(node.colon),
+          cloneNode(node.elseExpression));
+
+  @override
+  Configuration visitConfiguration(Configuration node) => new Configuration(
+      cloneToken(node.ifKeyword),
+      cloneToken(node.leftParenthesis),
+      cloneNode(node.name),
+      cloneToken(node.equalToken),
+      cloneNode(node.value),
+      cloneToken(node.rightParenthesis),
+      cloneNode(node.libraryUri));
+
+  @override
+  ConstructorDeclaration visitConstructorDeclaration(
+          ConstructorDeclaration node) =>
+      new ConstructorDeclaration(
+          cloneNode(node.documentationComment),
+          cloneNodeList(node.metadata),
+          cloneToken(node.externalKeyword),
+          cloneToken(node.constKeyword),
+          cloneToken(node.factoryKeyword),
+          cloneNode(node.returnType),
+          cloneToken(node.period),
+          cloneNode(node.name),
+          cloneNode(node.parameters),
+          cloneToken(node.separator),
+          cloneNodeList(node.initializers),
+          cloneNode(node.redirectedConstructor),
+          cloneNode(node.body));
+
+  @override
+  ConstructorFieldInitializer visitConstructorFieldInitializer(
+          ConstructorFieldInitializer node) =>
+      new ConstructorFieldInitializer(
+          cloneToken(node.thisKeyword),
+          cloneToken(node.period),
+          cloneNode(node.fieldName),
+          cloneToken(node.equals),
+          cloneNode(node.expression));
+
+  @override
+  ConstructorName visitConstructorName(ConstructorName node) =>
+      new ConstructorName(
+          cloneNode(node.type), cloneToken(node.period), cloneNode(node.name));
+
+  @override
+  ContinueStatement visitContinueStatement(ContinueStatement node) =>
+      new ContinueStatement(cloneToken(node.continueKeyword),
+          cloneNode(node.label), cloneToken(node.semicolon));
+
+  @override
+  DeclaredIdentifier visitDeclaredIdentifier(DeclaredIdentifier node) =>
+      new DeclaredIdentifier(
+          cloneNode(node.documentationComment),
+          cloneNodeList(node.metadata),
+          cloneToken(node.keyword),
+          cloneNode(node.type),
+          cloneNode(node.identifier));
+
+  @override
+  DefaultFormalParameter visitDefaultFormalParameter(
+          DefaultFormalParameter node) =>
+      new DefaultFormalParameter(cloneNode(node.parameter), node.kind,
+          cloneToken(node.separator), cloneNode(node.defaultValue));
+
+  @override
+  DoStatement visitDoStatement(DoStatement node) => new DoStatement(
+      cloneToken(node.doKeyword),
+      cloneNode(node.body),
+      cloneToken(node.whileKeyword),
+      cloneToken(node.leftParenthesis),
+      cloneNode(node.condition),
+      cloneToken(node.rightParenthesis),
+      cloneToken(node.semicolon));
+
+  @override
+  DottedName visitDottedName(DottedName node) =>
+      new DottedName(cloneNodeList(node.components));
+
+  @override
+  DoubleLiteral visitDoubleLiteral(DoubleLiteral node) =>
+      new DoubleLiteral(cloneToken(node.literal), node.value);
+
+  @override
+  EmptyFunctionBody visitEmptyFunctionBody(EmptyFunctionBody node) =>
+      new EmptyFunctionBody(cloneToken(node.semicolon));
+
+  @override
+  EmptyStatement visitEmptyStatement(EmptyStatement node) =>
+      new EmptyStatement(cloneToken(node.semicolon));
+
+  @override
+  AstNode visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
+      new EnumConstantDeclaration(cloneNode(node.documentationComment),
+          cloneNodeList(node.metadata), cloneNode(node.name));
+
+  @override
+  EnumDeclaration visitEnumDeclaration(EnumDeclaration node) =>
+      new EnumDeclaration(
+          cloneNode(node.documentationComment),
+          cloneNodeList(node.metadata),
+          cloneToken(node.enumKeyword),
+          cloneNode(node.name),
+          cloneToken(node.leftBracket),
+          cloneNodeList(node.constants),
+          cloneToken(node.rightBracket));
+
+  @override
+  ExportDirective visitExportDirective(ExportDirective node) {
+    ExportDirective directive = new ExportDirective(
+        cloneNode(node.documentationComment),
+        cloneNodeList(node.metadata),
+        cloneToken(node.keyword),
+        cloneNode(node.uri),
+        cloneNodeList(node.configurations),
+        cloneNodeList(node.combinators),
+        cloneToken(node.semicolon));
+    directive.source = node.source;
+    directive.uriContent = node.uriContent;
+    return directive;
+  }
+
+  @override
+  ExpressionFunctionBody visitExpressionFunctionBody(
+          ExpressionFunctionBody node) =>
+      new ExpressionFunctionBody(
+          cloneToken(node.keyword),
+          cloneToken(node.functionDefinition),
+          cloneNode(node.expression),
+          cloneToken(node.semicolon));
+
+  @override
+  ExpressionStatement visitExpressionStatement(ExpressionStatement node) =>
+      new ExpressionStatement(
+          cloneNode(node.expression), cloneToken(node.semicolon));
+
+  @override
+  ExtendsClause visitExtendsClause(ExtendsClause node) => new ExtendsClause(
+      cloneToken(node.extendsKeyword), cloneNode(node.superclass));
+
+  @override
+  FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
+      new FieldDeclaration(
+          cloneNode(node.documentationComment),
+          cloneNodeList(node.metadata),
+          cloneToken(node.staticKeyword),
+          cloneNode(node.fields),
+          cloneToken(node.semicolon));
+
+  @override
+  FieldFormalParameter visitFieldFormalParameter(FieldFormalParameter node) =>
+      new FieldFormalParameter(
+          cloneNode(node.documentationComment),
+          cloneNodeList(node.metadata),
+          cloneToken(node.keyword),
+          cloneNode(node.type),
+          cloneToken(node.thisKeyword),
+          cloneToken(node.period),
+          cloneNode(node.identifier),
+          cloneNode(node.typeParameters),
+          cloneNode(node.parameters));
+
+  @override
+  ForEachStatement visitForEachStatement(ForEachStatement node) {
+    DeclaredIdentifier loopVariable = node.loopVariable;
+    if (loopVariable == null) {
+      return new ForEachStatement.withReference(
+          cloneToken(node.awaitKeyword),
+          cloneToken(node.forKeyword),
+          cloneToken(node.leftParenthesis),
+          cloneNode(node.identifier),
+          cloneToken(node.inKeyword),
+          cloneNode(node.iterable),
+          cloneToken(node.rightParenthesis),
+          cloneNode(node.body));
+    }
+    return new ForEachStatement.withDeclaration(
+        cloneToken(node.awaitKeyword),
+        cloneToken(node.forKeyword),
+        cloneToken(node.leftParenthesis),
+        cloneNode(loopVariable),
+        cloneToken(node.inKeyword),
+        cloneNode(node.iterable),
+        cloneToken(node.rightParenthesis),
+        cloneNode(node.body));
+  }
+
+  @override
+  FormalParameterList visitFormalParameterList(FormalParameterList node) =>
+      new FormalParameterList(
+          cloneToken(node.leftParenthesis),
+          cloneNodeList(node.parameters),
+          cloneToken(node.leftDelimiter),
+          cloneToken(node.rightDelimiter),
+          cloneToken(node.rightParenthesis));
+
+  @override
+  ForStatement visitForStatement(ForStatement node) => new ForStatement(
+      cloneToken(node.forKeyword),
+      cloneToken(node.leftParenthesis),
+      cloneNode(node.variables),
+      cloneNode(node.initialization),
+      cloneToken(node.leftSeparator),
+      cloneNode(node.condition),
+      cloneToken(node.rightSeparator),
+      cloneNodeList(node.updaters),
+      cloneToken(node.rightParenthesis),
+      cloneNode(node.body));
+
+  @override
+  FunctionDeclaration visitFunctionDeclaration(FunctionDeclaration node) =>
+      new FunctionDeclaration(
+          cloneNode(node.documentationComment),
+          cloneNodeList(node.metadata),
+          cloneToken(node.externalKeyword),
+          cloneNode(node.returnType),
+          cloneToken(node.propertyKeyword),
+          cloneNode(node.name),
+          cloneNode(node.functionExpression));
+
+  @override
+  FunctionDeclarationStatement visitFunctionDeclarationStatement(
+          FunctionDeclarationStatement node) =>
+      new FunctionDeclarationStatement(cloneNode(node.functionDeclaration));
+
+  @override
+  FunctionExpression visitFunctionExpression(FunctionExpression node) =>
+      new FunctionExpression(cloneNode(node.typeParameters),
+          cloneNode(node.parameters), cloneNode(node.body));
+
+  @override
+  FunctionExpressionInvocation visitFunctionExpressionInvocation(
+          FunctionExpressionInvocation node) =>
+      new FunctionExpressionInvocation(cloneNode(node.function),
+          cloneNode(node.typeArguments), cloneNode(node.argumentList));
+
+  @override
+  FunctionTypeAlias visitFunctionTypeAlias(FunctionTypeAlias node) =>
+      new FunctionTypeAlias(
+          cloneNode(node.documentationComment),
+          cloneNodeList(node.metadata),
+          cloneToken(node.typedefKeyword),
+          cloneNode(node.returnType),
+          cloneNode(node.name),
+          cloneNode(node.typeParameters),
+          cloneNode(node.parameters),
+          cloneToken(node.semicolon));
+
+  @override
+  FunctionTypedFormalParameter visitFunctionTypedFormalParameter(
+          FunctionTypedFormalParameter node) =>
+      new FunctionTypedFormalParameter(
+          cloneNode(node.documentationComment),
+          cloneNodeList(node.metadata),
+          cloneNode(node.returnType),
+          cloneNode(node.identifier),
+          cloneNode(node.typeParameters),
+          cloneNode(node.parameters));
+
+  @override
+  HideCombinator visitHideCombinator(HideCombinator node) => new HideCombinator(
+      cloneToken(node.keyword), cloneNodeList(node.hiddenNames));
+
+  @override
+  IfStatement visitIfStatement(IfStatement node) => new IfStatement(
+      cloneToken(node.ifKeyword),
+      cloneToken(node.leftParenthesis),
+      cloneNode(node.condition),
+      cloneToken(node.rightParenthesis),
+      cloneNode(node.thenStatement),
+      cloneToken(node.elseKeyword),
+      cloneNode(node.elseStatement));
+
+  @override
+  ImplementsClause visitImplementsClause(ImplementsClause node) =>
+      new ImplementsClause(
+          cloneToken(node.implementsKeyword), cloneNodeList(node.interfaces));
+
+  @override
+  ImportDirective visitImportDirective(ImportDirective node) {
+    ImportDirective directive = new ImportDirective(
+        cloneNode(node.documentationComment),
+        cloneNodeList(node.metadata),
+        cloneToken(node.keyword),
+        cloneNode(node.uri),
+        cloneNodeList(node.configurations),
+        cloneToken(node.deferredKeyword),
+        cloneToken(node.asKeyword),
+        cloneNode(node.prefix),
+        cloneNodeList(node.combinators),
+        cloneToken(node.semicolon));
+    directive.source = node.source;
+    directive.uriContent = node.uriContent;
+    return directive;
+  }
+
+  @override
+  IndexExpression visitIndexExpression(IndexExpression node) {
+    Token period = node.period;
+    if (period == null) {
+      return new IndexExpression.forTarget(
+          cloneNode(node.target),
+          cloneToken(node.leftBracket),
+          cloneNode(node.index),
+          cloneToken(node.rightBracket));
+    } else {
+      return new IndexExpression.forCascade(
+          cloneToken(period),
+          cloneToken(node.leftBracket),
+          cloneNode(node.index),
+          cloneToken(node.rightBracket));
+    }
+  }
+
+  @override
+  InstanceCreationExpression visitInstanceCreationExpression(
+          InstanceCreationExpression node) =>
+      new InstanceCreationExpression(cloneToken(node.keyword),
+          cloneNode(node.constructorName), cloneNode(node.argumentList));
+
+  @override
+  IntegerLiteral visitIntegerLiteral(IntegerLiteral node) =>
+      new IntegerLiteral(cloneToken(node.literal), node.value);
+
+  @override
+  InterpolationExpression visitInterpolationExpression(
+          InterpolationExpression node) =>
+      new InterpolationExpression(cloneToken(node.leftBracket),
+          cloneNode(node.expression), cloneToken(node.rightBracket));
+
+  @override
+  InterpolationString visitInterpolationString(InterpolationString node) =>
+      new InterpolationString(cloneToken(node.contents), node.value);
+
+  @override
+  IsExpression visitIsExpression(IsExpression node) => new IsExpression(
+      cloneNode(node.expression),
+      cloneToken(node.isOperator),
+      cloneToken(node.notOperator),
+      cloneNode(node.type));
+
+  @override
+  Label visitLabel(Label node) =>
+      new Label(cloneNode(node.label), cloneToken(node.colon));
+
+  @override
+  LabeledStatement visitLabeledStatement(LabeledStatement node) =>
+      new LabeledStatement(
+          cloneNodeList(node.labels), cloneNode(node.statement));
+
+  @override
+  LibraryDirective visitLibraryDirective(LibraryDirective node) =>
+      new LibraryDirective(
+          cloneNode(node.documentationComment),
+          cloneNodeList(node.metadata),
+          cloneToken(node.libraryKeyword),
+          cloneNode(node.name),
+          cloneToken(node.semicolon));
+
+  @override
+  LibraryIdentifier visitLibraryIdentifier(LibraryIdentifier node) =>
+      new LibraryIdentifier(cloneNodeList(node.components));
+
+  @override
+  ListLiteral visitListLiteral(ListLiteral node) => new ListLiteral(
+      cloneToken(node.constKeyword),
+      cloneNode(node.typeArguments),
+      cloneToken(node.leftBracket),
+      cloneNodeList(node.elements),
+      cloneToken(node.rightBracket));
+
+  @override
+  MapLiteral visitMapLiteral(MapLiteral node) => new MapLiteral(
+      cloneToken(node.constKeyword),
+      cloneNode(node.typeArguments),
+      cloneToken(node.leftBracket),
+      cloneNodeList(node.entries),
+      cloneToken(node.rightBracket));
+
+  @override
+  MapLiteralEntry visitMapLiteralEntry(MapLiteralEntry node) =>
+      new MapLiteralEntry(cloneNode(node.key), cloneToken(node.separator),
+          cloneNode(node.value));
+
+  @override
+  MethodDeclaration visitMethodDeclaration(MethodDeclaration node) =>
+      new MethodDeclaration(
+          cloneNode(node.documentationComment),
+          cloneNodeList(node.metadata),
+          cloneToken(node.externalKeyword),
+          cloneToken(node.modifierKeyword),
+          cloneNode(node.returnType),
+          cloneToken(node.propertyKeyword),
+          cloneToken(node.operatorKeyword),
+          cloneNode(node.name),
+          cloneNode(node.typeParameters),
+          cloneNode(node.parameters),
+          cloneNode(node.body));
+
+  @override
+  MethodInvocation visitMethodInvocation(MethodInvocation node) =>
+      new MethodInvocation(
+          cloneNode(node.target),
+          cloneToken(node.operator),
+          cloneNode(node.methodName),
+          cloneNode(node.typeArguments),
+          cloneNode(node.argumentList));
+
+  @override
+  NamedExpression visitNamedExpression(NamedExpression node) =>
+      new NamedExpression(cloneNode(node.name), cloneNode(node.expression));
+
+  @override
+  AstNode visitNativeClause(NativeClause node) =>
+      new NativeClause(cloneToken(node.nativeKeyword), cloneNode(node.name));
+
+  @override
+  NativeFunctionBody visitNativeFunctionBody(NativeFunctionBody node) =>
+      new NativeFunctionBody(cloneToken(node.nativeKeyword),
+          cloneNode(node.stringLiteral), cloneToken(node.semicolon));
+
+  @override
+  NullLiteral visitNullLiteral(NullLiteral node) =>
+      new NullLiteral(cloneToken(node.literal));
+
+  @override
+  ParenthesizedExpression visitParenthesizedExpression(
+          ParenthesizedExpression node) =>
+      new ParenthesizedExpression(cloneToken(node.leftParenthesis),
+          cloneNode(node.expression), cloneToken(node.rightParenthesis));
+
+  @override
+  PartDirective visitPartDirective(PartDirective node) {
+    PartDirective directive = new PartDirective(
+        cloneNode(node.documentationComment),
+        cloneNodeList(node.metadata),
+        cloneToken(node.partKeyword),
+        cloneNode(node.uri),
+        cloneToken(node.semicolon));
+    directive.source = node.source;
+    directive.uriContent = node.uriContent;
+    return directive;
+  }
+
+  @override
+  PartOfDirective visitPartOfDirective(PartOfDirective node) =>
+      new PartOfDirective(
+          cloneNode(node.documentationComment),
+          cloneNodeList(node.metadata),
+          cloneToken(node.partKeyword),
+          cloneToken(node.ofKeyword),
+          cloneNode(node.libraryName),
+          cloneToken(node.semicolon));
+
+  @override
+  PostfixExpression visitPostfixExpression(PostfixExpression node) =>
+      new PostfixExpression(cloneNode(node.operand), cloneToken(node.operator));
+
+  @override
+  PrefixedIdentifier visitPrefixedIdentifier(PrefixedIdentifier node) =>
+      new PrefixedIdentifier(cloneNode(node.prefix), cloneToken(node.period),
+          cloneNode(node.identifier));
+
+  @override
+  PrefixExpression visitPrefixExpression(PrefixExpression node) =>
+      new PrefixExpression(cloneToken(node.operator), cloneNode(node.operand));
+
+  @override
+  PropertyAccess visitPropertyAccess(PropertyAccess node) => new PropertyAccess(
+      cloneNode(node.target),
+      cloneToken(node.operator),
+      cloneNode(node.propertyName));
+
+  @override
+  RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
+          RedirectingConstructorInvocation node) =>
+      new RedirectingConstructorInvocation(
+          cloneToken(node.thisKeyword),
+          cloneToken(node.period),
+          cloneNode(node.constructorName),
+          cloneNode(node.argumentList));
+
+  @override
+  RethrowExpression visitRethrowExpression(RethrowExpression node) =>
+      new RethrowExpression(cloneToken(node.rethrowKeyword));
+
+  @override
+  ReturnStatement visitReturnStatement(ReturnStatement node) =>
+      new ReturnStatement(cloneToken(node.returnKeyword),
+          cloneNode(node.expression), cloneToken(node.semicolon));
+
+  @override
+  ScriptTag visitScriptTag(ScriptTag node) =>
+      new ScriptTag(cloneToken(node.scriptTag));
+
+  @override
+  ShowCombinator visitShowCombinator(ShowCombinator node) => new ShowCombinator(
+      cloneToken(node.keyword), cloneNodeList(node.shownNames));
+
+  @override
+  SimpleFormalParameter visitSimpleFormalParameter(
+          SimpleFormalParameter node) =>
+      new SimpleFormalParameter(
+          cloneNode(node.documentationComment),
+          cloneNodeList(node.metadata),
+          cloneToken(node.keyword),
+          cloneNode(node.type),
+          cloneNode(node.identifier));
+
+  @override
+  SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) =>
+      new SimpleIdentifier(cloneToken(node.token));
+
+  @override
+  SimpleStringLiteral visitSimpleStringLiteral(SimpleStringLiteral node) =>
+      new SimpleStringLiteral(cloneToken(node.literal), node.value);
+
+  @override
+  StringInterpolation visitStringInterpolation(StringInterpolation node) =>
+      new StringInterpolation(cloneNodeList(node.elements));
+
+  @override
+  SuperConstructorInvocation visitSuperConstructorInvocation(
+          SuperConstructorInvocation node) =>
+      new SuperConstructorInvocation(
+          cloneToken(node.superKeyword),
+          cloneToken(node.period),
+          cloneNode(node.constructorName),
+          cloneNode(node.argumentList));
+
+  @override
+  SuperExpression visitSuperExpression(SuperExpression node) =>
+      new SuperExpression(cloneToken(node.superKeyword));
+
+  @override
+  SwitchCase visitSwitchCase(SwitchCase node) => new SwitchCase(
+      cloneNodeList(node.labels),
+      cloneToken(node.keyword),
+      cloneNode(node.expression),
+      cloneToken(node.colon),
+      cloneNodeList(node.statements));
+
+  @override
+  SwitchDefault visitSwitchDefault(SwitchDefault node) => new SwitchDefault(
+      cloneNodeList(node.labels),
+      cloneToken(node.keyword),
+      cloneToken(node.colon),
+      cloneNodeList(node.statements));
+
+  @override
+  SwitchStatement visitSwitchStatement(SwitchStatement node) =>
+      new SwitchStatement(
+          cloneToken(node.switchKeyword),
+          cloneToken(node.leftParenthesis),
+          cloneNode(node.expression),
+          cloneToken(node.rightParenthesis),
+          cloneToken(node.leftBracket),
+          cloneNodeList(node.members),
+          cloneToken(node.rightBracket));
+
+  @override
+  SymbolLiteral visitSymbolLiteral(SymbolLiteral node) => new SymbolLiteral(
+      cloneToken(node.poundSign), cloneTokenList(node.components));
+
+  @override
+  ThisExpression visitThisExpression(ThisExpression node) =>
+      new ThisExpression(cloneToken(node.thisKeyword));
+
+  @override
+  ThrowExpression visitThrowExpression(ThrowExpression node) =>
+      new ThrowExpression(
+          cloneToken(node.throwKeyword), cloneNode(node.expression));
+
+  @override
+  TopLevelVariableDeclaration visitTopLevelVariableDeclaration(
+          TopLevelVariableDeclaration node) =>
+      new TopLevelVariableDeclaration(
+          cloneNode(node.documentationComment),
+          cloneNodeList(node.metadata),
+          cloneNode(node.variables),
+          cloneToken(node.semicolon));
+
+  @override
+  TryStatement visitTryStatement(TryStatement node) => new TryStatement(
+      cloneToken(node.tryKeyword),
+      cloneNode(node.body),
+      cloneNodeList(node.catchClauses),
+      cloneToken(node.finallyKeyword),
+      cloneNode(node.finallyBlock));
+
+  @override
+  TypeArgumentList visitTypeArgumentList(TypeArgumentList node) =>
+      new TypeArgumentList(cloneToken(node.leftBracket),
+          cloneNodeList(node.arguments), cloneToken(node.rightBracket));
+
+  @override
+  TypeName visitTypeName(TypeName node) =>
+      new TypeName(cloneNode(node.name), cloneNode(node.typeArguments));
+
+  @override
+  TypeParameter visitTypeParameter(TypeParameter node) => new TypeParameter(
+      cloneNode(node.documentationComment),
+      cloneNodeList(node.metadata),
+      cloneNode(node.name),
+      cloneToken(node.extendsKeyword),
+      cloneNode(node.bound));
+
+  @override
+  TypeParameterList visitTypeParameterList(TypeParameterList node) =>
+      new TypeParameterList(cloneToken(node.leftBracket),
+          cloneNodeList(node.typeParameters), cloneToken(node.rightBracket));
+
+  @override
+  VariableDeclaration visitVariableDeclaration(VariableDeclaration node) =>
+      new VariableDeclaration(cloneNode(node.name), cloneToken(node.equals),
+          cloneNode(node.initializer));
+
+  @override
+  VariableDeclarationList visitVariableDeclarationList(
+          VariableDeclarationList node) =>
+      new VariableDeclarationList(
+          cloneNode(node.documentationComment),
+          cloneNodeList(node.metadata),
+          cloneToken(node.keyword),
+          cloneNode(node.type),
+          cloneNodeList(node.variables));
+
+  @override
+  VariableDeclarationStatement visitVariableDeclarationStatement(
+          VariableDeclarationStatement node) =>
+      new VariableDeclarationStatement(
+          cloneNode(node.variables), cloneToken(node.semicolon));
+
+  @override
+  WhileStatement visitWhileStatement(WhileStatement node) => new WhileStatement(
+      cloneToken(node.whileKeyword),
+      cloneToken(node.leftParenthesis),
+      cloneNode(node.condition),
+      cloneToken(node.rightParenthesis),
+      cloneNode(node.body));
+
+  @override
+  WithClause visitWithClause(WithClause node) => new WithClause(
+      cloneToken(node.withKeyword), cloneNodeList(node.mixinTypes));
+
+  @override
+  YieldStatement visitYieldStatement(YieldStatement node) => new YieldStatement(
+      cloneToken(node.yieldKeyword),
+      cloneToken(node.star),
+      cloneNode(node.expression),
+      cloneToken(node.semicolon));
+
+  /**
+   * Return a clone of the given [node].
+   */
+  static AstNode clone(AstNode node) {
+    return node.accept(new AstCloner());
+  }
+}
+
+/**
+ * An AstVisitor that compares the structure of two AstNodes to see whether they
+ * are equal.
+ */
+class AstComparator implements AstVisitor<bool> {
+  /**
+   * The AST node with which the node being visited is to be compared. This is
+   * only valid at the beginning of each visit method (until [isEqualNodes] is
+   * invoked).
+   */
+  AstNode _other;
+
+  /**
+   * Return `true` if the [first] node and the [second] node have the same
+   * structure.
+   *
+   * *Note:* This method is only visible for testing purposes and should not be
+   * used by clients.
+   */
+  bool isEqualNodes(AstNode first, AstNode second) {
+    if (first == null) {
+      return second == null;
+    } else if (second == null) {
+      return false;
+    } else if (first.runtimeType != second.runtimeType) {
+      return false;
+    }
+    _other = second;
+    return first.accept(this);
+  }
+
+  /**
+   * Return `true` if the [first] token and the [second] token have the same
+   * structure.
+   *
+   * *Note:* This method is only visible for testing purposes and should not be
+   * used by clients.
+   */
+  bool isEqualTokens(Token first, Token second) {
+    if (first == null) {
+      return second == null;
+    } else if (second == null) {
+      return false;
+    } else if (identical(first, second)) {
+      return true;
+    }
+    return first.offset == second.offset &&
+        first.length == second.length &&
+        first.lexeme == second.lexeme;
+  }
+
+  @override
+  bool visitAdjacentStrings(AdjacentStrings node) {
+    AdjacentStrings other = _other as AdjacentStrings;
+    return _isEqualNodeLists(node.strings, other.strings);
+  }
+
+  @override
+  bool visitAnnotation(Annotation node) {
+    Annotation other = _other as Annotation;
+    return isEqualTokens(node.atSign, other.atSign) &&
+        isEqualNodes(node.name, other.name) &&
+        isEqualTokens(node.period, other.period) &&
+        isEqualNodes(node.constructorName, other.constructorName) &&
+        isEqualNodes(node.arguments, other.arguments);
+  }
+
+  @override
+  bool visitArgumentList(ArgumentList node) {
+    ArgumentList other = _other as ArgumentList;
+    return isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+        _isEqualNodeLists(node.arguments, other.arguments) &&
+        isEqualTokens(node.rightParenthesis, other.rightParenthesis);
+  }
+
+  @override
+  bool visitAsExpression(AsExpression node) {
+    AsExpression other = _other as AsExpression;
+    return isEqualNodes(node.expression, other.expression) &&
+        isEqualTokens(node.asOperator, other.asOperator) &&
+        isEqualNodes(node.type, other.type);
+  }
+
+  @override
+  bool visitAssertStatement(AssertStatement node) {
+    AssertStatement other = _other as AssertStatement;
+    return isEqualTokens(node.assertKeyword, other.assertKeyword) &&
+        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+        isEqualNodes(node.condition, other.condition) &&
+        isEqualTokens(node.comma, other.comma) &&
+        isEqualNodes(node.message, other.message) &&
+        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitAssignmentExpression(AssignmentExpression node) {
+    AssignmentExpression other = _other as AssignmentExpression;
+    return isEqualNodes(node.leftHandSide, other.leftHandSide) &&
+        isEqualTokens(node.operator, other.operator) &&
+        isEqualNodes(node.rightHandSide, other.rightHandSide);
+  }
+
+  @override
+  bool visitAwaitExpression(AwaitExpression node) {
+    AwaitExpression other = _other as AwaitExpression;
+    return isEqualTokens(node.awaitKeyword, other.awaitKeyword) &&
+        isEqualNodes(node.expression, other.expression);
+  }
+
+  @override
+  bool visitBinaryExpression(BinaryExpression node) {
+    BinaryExpression other = _other as BinaryExpression;
+    return isEqualNodes(node.leftOperand, other.leftOperand) &&
+        isEqualTokens(node.operator, other.operator) &&
+        isEqualNodes(node.rightOperand, other.rightOperand);
+  }
+
+  @override
+  bool visitBlock(Block node) {
+    Block other = _other as Block;
+    return isEqualTokens(node.leftBracket, other.leftBracket) &&
+        _isEqualNodeLists(node.statements, other.statements) &&
+        isEqualTokens(node.rightBracket, other.rightBracket);
+  }
+
+  @override
+  bool visitBlockFunctionBody(BlockFunctionBody node) {
+    BlockFunctionBody other = _other as BlockFunctionBody;
+    return isEqualNodes(node.block, other.block);
+  }
+
+  @override
+  bool visitBooleanLiteral(BooleanLiteral node) {
+    BooleanLiteral other = _other as BooleanLiteral;
+    return isEqualTokens(node.literal, other.literal) &&
+        node.value == other.value;
+  }
+
+  @override
+  bool visitBreakStatement(BreakStatement node) {
+    BreakStatement other = _other as BreakStatement;
+    return isEqualTokens(node.breakKeyword, other.breakKeyword) &&
+        isEqualNodes(node.label, other.label) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitCascadeExpression(CascadeExpression node) {
+    CascadeExpression other = _other as CascadeExpression;
+    return isEqualNodes(node.target, other.target) &&
+        _isEqualNodeLists(node.cascadeSections, other.cascadeSections);
+  }
+
+  @override
+  bool visitCatchClause(CatchClause node) {
+    CatchClause other = _other as CatchClause;
+    return isEqualTokens(node.onKeyword, other.onKeyword) &&
+        isEqualNodes(node.exceptionType, other.exceptionType) &&
+        isEqualTokens(node.catchKeyword, other.catchKeyword) &&
+        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+        isEqualNodes(node.exceptionParameter, other.exceptionParameter) &&
+        isEqualTokens(node.comma, other.comma) &&
+        isEqualNodes(node.stackTraceParameter, other.stackTraceParameter) &&
+        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+        isEqualNodes(node.body, other.body);
+  }
+
+  @override
+  bool visitClassDeclaration(ClassDeclaration node) {
+    ClassDeclaration other = _other as ClassDeclaration;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.abstractKeyword, other.abstractKeyword) &&
+        isEqualTokens(node.classKeyword, other.classKeyword) &&
+        isEqualNodes(node.name, other.name) &&
+        isEqualNodes(node.typeParameters, other.typeParameters) &&
+        isEqualNodes(node.extendsClause, other.extendsClause) &&
+        isEqualNodes(node.withClause, other.withClause) &&
+        isEqualNodes(node.implementsClause, other.implementsClause) &&
+        isEqualTokens(node.leftBracket, other.leftBracket) &&
+        _isEqualNodeLists(node.members, other.members) &&
+        isEqualTokens(node.rightBracket, other.rightBracket);
+  }
+
+  @override
+  bool visitClassTypeAlias(ClassTypeAlias node) {
+    ClassTypeAlias other = _other as ClassTypeAlias;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.typedefKeyword, other.typedefKeyword) &&
+        isEqualNodes(node.name, other.name) &&
+        isEqualNodes(node.typeParameters, other.typeParameters) &&
+        isEqualTokens(node.equals, other.equals) &&
+        isEqualTokens(node.abstractKeyword, other.abstractKeyword) &&
+        isEqualNodes(node.superclass, other.superclass) &&
+        isEqualNodes(node.withClause, other.withClause) &&
+        isEqualNodes(node.implementsClause, other.implementsClause) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitComment(Comment node) {
+    Comment other = _other as Comment;
+    return _isEqualNodeLists(node.references, other.references);
+  }
+
+  @override
+  bool visitCommentReference(CommentReference node) {
+    CommentReference other = _other as CommentReference;
+    return isEqualTokens(node.newKeyword, other.newKeyword) &&
+        isEqualNodes(node.identifier, other.identifier);
+  }
+
+  @override
+  bool visitCompilationUnit(CompilationUnit node) {
+    CompilationUnit other = _other as CompilationUnit;
+    return isEqualTokens(node.beginToken, other.beginToken) &&
+        isEqualNodes(node.scriptTag, other.scriptTag) &&
+        _isEqualNodeLists(node.directives, other.directives) &&
+        _isEqualNodeLists(node.declarations, other.declarations) &&
+        isEqualTokens(node.endToken, other.endToken);
+  }
+
+  @override
+  bool visitConditionalExpression(ConditionalExpression node) {
+    ConditionalExpression other = _other as ConditionalExpression;
+    return isEqualNodes(node.condition, other.condition) &&
+        isEqualTokens(node.question, other.question) &&
+        isEqualNodes(node.thenExpression, other.thenExpression) &&
+        isEqualTokens(node.colon, other.colon) &&
+        isEqualNodes(node.elseExpression, other.elseExpression);
+  }
+
+  @override
+  bool visitConfiguration(Configuration node) {
+    Configuration other = _other as Configuration;
+    return isEqualTokens(node.ifKeyword, other.ifKeyword) &&
+        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+        isEqualNodes(node.name, other.name) &&
+        isEqualTokens(node.equalToken, other.equalToken) &&
+        isEqualNodes(node.value, other.value) &&
+        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+        isEqualNodes(node.libraryUri, other.libraryUri);
+  }
+
+  @override
+  bool visitConstructorDeclaration(ConstructorDeclaration node) {
+    ConstructorDeclaration other = _other as ConstructorDeclaration;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.externalKeyword, other.externalKeyword) &&
+        isEqualTokens(node.constKeyword, other.constKeyword) &&
+        isEqualTokens(node.factoryKeyword, other.factoryKeyword) &&
+        isEqualNodes(node.returnType, other.returnType) &&
+        isEqualTokens(node.period, other.period) &&
+        isEqualNodes(node.name, other.name) &&
+        isEqualNodes(node.parameters, other.parameters) &&
+        isEqualTokens(node.separator, other.separator) &&
+        _isEqualNodeLists(node.initializers, other.initializers) &&
+        isEqualNodes(node.redirectedConstructor, other.redirectedConstructor) &&
+        isEqualNodes(node.body, other.body);
+  }
+
+  @override
+  bool visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+    ConstructorFieldInitializer other = _other as ConstructorFieldInitializer;
+    return isEqualTokens(node.thisKeyword, other.thisKeyword) &&
+        isEqualTokens(node.period, other.period) &&
+        isEqualNodes(node.fieldName, other.fieldName) &&
+        isEqualTokens(node.equals, other.equals) &&
+        isEqualNodes(node.expression, other.expression);
+  }
+
+  @override
+  bool visitConstructorName(ConstructorName node) {
+    ConstructorName other = _other as ConstructorName;
+    return isEqualNodes(node.type, other.type) &&
+        isEqualTokens(node.period, other.period) &&
+        isEqualNodes(node.name, other.name);
+  }
+
+  @override
+  bool visitContinueStatement(ContinueStatement node) {
+    ContinueStatement other = _other as ContinueStatement;
+    return isEqualTokens(node.continueKeyword, other.continueKeyword) &&
+        isEqualNodes(node.label, other.label) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitDeclaredIdentifier(DeclaredIdentifier node) {
+    DeclaredIdentifier other = _other as DeclaredIdentifier;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.keyword, other.keyword) &&
+        isEqualNodes(node.type, other.type) &&
+        isEqualNodes(node.identifier, other.identifier);
+  }
+
+  @override
+  bool visitDefaultFormalParameter(DefaultFormalParameter node) {
+    DefaultFormalParameter other = _other as DefaultFormalParameter;
+    return isEqualNodes(node.parameter, other.parameter) &&
+        node.kind == other.kind &&
+        isEqualTokens(node.separator, other.separator) &&
+        isEqualNodes(node.defaultValue, other.defaultValue);
+  }
+
+  @override
+  bool visitDoStatement(DoStatement node) {
+    DoStatement other = _other as DoStatement;
+    return isEqualTokens(node.doKeyword, other.doKeyword) &&
+        isEqualNodes(node.body, other.body) &&
+        isEqualTokens(node.whileKeyword, other.whileKeyword) &&
+        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+        isEqualNodes(node.condition, other.condition) &&
+        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitDottedName(DottedName node) {
+    DottedName other = _other as DottedName;
+    return _isEqualNodeLists(node.components, other.components);
+  }
+
+  @override
+  bool visitDoubleLiteral(DoubleLiteral node) {
+    DoubleLiteral other = _other as DoubleLiteral;
+    return isEqualTokens(node.literal, other.literal) &&
+        node.value == other.value;
+  }
+
+  @override
+  bool visitEmptyFunctionBody(EmptyFunctionBody node) {
+    EmptyFunctionBody other = _other as EmptyFunctionBody;
+    return isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitEmptyStatement(EmptyStatement node) {
+    EmptyStatement other = _other as EmptyStatement;
+    return isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+    EnumConstantDeclaration other = _other as EnumConstantDeclaration;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualNodes(node.name, other.name);
+  }
+
+  @override
+  bool visitEnumDeclaration(EnumDeclaration node) {
+    EnumDeclaration other = _other as EnumDeclaration;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.enumKeyword, other.enumKeyword) &&
+        isEqualNodes(node.name, other.name) &&
+        isEqualTokens(node.leftBracket, other.leftBracket) &&
+        _isEqualNodeLists(node.constants, other.constants) &&
+        isEqualTokens(node.rightBracket, other.rightBracket);
+  }
+
+  @override
+  bool visitExportDirective(ExportDirective node) {
+    ExportDirective other = _other as ExportDirective;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.keyword, other.keyword) &&
+        isEqualNodes(node.uri, other.uri) &&
+        _isEqualNodeLists(node.combinators, other.combinators) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitExpressionFunctionBody(ExpressionFunctionBody node) {
+    ExpressionFunctionBody other = _other as ExpressionFunctionBody;
+    return isEqualTokens(node.functionDefinition, other.functionDefinition) &&
+        isEqualNodes(node.expression, other.expression) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitExpressionStatement(ExpressionStatement node) {
+    ExpressionStatement other = _other as ExpressionStatement;
+    return isEqualNodes(node.expression, other.expression) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitExtendsClause(ExtendsClause node) {
+    ExtendsClause other = _other as ExtendsClause;
+    return isEqualTokens(node.extendsKeyword, other.extendsKeyword) &&
+        isEqualNodes(node.superclass, other.superclass);
+  }
+
+  @override
+  bool visitFieldDeclaration(FieldDeclaration node) {
+    FieldDeclaration other = _other as FieldDeclaration;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.staticKeyword, other.staticKeyword) &&
+        isEqualNodes(node.fields, other.fields) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitFieldFormalParameter(FieldFormalParameter node) {
+    FieldFormalParameter other = _other as FieldFormalParameter;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.keyword, other.keyword) &&
+        isEqualNodes(node.type, other.type) &&
+        isEqualTokens(node.thisKeyword, other.thisKeyword) &&
+        isEqualTokens(node.period, other.period) &&
+        isEqualNodes(node.identifier, other.identifier);
+  }
+
+  @override
+  bool visitForEachStatement(ForEachStatement node) {
+    ForEachStatement other = _other as ForEachStatement;
+    return isEqualTokens(node.forKeyword, other.forKeyword) &&
+        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+        isEqualNodes(node.loopVariable, other.loopVariable) &&
+        isEqualTokens(node.inKeyword, other.inKeyword) &&
+        isEqualNodes(node.iterable, other.iterable) &&
+        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+        isEqualNodes(node.body, other.body);
+  }
+
+  @override
+  bool visitFormalParameterList(FormalParameterList node) {
+    FormalParameterList other = _other as FormalParameterList;
+    return isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+        _isEqualNodeLists(node.parameters, other.parameters) &&
+        isEqualTokens(node.leftDelimiter, other.leftDelimiter) &&
+        isEqualTokens(node.rightDelimiter, other.rightDelimiter) &&
+        isEqualTokens(node.rightParenthesis, other.rightParenthesis);
+  }
+
+  @override
+  bool visitForStatement(ForStatement node) {
+    ForStatement other = _other as ForStatement;
+    return isEqualTokens(node.forKeyword, other.forKeyword) &&
+        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+        isEqualNodes(node.variables, other.variables) &&
+        isEqualNodes(node.initialization, other.initialization) &&
+        isEqualTokens(node.leftSeparator, other.leftSeparator) &&
+        isEqualNodes(node.condition, other.condition) &&
+        isEqualTokens(node.rightSeparator, other.rightSeparator) &&
+        _isEqualNodeLists(node.updaters, other.updaters) &&
+        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+        isEqualNodes(node.body, other.body);
+  }
+
+  @override
+  bool visitFunctionDeclaration(FunctionDeclaration node) {
+    FunctionDeclaration other = _other as FunctionDeclaration;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.externalKeyword, other.externalKeyword) &&
+        isEqualNodes(node.returnType, other.returnType) &&
+        isEqualTokens(node.propertyKeyword, other.propertyKeyword) &&
+        isEqualNodes(node.name, other.name) &&
+        isEqualNodes(node.functionExpression, other.functionExpression);
+  }
+
+  @override
+  bool visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+    FunctionDeclarationStatement other = _other as FunctionDeclarationStatement;
+    return isEqualNodes(node.functionDeclaration, other.functionDeclaration);
+  }
+
+  @override
+  bool visitFunctionExpression(FunctionExpression node) {
+    FunctionExpression other = _other as FunctionExpression;
+    return isEqualNodes(node.parameters, other.parameters) &&
+        isEqualNodes(node.body, other.body);
+  }
+
+  @override
+  bool visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+    FunctionExpressionInvocation other = _other as FunctionExpressionInvocation;
+    return isEqualNodes(node.function, other.function) &&
+        isEqualNodes(node.argumentList, other.argumentList);
+  }
+
+  @override
+  bool visitFunctionTypeAlias(FunctionTypeAlias node) {
+    FunctionTypeAlias other = _other as FunctionTypeAlias;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.typedefKeyword, other.typedefKeyword) &&
+        isEqualNodes(node.returnType, other.returnType) &&
+        isEqualNodes(node.name, other.name) &&
+        isEqualNodes(node.typeParameters, other.typeParameters) &&
+        isEqualNodes(node.parameters, other.parameters) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+    FunctionTypedFormalParameter other = _other as FunctionTypedFormalParameter;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualNodes(node.returnType, other.returnType) &&
+        isEqualNodes(node.identifier, other.identifier) &&
+        isEqualNodes(node.parameters, other.parameters);
+  }
+
+  @override
+  bool visitHideCombinator(HideCombinator node) {
+    HideCombinator other = _other as HideCombinator;
+    return isEqualTokens(node.keyword, other.keyword) &&
+        _isEqualNodeLists(node.hiddenNames, other.hiddenNames);
+  }
+
+  @override
+  bool visitIfStatement(IfStatement node) {
+    IfStatement other = _other as IfStatement;
+    return isEqualTokens(node.ifKeyword, other.ifKeyword) &&
+        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+        isEqualNodes(node.condition, other.condition) &&
+        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+        isEqualNodes(node.thenStatement, other.thenStatement) &&
+        isEqualTokens(node.elseKeyword, other.elseKeyword) &&
+        isEqualNodes(node.elseStatement, other.elseStatement);
+  }
+
+  @override
+  bool visitImplementsClause(ImplementsClause node) {
+    ImplementsClause other = _other as ImplementsClause;
+    return isEqualTokens(node.implementsKeyword, other.implementsKeyword) &&
+        _isEqualNodeLists(node.interfaces, other.interfaces);
+  }
+
+  @override
+  bool visitImportDirective(ImportDirective node) {
+    ImportDirective other = _other as ImportDirective;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.keyword, other.keyword) &&
+        isEqualNodes(node.uri, other.uri) &&
+        isEqualTokens(node.deferredKeyword, other.deferredKeyword) &&
+        isEqualTokens(node.asKeyword, other.asKeyword) &&
+        isEqualNodes(node.prefix, other.prefix) &&
+        _isEqualNodeLists(node.combinators, other.combinators) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitIndexExpression(IndexExpression node) {
+    IndexExpression other = _other as IndexExpression;
+    return isEqualNodes(node.target, other.target) &&
+        isEqualTokens(node.leftBracket, other.leftBracket) &&
+        isEqualNodes(node.index, other.index) &&
+        isEqualTokens(node.rightBracket, other.rightBracket);
+  }
+
+  @override
+  bool visitInstanceCreationExpression(InstanceCreationExpression node) {
+    InstanceCreationExpression other = _other as InstanceCreationExpression;
+    return isEqualTokens(node.keyword, other.keyword) &&
+        isEqualNodes(node.constructorName, other.constructorName) &&
+        isEqualNodes(node.argumentList, other.argumentList);
+  }
+
+  @override
+  bool visitIntegerLiteral(IntegerLiteral node) {
+    IntegerLiteral other = _other as IntegerLiteral;
+    return isEqualTokens(node.literal, other.literal) &&
+        (node.value == other.value);
+  }
+
+  @override
+  bool visitInterpolationExpression(InterpolationExpression node) {
+    InterpolationExpression other = _other as InterpolationExpression;
+    return isEqualTokens(node.leftBracket, other.leftBracket) &&
+        isEqualNodes(node.expression, other.expression) &&
+        isEqualTokens(node.rightBracket, other.rightBracket);
+  }
+
+  @override
+  bool visitInterpolationString(InterpolationString node) {
+    InterpolationString other = _other as InterpolationString;
+    return isEqualTokens(node.contents, other.contents) &&
+        node.value == other.value;
+  }
+
+  @override
+  bool visitIsExpression(IsExpression node) {
+    IsExpression other = _other as IsExpression;
+    return isEqualNodes(node.expression, other.expression) &&
+        isEqualTokens(node.isOperator, other.isOperator) &&
+        isEqualTokens(node.notOperator, other.notOperator) &&
+        isEqualNodes(node.type, other.type);
+  }
+
+  @override
+  bool visitLabel(Label node) {
+    Label other = _other as Label;
+    return isEqualNodes(node.label, other.label) &&
+        isEqualTokens(node.colon, other.colon);
+  }
+
+  @override
+  bool visitLabeledStatement(LabeledStatement node) {
+    LabeledStatement other = _other as LabeledStatement;
+    return _isEqualNodeLists(node.labels, other.labels) &&
+        isEqualNodes(node.statement, other.statement);
+  }
+
+  @override
+  bool visitLibraryDirective(LibraryDirective node) {
+    LibraryDirective other = _other as LibraryDirective;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.libraryKeyword, other.libraryKeyword) &&
+        isEqualNodes(node.name, other.name) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitLibraryIdentifier(LibraryIdentifier node) {
+    LibraryIdentifier other = _other as LibraryIdentifier;
+    return _isEqualNodeLists(node.components, other.components);
+  }
+
+  @override
+  bool visitListLiteral(ListLiteral node) {
+    ListLiteral other = _other as ListLiteral;
+    return isEqualTokens(node.constKeyword, other.constKeyword) &&
+        isEqualNodes(node.typeArguments, other.typeArguments) &&
+        isEqualTokens(node.leftBracket, other.leftBracket) &&
+        _isEqualNodeLists(node.elements, other.elements) &&
+        isEqualTokens(node.rightBracket, other.rightBracket);
+  }
+
+  @override
+  bool visitMapLiteral(MapLiteral node) {
+    MapLiteral other = _other as MapLiteral;
+    return isEqualTokens(node.constKeyword, other.constKeyword) &&
+        isEqualNodes(node.typeArguments, other.typeArguments) &&
+        isEqualTokens(node.leftBracket, other.leftBracket) &&
+        _isEqualNodeLists(node.entries, other.entries) &&
+        isEqualTokens(node.rightBracket, other.rightBracket);
+  }
+
+  @override
+  bool visitMapLiteralEntry(MapLiteralEntry node) {
+    MapLiteralEntry other = _other as MapLiteralEntry;
+    return isEqualNodes(node.key, other.key) &&
+        isEqualTokens(node.separator, other.separator) &&
+        isEqualNodes(node.value, other.value);
+  }
+
+  @override
+  bool visitMethodDeclaration(MethodDeclaration node) {
+    MethodDeclaration other = _other as MethodDeclaration;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.externalKeyword, other.externalKeyword) &&
+        isEqualTokens(node.modifierKeyword, other.modifierKeyword) &&
+        isEqualNodes(node.returnType, other.returnType) &&
+        isEqualTokens(node.propertyKeyword, other.propertyKeyword) &&
+        isEqualTokens(node.propertyKeyword, other.propertyKeyword) &&
+        isEqualNodes(node.name, other.name) &&
+        isEqualNodes(node.parameters, other.parameters) &&
+        isEqualNodes(node.body, other.body);
+  }
+
+  @override
+  bool visitMethodInvocation(MethodInvocation node) {
+    MethodInvocation other = _other as MethodInvocation;
+    return isEqualNodes(node.target, other.target) &&
+        isEqualTokens(node.operator, other.operator) &&
+        isEqualNodes(node.methodName, other.methodName) &&
+        isEqualNodes(node.argumentList, other.argumentList);
+  }
+
+  @override
+  bool visitNamedExpression(NamedExpression node) {
+    NamedExpression other = _other as NamedExpression;
+    return isEqualNodes(node.name, other.name) &&
+        isEqualNodes(node.expression, other.expression);
+  }
+
+  @override
+  bool visitNativeClause(NativeClause node) {
+    NativeClause other = _other as NativeClause;
+    return isEqualTokens(node.nativeKeyword, other.nativeKeyword) &&
+        isEqualNodes(node.name, other.name);
+  }
+
+  @override
+  bool visitNativeFunctionBody(NativeFunctionBody node) {
+    NativeFunctionBody other = _other as NativeFunctionBody;
+    return isEqualTokens(node.nativeKeyword, other.nativeKeyword) &&
+        isEqualNodes(node.stringLiteral, other.stringLiteral) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitNullLiteral(NullLiteral node) {
+    NullLiteral other = _other as NullLiteral;
+    return isEqualTokens(node.literal, other.literal);
+  }
+
+  @override
+  bool visitParenthesizedExpression(ParenthesizedExpression node) {
+    ParenthesizedExpression other = _other as ParenthesizedExpression;
+    return isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+        isEqualNodes(node.expression, other.expression) &&
+        isEqualTokens(node.rightParenthesis, other.rightParenthesis);
+  }
+
+  @override
+  bool visitPartDirective(PartDirective node) {
+    PartDirective other = _other as PartDirective;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.partKeyword, other.partKeyword) &&
+        isEqualNodes(node.uri, other.uri) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitPartOfDirective(PartOfDirective node) {
+    PartOfDirective other = _other as PartOfDirective;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.partKeyword, other.partKeyword) &&
+        isEqualTokens(node.ofKeyword, other.ofKeyword) &&
+        isEqualNodes(node.libraryName, other.libraryName) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitPostfixExpression(PostfixExpression node) {
+    PostfixExpression other = _other as PostfixExpression;
+    return isEqualNodes(node.operand, other.operand) &&
+        isEqualTokens(node.operator, other.operator);
+  }
+
+  @override
+  bool visitPrefixedIdentifier(PrefixedIdentifier node) {
+    PrefixedIdentifier other = _other as PrefixedIdentifier;
+    return isEqualNodes(node.prefix, other.prefix) &&
+        isEqualTokens(node.period, other.period) &&
+        isEqualNodes(node.identifier, other.identifier);
+  }
+
+  @override
+  bool visitPrefixExpression(PrefixExpression node) {
+    PrefixExpression other = _other as PrefixExpression;
+    return isEqualTokens(node.operator, other.operator) &&
+        isEqualNodes(node.operand, other.operand);
+  }
+
+  @override
+  bool visitPropertyAccess(PropertyAccess node) {
+    PropertyAccess other = _other as PropertyAccess;
+    return isEqualNodes(node.target, other.target) &&
+        isEqualTokens(node.operator, other.operator) &&
+        isEqualNodes(node.propertyName, other.propertyName);
+  }
+
+  @override
+  bool visitRedirectingConstructorInvocation(
+      RedirectingConstructorInvocation node) {
+    RedirectingConstructorInvocation other =
+        _other as RedirectingConstructorInvocation;
+    return isEqualTokens(node.thisKeyword, other.thisKeyword) &&
+        isEqualTokens(node.period, other.period) &&
+        isEqualNodes(node.constructorName, other.constructorName) &&
+        isEqualNodes(node.argumentList, other.argumentList);
+  }
+
+  @override
+  bool visitRethrowExpression(RethrowExpression node) {
+    RethrowExpression other = _other as RethrowExpression;
+    return isEqualTokens(node.rethrowKeyword, other.rethrowKeyword);
+  }
+
+  @override
+  bool visitReturnStatement(ReturnStatement node) {
+    ReturnStatement other = _other as ReturnStatement;
+    return isEqualTokens(node.returnKeyword, other.returnKeyword) &&
+        isEqualNodes(node.expression, other.expression) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitScriptTag(ScriptTag node) {
+    ScriptTag other = _other as ScriptTag;
+    return isEqualTokens(node.scriptTag, other.scriptTag);
+  }
+
+  @override
+  bool visitShowCombinator(ShowCombinator node) {
+    ShowCombinator other = _other as ShowCombinator;
+    return isEqualTokens(node.keyword, other.keyword) &&
+        _isEqualNodeLists(node.shownNames, other.shownNames);
+  }
+
+  @override
+  bool visitSimpleFormalParameter(SimpleFormalParameter node) {
+    SimpleFormalParameter other = _other as SimpleFormalParameter;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.keyword, other.keyword) &&
+        isEqualNodes(node.type, other.type) &&
+        isEqualNodes(node.identifier, other.identifier);
+  }
+
+  @override
+  bool visitSimpleIdentifier(SimpleIdentifier node) {
+    SimpleIdentifier other = _other as SimpleIdentifier;
+    return isEqualTokens(node.token, other.token);
+  }
+
+  @override
+  bool visitSimpleStringLiteral(SimpleStringLiteral node) {
+    SimpleStringLiteral other = _other as SimpleStringLiteral;
+    return isEqualTokens(node.literal, other.literal) &&
+        (node.value == other.value);
+  }
+
+  @override
+  bool visitStringInterpolation(StringInterpolation node) {
+    StringInterpolation other = _other as StringInterpolation;
+    return _isEqualNodeLists(node.elements, other.elements);
+  }
+
+  @override
+  bool visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+    SuperConstructorInvocation other = _other as SuperConstructorInvocation;
+    return isEqualTokens(node.superKeyword, other.superKeyword) &&
+        isEqualTokens(node.period, other.period) &&
+        isEqualNodes(node.constructorName, other.constructorName) &&
+        isEqualNodes(node.argumentList, other.argumentList);
+  }
+
+  @override
+  bool visitSuperExpression(SuperExpression node) {
+    SuperExpression other = _other as SuperExpression;
+    return isEqualTokens(node.superKeyword, other.superKeyword);
+  }
+
+  @override
+  bool visitSwitchCase(SwitchCase node) {
+    SwitchCase other = _other as SwitchCase;
+    return _isEqualNodeLists(node.labels, other.labels) &&
+        isEqualTokens(node.keyword, other.keyword) &&
+        isEqualNodes(node.expression, other.expression) &&
+        isEqualTokens(node.colon, other.colon) &&
+        _isEqualNodeLists(node.statements, other.statements);
+  }
+
+  @override
+  bool visitSwitchDefault(SwitchDefault node) {
+    SwitchDefault other = _other as SwitchDefault;
+    return _isEqualNodeLists(node.labels, other.labels) &&
+        isEqualTokens(node.keyword, other.keyword) &&
+        isEqualTokens(node.colon, other.colon) &&
+        _isEqualNodeLists(node.statements, other.statements);
+  }
+
+  @override
+  bool visitSwitchStatement(SwitchStatement node) {
+    SwitchStatement other = _other as SwitchStatement;
+    return isEqualTokens(node.switchKeyword, other.switchKeyword) &&
+        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+        isEqualNodes(node.expression, other.expression) &&
+        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+        isEqualTokens(node.leftBracket, other.leftBracket) &&
+        _isEqualNodeLists(node.members, other.members) &&
+        isEqualTokens(node.rightBracket, other.rightBracket);
+  }
+
+  @override
+  bool visitSymbolLiteral(SymbolLiteral node) {
+    SymbolLiteral other = _other as SymbolLiteral;
+    return isEqualTokens(node.poundSign, other.poundSign) &&
+        _isEqualTokenLists(node.components, other.components);
+  }
+
+  @override
+  bool visitThisExpression(ThisExpression node) {
+    ThisExpression other = _other as ThisExpression;
+    return isEqualTokens(node.thisKeyword, other.thisKeyword);
+  }
+
+  @override
+  bool visitThrowExpression(ThrowExpression node) {
+    ThrowExpression other = _other as ThrowExpression;
+    return isEqualTokens(node.throwKeyword, other.throwKeyword) &&
+        isEqualNodes(node.expression, other.expression);
+  }
+
+  @override
+  bool visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    TopLevelVariableDeclaration other = _other as TopLevelVariableDeclaration;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualNodes(node.variables, other.variables) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitTryStatement(TryStatement node) {
+    TryStatement other = _other as TryStatement;
+    return isEqualTokens(node.tryKeyword, other.tryKeyword) &&
+        isEqualNodes(node.body, other.body) &&
+        _isEqualNodeLists(node.catchClauses, other.catchClauses) &&
+        isEqualTokens(node.finallyKeyword, other.finallyKeyword) &&
+        isEqualNodes(node.finallyBlock, other.finallyBlock);
+  }
+
+  @override
+  bool visitTypeArgumentList(TypeArgumentList node) {
+    TypeArgumentList other = _other as TypeArgumentList;
+    return isEqualTokens(node.leftBracket, other.leftBracket) &&
+        _isEqualNodeLists(node.arguments, other.arguments) &&
+        isEqualTokens(node.rightBracket, other.rightBracket);
+  }
+
+  @override
+  bool visitTypeName(TypeName node) {
+    TypeName other = _other as TypeName;
+    return isEqualNodes(node.name, other.name) &&
+        isEqualNodes(node.typeArguments, other.typeArguments);
+  }
+
+  @override
+  bool visitTypeParameter(TypeParameter node) {
+    TypeParameter other = _other as TypeParameter;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualNodes(node.name, other.name) &&
+        isEqualTokens(node.extendsKeyword, other.extendsKeyword) &&
+        isEqualNodes(node.bound, other.bound);
+  }
+
+  @override
+  bool visitTypeParameterList(TypeParameterList node) {
+    TypeParameterList other = _other as TypeParameterList;
+    return isEqualTokens(node.leftBracket, other.leftBracket) &&
+        _isEqualNodeLists(node.typeParameters, other.typeParameters) &&
+        isEqualTokens(node.rightBracket, other.rightBracket);
+  }
+
+  @override
+  bool visitVariableDeclaration(VariableDeclaration node) {
+    VariableDeclaration other = _other as VariableDeclaration;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualNodes(node.name, other.name) &&
+        isEqualTokens(node.equals, other.equals) &&
+        isEqualNodes(node.initializer, other.initializer);
+  }
+
+  @override
+  bool visitVariableDeclarationList(VariableDeclarationList node) {
+    VariableDeclarationList other = _other as VariableDeclarationList;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.keyword, other.keyword) &&
+        isEqualNodes(node.type, other.type) &&
+        _isEqualNodeLists(node.variables, other.variables);
+  }
+
+  @override
+  bool visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+    VariableDeclarationStatement other = _other as VariableDeclarationStatement;
+    return isEqualNodes(node.variables, other.variables) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  @override
+  bool visitWhileStatement(WhileStatement node) {
+    WhileStatement other = _other as WhileStatement;
+    return isEqualTokens(node.whileKeyword, other.whileKeyword) &&
+        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+        isEqualNodes(node.condition, other.condition) &&
+        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+        isEqualNodes(node.body, other.body);
+  }
+
+  @override
+  bool visitWithClause(WithClause node) {
+    WithClause other = _other as WithClause;
+    return isEqualTokens(node.withKeyword, other.withKeyword) &&
+        _isEqualNodeLists(node.mixinTypes, other.mixinTypes);
+  }
+
+  @override
+  bool visitYieldStatement(YieldStatement node) {
+    YieldStatement other = _other as YieldStatement;
+    return isEqualTokens(node.yieldKeyword, other.yieldKeyword) &&
+        isEqualNodes(node.expression, other.expression) &&
+        isEqualTokens(node.semicolon, other.semicolon);
+  }
+
+  /**
+   * Return `true` if the [first] and [second] lists of AST nodes have the same
+   * size and corresponding elements are equal.
+   */
+  bool _isEqualNodeLists(NodeList first, NodeList second) {
+    if (first == null) {
+      return second == null;
+    } else if (second == null) {
+      return false;
+    }
+    int size = first.length;
+    if (second.length != size) {
+      return false;
+    }
+    for (int i = 0; i < size; i++) {
+      if (!isEqualNodes(first[i], second[i])) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Return `true` if the [first] and [second] lists of tokens have the same
+   * length and corresponding elements are equal.
+   */
+  bool _isEqualTokenLists(List<Token> first, List<Token> second) {
+    int length = first.length;
+    if (second.length != length) {
+      return false;
+    }
+    for (int i = 0; i < length; i++) {
+      if (!isEqualTokens(first[i], second[i])) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Return `true` if the [first] and [second] nodes are equal.
+   */
+  static bool equalNodes(AstNode first, AstNode second) {
+    AstComparator comparator = new AstComparator();
+    return comparator.isEqualNodes(first, second);
+  }
+}
+
+/**
+ * Instances of the class [ConstantEvaluator] evaluate constant expressions to
+ * produce their compile-time value.
+ *
+ * According to the Dart Language Specification:
+ *
+ * > A constant expression is one of the following:
+ * >
+ * > * A literal number.
+ * > * A literal boolean.
+ * > * A literal string where any interpolated expression is a compile-time
+ * >   constant that evaluates to a numeric, string or boolean value or to
+ * >   **null**.
+ * > * A literal symbol.
+ * > * **null**.
+ * > * A qualified reference to a static constant variable.
+ * > * An identifier expression that denotes a constant variable, class or type
+ * >   alias.
+ * > * A constant constructor invocation.
+ * > * A constant list literal.
+ * > * A constant map literal.
+ * > * A simple or qualified identifier denoting a top-level function or a
+ * >   static method.
+ * > * A parenthesized expression _(e)_ where _e_ is a constant expression.
+ * > * <span>
+ * >   An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i>
+ * >   where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
+ * >   expressions and <i>identical()</i> is statically bound to the predefined
+ * >   dart function <i>identical()</i> discussed above.
+ * >   </span>
+ * > * <span>
+ * >   An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i>
+ * >   or <i>e<sub>1</sub> != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and
+ * >   <i>e<sub>2</sub></i> are constant expressions that evaluate to a
+ * >   numeric, string or boolean value.
+ * >   </span>
+ * > * <span>
+ * >   An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> &amp;&amp;
+ * >   e<sub>2</sub></i> or <i>e<sub>1</sub> || e<sub>2</sub></i>, where
+ * >   <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
+ * >   expressions that evaluate to a boolean value.
+ * >   </span>
+ * > * <span>
+ * >   An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^
+ * >   e<sub>2</sub></i>, <i>e<sub>1</sub> &amp; e<sub>2</sub></i>,
+ * >   <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;&gt;
+ * >   e<sub>2</sub></i> or <i>e<sub>1</sub> &lt;&lt; e<sub>2</sub></i>, where
+ * >   <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
+ * >   expressions that evaluate to an integer value or to <b>null</b>.
+ * >   </span>
+ * > * <span>
+ * >   An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> +
+ * >   e<sub>2</sub></i>, <i>e<sub>1</sub> -e<sub>2</sub></i>,
+ * >   <i>e<sub>1</sub> * e<sub>2</sub></i>, <i>e<sub>1</sub> /
+ * >   e<sub>2</sub></i>, <i>e<sub>1</sub> ~/ e<sub>2</sub></i>,
+ * >   <i>e<sub>1</sub> &gt; e<sub>2</sub></i>, <i>e<sub>1</sub> &lt;
+ * >   e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;= e<sub>2</sub></i>,
+ * >   <i>e<sub>1</sub> &lt;= e<sub>2</sub></i> or <i>e<sub>1</sub> %
+ * >   e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i> and
+ * >   <i>e<sub>2</sub></i> are constant expressions that evaluate to a numeric
+ * >   value or to <b>null</b>.
+ * >   </span>
+ * > * <span>
+ * >   An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> :
+ * >   e<sub>3</sub></i> where <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and
+ * >   <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i>
+ * >   evaluates to a boolean value.
+ * >   </span>
+ *
+ * The values returned by instances of this class are therefore `null` and
+ * instances of the classes `Boolean`, `BigInteger`, `Double`, `String`, and
+ * `DartObject`.
+ *
+ * In addition, this class defines several values that can be returned to
+ * indicate various conditions encountered during evaluation. These are
+ * documented with the static fields that define those values.
+ */
+class ConstantEvaluator extends GeneralizingAstVisitor<Object> {
+  /**
+   * The value returned for expressions (or non-expression nodes) that are not
+   * compile-time constant expressions.
+   */
+  static Object NOT_A_CONSTANT = new Object();
+
+  @override
+  Object visitAdjacentStrings(AdjacentStrings node) {
+    StringBuffer buffer = new StringBuffer();
+    for (StringLiteral string in node.strings) {
+      Object value = string.accept(this);
+      if (identical(value, NOT_A_CONSTANT)) {
+        return value;
+      }
+      buffer.write(value);
+    }
+    return buffer.toString();
+  }
+
+  @override
+  Object visitBinaryExpression(BinaryExpression node) {
+    Object leftOperand = node.leftOperand.accept(this);
+    if (identical(leftOperand, NOT_A_CONSTANT)) {
+      return leftOperand;
+    }
+    Object rightOperand = node.rightOperand.accept(this);
+    if (identical(rightOperand, NOT_A_CONSTANT)) {
+      return rightOperand;
+    }
+    while (true) {
+      if (node.operator.type == TokenType.AMPERSAND) {
+        // integer or {@code null}
+        if (leftOperand is int && rightOperand is int) {
+          return leftOperand & rightOperand;
+        }
+      } else if (node.operator.type == TokenType.AMPERSAND_AMPERSAND) {
+        // boolean or {@code null}
+        if (leftOperand is bool && rightOperand is bool) {
+          return leftOperand && rightOperand;
+        }
+      } else if (node.operator.type == TokenType.BANG_EQ) {
+        // numeric, string, boolean, or {@code null}
+        if (leftOperand is bool && rightOperand is bool) {
+          return leftOperand != rightOperand;
+        } else if (leftOperand is num && rightOperand is num) {
+          return leftOperand != rightOperand;
+        } else if (leftOperand is String && rightOperand is String) {
+          return leftOperand != rightOperand;
+        }
+      } else if (node.operator.type == TokenType.BAR) {
+        // integer or {@code null}
+        if (leftOperand is int && rightOperand is int) {
+          return leftOperand | rightOperand;
+        }
+      } else if (node.operator.type == TokenType.BAR_BAR) {
+        // boolean or {@code null}
+        if (leftOperand is bool && rightOperand is bool) {
+          return leftOperand || rightOperand;
+        }
+      } else if (node.operator.type == TokenType.CARET) {
+        // integer or {@code null}
+        if (leftOperand is int && rightOperand is int) {
+          return leftOperand ^ rightOperand;
+        }
+      } else if (node.operator.type == TokenType.EQ_EQ) {
+        // numeric, string, boolean, or {@code null}
+        if (leftOperand is bool && rightOperand is bool) {
+          return leftOperand == rightOperand;
+        } else if (leftOperand is num && rightOperand is num) {
+          return leftOperand == rightOperand;
+        } else if (leftOperand is String && rightOperand is String) {
+          return leftOperand == rightOperand;
+        }
+      } else if (node.operator.type == TokenType.GT) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand.compareTo(rightOperand) > 0;
+        }
+      } else if (node.operator.type == TokenType.GT_EQ) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand.compareTo(rightOperand) >= 0;
+        }
+      } else if (node.operator.type == TokenType.GT_GT) {
+        // integer or {@code null}
+        if (leftOperand is int && rightOperand is int) {
+          return leftOperand >> rightOperand;
+        }
+      } else if (node.operator.type == TokenType.LT) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand.compareTo(rightOperand) < 0;
+        }
+      } else if (node.operator.type == TokenType.LT_EQ) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand.compareTo(rightOperand) <= 0;
+        }
+      } else if (node.operator.type == TokenType.LT_LT) {
+        // integer or {@code null}
+        if (leftOperand is int && rightOperand is int) {
+          return leftOperand << rightOperand;
+        }
+      } else if (node.operator.type == TokenType.MINUS) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand - rightOperand;
+        }
+      } else if (node.operator.type == TokenType.PERCENT) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand.remainder(rightOperand);
+        }
+      } else if (node.operator.type == TokenType.PLUS) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand + rightOperand;
+        }
+      } else if (node.operator.type == TokenType.STAR) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand * rightOperand;
+        }
+      } else if (node.operator.type == TokenType.SLASH) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand / rightOperand;
+        }
+      } else if (node.operator.type == TokenType.TILDE_SLASH) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand ~/ rightOperand;
+        }
+      } else {}
+      break;
+    }
+    // TODO(brianwilkerson) This doesn't handle numeric conversions.
+    return visitExpression(node);
+  }
+
+  @override
+  Object visitBooleanLiteral(BooleanLiteral node) => node.value ? true : false;
+
+  @override
+  Object visitDoubleLiteral(DoubleLiteral node) => node.value;
+
+  @override
+  Object visitIntegerLiteral(IntegerLiteral node) => node.value;
+
+  @override
+  Object visitInterpolationExpression(InterpolationExpression node) {
+    Object value = node.expression.accept(this);
+    if (value == null || value is bool || value is String || value is num) {
+      return value;
+    }
+    return NOT_A_CONSTANT;
+  }
+
+  @override
+  Object visitInterpolationString(InterpolationString node) => node.value;
+
+  @override
+  Object visitListLiteral(ListLiteral node) {
+    List<Object> list = new List<Object>();
+    for (Expression element in node.elements) {
+      Object value = element.accept(this);
+      if (identical(value, NOT_A_CONSTANT)) {
+        return value;
+      }
+      list.add(value);
+    }
+    return list;
+  }
+
+  @override
+  Object visitMapLiteral(MapLiteral node) {
+    HashMap<String, Object> map = new HashMap<String, Object>();
+    for (MapLiteralEntry entry in node.entries) {
+      Object key = entry.key.accept(this);
+      Object value = entry.value.accept(this);
+      if (key is! String || identical(value, NOT_A_CONSTANT)) {
+        return NOT_A_CONSTANT;
+      }
+      map[(key as String)] = value;
+    }
+    return map;
+  }
+
+  @override
+  Object visitMethodInvocation(MethodInvocation node) => visitNode(node);
+
+  @override
+  Object visitNode(AstNode node) => NOT_A_CONSTANT;
+
+  @override
+  Object visitNullLiteral(NullLiteral node) => null;
+
+  @override
+  Object visitParenthesizedExpression(ParenthesizedExpression node) =>
+      node.expression.accept(this);
+
+  @override
+  Object visitPrefixedIdentifier(PrefixedIdentifier node) =>
+      _getConstantValue(null);
+
+  @override
+  Object visitPrefixExpression(PrefixExpression node) {
+    Object operand = node.operand.accept(this);
+    if (identical(operand, NOT_A_CONSTANT)) {
+      return operand;
+    }
+    while (true) {
+      if (node.operator.type == TokenType.BANG) {
+        if (identical(operand, true)) {
+          return false;
+        } else if (identical(operand, false)) {
+          return true;
+        }
+      } else if (node.operator.type == TokenType.TILDE) {
+        if (operand is int) {
+          return ~operand;
+        }
+      } else if (node.operator.type == TokenType.MINUS) {
+        if (operand == null) {
+          return null;
+        } else if (operand is num) {
+          return -operand;
+        }
+      } else {}
+      break;
+    }
+    return NOT_A_CONSTANT;
+  }
+
+  @override
+  Object visitPropertyAccess(PropertyAccess node) => _getConstantValue(null);
+
+  @override
+  Object visitSimpleIdentifier(SimpleIdentifier node) =>
+      _getConstantValue(null);
+
+  @override
+  Object visitSimpleStringLiteral(SimpleStringLiteral node) => node.value;
+
+  @override
+  Object visitStringInterpolation(StringInterpolation node) {
+    StringBuffer buffer = new StringBuffer();
+    for (InterpolationElement element in node.elements) {
+      Object value = element.accept(this);
+      if (identical(value, NOT_A_CONSTANT)) {
+        return value;
+      }
+      buffer.write(value);
+    }
+    return buffer.toString();
+  }
+
+  @override
+  Object visitSymbolLiteral(SymbolLiteral node) {
+    // TODO(brianwilkerson) This isn't optimal because a Symbol is not a String.
+    StringBuffer buffer = new StringBuffer();
+    for (Token component in node.components) {
+      if (buffer.length > 0) {
+        buffer.writeCharCode(0x2E);
+      }
+      buffer.write(component.lexeme);
+    }
+    return buffer.toString();
+  }
+
+  /**
+   * Return the constant value of the static constant represented by the given
+   * [element].
+   */
+  Object _getConstantValue(Element element) {
+    // TODO(brianwilkerson) Implement this
+    if (element is FieldElement) {
+      FieldElement field = element;
+      if (field.isStatic && field.isConst) {
+        //field.getConstantValue();
+      }
+      //    } else if (element instanceof VariableElement) {
+      //      VariableElement variable = (VariableElement) element;
+      //      if (variable.isStatic() && variable.isConst()) {
+      //        //variable.getConstantValue();
+      //      }
+    }
+    return NOT_A_CONSTANT;
+  }
+}
+
+/**
+ * A recursive AST visitor that is used to run over [Expression]s to determine
+ * whether the expression is composed by at least one deferred
+ * [PrefixedIdentifier].
+ *
+ * See [PrefixedIdentifier.isDeferred].
+ */
+class DeferredLibraryReferenceDetector extends RecursiveAstVisitor<Object> {
+  /**
+   * A flag indicating whether an identifier from a deferred library has been
+   * found.
+   */
+  bool _result = false;
+
+  /**
+   * Return `true` if the visitor found a [PrefixedIdentifier] that returned
+   * `true` to the [PrefixedIdentifier.isDeferred] query.
+   */
+  bool get result => _result;
+
+  @override
+  Object visitPrefixedIdentifier(PrefixedIdentifier node) {
+    if (!_result) {
+      if (node.isDeferred) {
+        _result = true;
+      }
+    }
+    return null;
+  }
+}
+
+/**
+ * An object used to locate the [Element] associated with a given [AstNode].
+ */
+class ElementLocator {
+  /**
+   * Return the element associated with the given [node], or `null` if there is
+   * no element associated with the node.
+   */
+  static Element locate(AstNode node) {
+    if (node == null) {
+      return null;
+    }
+    ElementLocator_ElementMapper mapper = new ElementLocator_ElementMapper();
+    return node.accept(mapper);
+  }
+}
+
+/**
+ * Visitor that maps nodes to elements.
+ */
+class ElementLocator_ElementMapper extends GeneralizingAstVisitor<Element> {
+  @override
+  Element visitAnnotation(Annotation node) => node.element;
+
+  @override
+  Element visitAssignmentExpression(AssignmentExpression node) =>
+      node.bestElement;
+
+  @override
+  Element visitBinaryExpression(BinaryExpression node) => node.bestElement;
+
+  @override
+  Element visitClassDeclaration(ClassDeclaration node) => node.element;
+
+  @override
+  Element visitCompilationUnit(CompilationUnit node) => node.element;
+
+  @override
+  Element visitConstructorDeclaration(ConstructorDeclaration node) =>
+      node.element;
+
+  @override
+  Element visitFunctionDeclaration(FunctionDeclaration node) => node.element;
+
+  @override
+  Element visitIdentifier(Identifier node) {
+    AstNode parent = node.parent;
+    // Type name in Annotation
+    if (parent is Annotation) {
+      Annotation annotation = parent;
+      if (identical(annotation.name, node) &&
+          annotation.constructorName == null) {
+        return annotation.element;
+      }
+    }
+    // Extra work to map Constructor Declarations to their associated
+    // Constructor Elements
+    if (parent is ConstructorDeclaration) {
+      Identifier returnType = parent.returnType;
+      if (identical(returnType, node)) {
+        SimpleIdentifier name = parent.name;
+        if (name != null) {
+          return name.bestElement;
+        }
+        Element element = node.bestElement;
+        if (element is ClassElement) {
+          return element.unnamedConstructor;
+        }
+      }
+    }
+    if (parent is LibraryIdentifier) {
+      AstNode grandParent = parent.parent;
+      if (grandParent is PartOfDirective) {
+        Element element = grandParent.element;
+        if (element is LibraryElement) {
+          return element.definingCompilationUnit;
+        }
+      }
+    }
+    return node.bestElement;
+  }
+
+  @override
+  Element visitImportDirective(ImportDirective node) => node.element;
+
+  @override
+  Element visitIndexExpression(IndexExpression node) => node.bestElement;
+
+  @override
+  Element visitInstanceCreationExpression(InstanceCreationExpression node) =>
+      node.staticElement;
+
+  @override
+  Element visitLibraryDirective(LibraryDirective node) => node.element;
+
+  @override
+  Element visitMethodDeclaration(MethodDeclaration node) => node.element;
+
+  @override
+  Element visitMethodInvocation(MethodInvocation node) =>
+      node.methodName.bestElement;
+
+  @override
+  Element visitPartOfDirective(PartOfDirective node) => node.element;
+
+  @override
+  Element visitPostfixExpression(PostfixExpression node) => node.bestElement;
+
+  @override
+  Element visitPrefixedIdentifier(PrefixedIdentifier node) => node.bestElement;
+
+  @override
+  Element visitPrefixExpression(PrefixExpression node) => node.bestElement;
+
+  @override
+  Element visitStringLiteral(StringLiteral node) {
+    AstNode parent = node.parent;
+    if (parent is UriBasedDirective) {
+      return parent.uriElement;
+    }
+    return null;
+  }
+
+  @override
+  Element visitVariableDeclaration(VariableDeclaration node) => node.element;
+}
+
+/**
+ * An object that will clone any AST structure that it visits. The cloner will
+ * clone the structure, replacing the specified ASTNode with a new ASTNode,
+ * mapping the old token stream to a new token stream, and preserving resolution
+ * results.
+ */
+class IncrementalAstCloner implements AstVisitor<AstNode> {
+  /**
+   * The node to be replaced during the cloning process.
+   */
+  final AstNode _oldNode;
+
+  /**
+   * The replacement node used during the cloning process.
+   */
+  final AstNode _newNode;
+
+  /**
+   * A mapping of old tokens to new tokens used during the cloning process.
+   */
+  final TokenMap _tokenMap;
+
+  /**
+   * Construct a new instance that will replace the [oldNode] with the [newNode]
+   * in the process of cloning an existing AST structure. The [tokenMap] is a
+   * mapping of old tokens to new tokens.
+   */
+  IncrementalAstCloner(this._oldNode, this._newNode, this._tokenMap);
+
+  @override
+  AdjacentStrings visitAdjacentStrings(AdjacentStrings node) =>
+      new AdjacentStrings(_cloneNodeList(node.strings));
+
+  @override
+  Annotation visitAnnotation(Annotation node) {
+    Annotation copy = new Annotation(
+        _mapToken(node.atSign),
+        _cloneNode(node.name),
+        _mapToken(node.period),
+        _cloneNode(node.constructorName),
+        _cloneNode(node.arguments));
+    copy.element = node.element;
+    return copy;
+  }
+
+  @override
+  ArgumentList visitArgumentList(ArgumentList node) => new ArgumentList(
+      _mapToken(node.leftParenthesis),
+      _cloneNodeList(node.arguments),
+      _mapToken(node.rightParenthesis));
+
+  @override
+  AsExpression visitAsExpression(AsExpression node) {
+    AsExpression copy = new AsExpression(_cloneNode(node.expression),
+        _mapToken(node.asOperator), _cloneNode(node.type));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  AstNode visitAssertStatement(AssertStatement node) => new AssertStatement(
+      _mapToken(node.assertKeyword),
+      _mapToken(node.leftParenthesis),
+      _cloneNode(node.condition),
+      _mapToken(node.comma),
+      _cloneNode(node.message),
+      _mapToken(node.rightParenthesis),
+      _mapToken(node.semicolon));
+
+  @override
+  AssignmentExpression visitAssignmentExpression(AssignmentExpression node) {
+    AssignmentExpression copy = new AssignmentExpression(
+        _cloneNode(node.leftHandSide),
+        _mapToken(node.operator),
+        _cloneNode(node.rightHandSide));
+    copy.propagatedElement = node.propagatedElement;
+    copy.propagatedType = node.propagatedType;
+    copy.staticElement = node.staticElement;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  AwaitExpression visitAwaitExpression(AwaitExpression node) =>
+      new AwaitExpression(
+          _mapToken(node.awaitKeyword), _cloneNode(node.expression));
+
+  @override
+  BinaryExpression visitBinaryExpression(BinaryExpression node) {
+    BinaryExpression copy = new BinaryExpression(_cloneNode(node.leftOperand),
+        _mapToken(node.operator), _cloneNode(node.rightOperand));
+    copy.propagatedElement = node.propagatedElement;
+    copy.propagatedType = node.propagatedType;
+    copy.staticElement = node.staticElement;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  Block visitBlock(Block node) => new Block(_mapToken(node.leftBracket),
+      _cloneNodeList(node.statements), _mapToken(node.rightBracket));
+
+  @override
+  BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) =>
+      new BlockFunctionBody(_mapToken(node.keyword), _mapToken(node.star),
+          _cloneNode(node.block));
+
+  @override
+  BooleanLiteral visitBooleanLiteral(BooleanLiteral node) {
+    BooleanLiteral copy =
+        new BooleanLiteral(_mapToken(node.literal), node.value);
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  BreakStatement visitBreakStatement(BreakStatement node) => new BreakStatement(
+      _mapToken(node.breakKeyword),
+      _cloneNode(node.label),
+      _mapToken(node.semicolon));
+
+  @override
+  CascadeExpression visitCascadeExpression(CascadeExpression node) {
+    CascadeExpression copy = new CascadeExpression(
+        _cloneNode(node.target), _cloneNodeList(node.cascadeSections));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  CatchClause visitCatchClause(CatchClause node) => new CatchClause(
+      _mapToken(node.onKeyword),
+      _cloneNode(node.exceptionType),
+      _mapToken(node.catchKeyword),
+      _mapToken(node.leftParenthesis),
+      _cloneNode(node.exceptionParameter),
+      _mapToken(node.comma),
+      _cloneNode(node.stackTraceParameter),
+      _mapToken(node.rightParenthesis),
+      _cloneNode(node.body));
+
+  @override
+  ClassDeclaration visitClassDeclaration(ClassDeclaration node) {
+    ClassDeclaration copy = new ClassDeclaration(
+        _cloneNode(node.documentationComment),
+        _cloneNodeList(node.metadata),
+        _mapToken(node.abstractKeyword),
+        _mapToken(node.classKeyword),
+        _cloneNode(node.name),
+        _cloneNode(node.typeParameters),
+        _cloneNode(node.extendsClause),
+        _cloneNode(node.withClause),
+        _cloneNode(node.implementsClause),
+        _mapToken(node.leftBracket),
+        _cloneNodeList(node.members),
+        _mapToken(node.rightBracket));
+    copy.nativeClause = _cloneNode(node.nativeClause);
+    return copy;
+  }
+
+  @override
+  ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) => new ClassTypeAlias(
+      _cloneNode(node.documentationComment),
+      _cloneNodeList(node.metadata),
+      _mapToken(node.typedefKeyword),
+      _cloneNode(node.name),
+      _cloneNode(node.typeParameters),
+      _mapToken(node.equals),
+      _mapToken(node.abstractKeyword),
+      _cloneNode(node.superclass),
+      _cloneNode(node.withClause),
+      _cloneNode(node.implementsClause),
+      _mapToken(node.semicolon));
+
+  @override
+  Comment visitComment(Comment node) {
+    if (node.isDocumentation) {
+      return Comment.createDocumentationCommentWithReferences(
+          _mapTokens(node.tokens), _cloneNodeList(node.references));
+    } else if (node.isBlock) {
+      return Comment.createBlockComment(_mapTokens(node.tokens));
+    }
+    return Comment.createEndOfLineComment(_mapTokens(node.tokens));
+  }
+
+  @override
+  CommentReference visitCommentReference(CommentReference node) =>
+      new CommentReference(
+          _mapToken(node.newKeyword), _cloneNode(node.identifier));
+
+  @override
+  CompilationUnit visitCompilationUnit(CompilationUnit node) {
+    CompilationUnit copy = new CompilationUnit(
+        _mapToken(node.beginToken),
+        _cloneNode(node.scriptTag),
+        _cloneNodeList(node.directives),
+        _cloneNodeList(node.declarations),
+        _mapToken(node.endToken));
+    copy.lineInfo = node.lineInfo;
+    copy.element = node.element;
+    return copy;
+  }
+
+  @override
+  ConditionalExpression visitConditionalExpression(ConditionalExpression node) {
+    ConditionalExpression copy = new ConditionalExpression(
+        _cloneNode(node.condition),
+        _mapToken(node.question),
+        _cloneNode(node.thenExpression),
+        _mapToken(node.colon),
+        _cloneNode(node.elseExpression));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  Configuration visitConfiguration(Configuration node) => new Configuration(
+      _mapToken(node.ifKeyword),
+      _mapToken(node.leftParenthesis),
+      _cloneNode(node.name),
+      _mapToken(node.equalToken),
+      _cloneNode(node.value),
+      _mapToken(node.rightParenthesis),
+      _cloneNode(node.libraryUri));
+
+  @override
+  ConstructorDeclaration visitConstructorDeclaration(
+      ConstructorDeclaration node) {
+    ConstructorDeclaration copy = new ConstructorDeclaration(
+        _cloneNode(node.documentationComment),
+        _cloneNodeList(node.metadata),
+        _mapToken(node.externalKeyword),
+        _mapToken(node.constKeyword),
+        _mapToken(node.factoryKeyword),
+        _cloneNode(node.returnType),
+        _mapToken(node.period),
+        _cloneNode(node.name),
+        _cloneNode(node.parameters),
+        _mapToken(node.separator),
+        _cloneNodeList(node.initializers),
+        _cloneNode(node.redirectedConstructor),
+        _cloneNode(node.body));
+    copy.element = node.element;
+    return copy;
+  }
+
+  @override
+  ConstructorFieldInitializer visitConstructorFieldInitializer(
+          ConstructorFieldInitializer node) =>
+      new ConstructorFieldInitializer(
+          _mapToken(node.thisKeyword),
+          _mapToken(node.period),
+          _cloneNode(node.fieldName),
+          _mapToken(node.equals),
+          _cloneNode(node.expression));
+
+  @override
+  ConstructorName visitConstructorName(ConstructorName node) {
+    ConstructorName copy = new ConstructorName(
+        _cloneNode(node.type), _mapToken(node.period), _cloneNode(node.name));
+    copy.staticElement = node.staticElement;
+    return copy;
+  }
+
+  @override
+  ContinueStatement visitContinueStatement(ContinueStatement node) =>
+      new ContinueStatement(_mapToken(node.continueKeyword),
+          _cloneNode(node.label), _mapToken(node.semicolon));
+
+  @override
+  DeclaredIdentifier visitDeclaredIdentifier(DeclaredIdentifier node) =>
+      new DeclaredIdentifier(
+          _cloneNode(node.documentationComment),
+          _cloneNodeList(node.metadata),
+          _mapToken(node.keyword),
+          _cloneNode(node.type),
+          _cloneNode(node.identifier));
+
+  @override
+  DefaultFormalParameter visitDefaultFormalParameter(
+          DefaultFormalParameter node) =>
+      new DefaultFormalParameter(_cloneNode(node.parameter), node.kind,
+          _mapToken(node.separator), _cloneNode(node.defaultValue));
+
+  @override
+  DoStatement visitDoStatement(DoStatement node) => new DoStatement(
+      _mapToken(node.doKeyword),
+      _cloneNode(node.body),
+      _mapToken(node.whileKeyword),
+      _mapToken(node.leftParenthesis),
+      _cloneNode(node.condition),
+      _mapToken(node.rightParenthesis),
+      _mapToken(node.semicolon));
+
+  @override
+  DottedName visitDottedName(DottedName node) =>
+      new DottedName(_cloneNodeList(node.components));
+
+  @override
+  DoubleLiteral visitDoubleLiteral(DoubleLiteral node) {
+    DoubleLiteral copy = new DoubleLiteral(_mapToken(node.literal), node.value);
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  EmptyFunctionBody visitEmptyFunctionBody(EmptyFunctionBody node) =>
+      new EmptyFunctionBody(_mapToken(node.semicolon));
+
+  @override
+  EmptyStatement visitEmptyStatement(EmptyStatement node) =>
+      new EmptyStatement(_mapToken(node.semicolon));
+
+  @override
+  AstNode visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
+      new EnumConstantDeclaration(_cloneNode(node.documentationComment),
+          _cloneNodeList(node.metadata), _cloneNode(node.name));
+
+  @override
+  AstNode visitEnumDeclaration(EnumDeclaration node) => new EnumDeclaration(
+      _cloneNode(node.documentationComment),
+      _cloneNodeList(node.metadata),
+      _mapToken(node.enumKeyword),
+      _cloneNode(node.name),
+      _mapToken(node.leftBracket),
+      _cloneNodeList(node.constants),
+      _mapToken(node.rightBracket));
+
+  @override
+  ExportDirective visitExportDirective(ExportDirective node) {
+    ExportDirective copy = new ExportDirective(
+        _cloneNode(node.documentationComment),
+        _cloneNodeList(node.metadata),
+        _mapToken(node.keyword),
+        _cloneNode(node.uri),
+        _cloneNodeList(node.configurations),
+        _cloneNodeList(node.combinators),
+        _mapToken(node.semicolon));
+    copy.element = node.element;
+    return copy;
+  }
+
+  @override
+  ExpressionFunctionBody visitExpressionFunctionBody(
+          ExpressionFunctionBody node) =>
+      new ExpressionFunctionBody(
+          _mapToken(node.keyword),
+          _mapToken(node.functionDefinition),
+          _cloneNode(node.expression),
+          _mapToken(node.semicolon));
+
+  @override
+  ExpressionStatement visitExpressionStatement(ExpressionStatement node) =>
+      new ExpressionStatement(
+          _cloneNode(node.expression), _mapToken(node.semicolon));
+
+  @override
+  ExtendsClause visitExtendsClause(ExtendsClause node) => new ExtendsClause(
+      _mapToken(node.extendsKeyword), _cloneNode(node.superclass));
+
+  @override
+  FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
+      new FieldDeclaration(
+          _cloneNode(node.documentationComment),
+          _cloneNodeList(node.metadata),
+          _mapToken(node.staticKeyword),
+          _cloneNode(node.fields),
+          _mapToken(node.semicolon));
+
+  @override
+  FieldFormalParameter visitFieldFormalParameter(FieldFormalParameter node) =>
+      new FieldFormalParameter(
+          _cloneNode(node.documentationComment),
+          _cloneNodeList(node.metadata),
+          _mapToken(node.keyword),
+          _cloneNode(node.type),
+          _mapToken(node.thisKeyword),
+          _mapToken(node.period),
+          _cloneNode(node.identifier),
+          _cloneNode(node.typeParameters),
+          _cloneNode(node.parameters));
+
+  @override
+  ForEachStatement visitForEachStatement(ForEachStatement node) {
+    DeclaredIdentifier loopVariable = node.loopVariable;
+    if (loopVariable == null) {
+      return new ForEachStatement.withReference(
+          _mapToken(node.awaitKeyword),
+          _mapToken(node.forKeyword),
+          _mapToken(node.leftParenthesis),
+          _cloneNode(node.identifier),
+          _mapToken(node.inKeyword),
+          _cloneNode(node.iterable),
+          _mapToken(node.rightParenthesis),
+          _cloneNode(node.body));
+    }
+    return new ForEachStatement.withDeclaration(
+        _mapToken(node.awaitKeyword),
+        _mapToken(node.forKeyword),
+        _mapToken(node.leftParenthesis),
+        _cloneNode(loopVariable),
+        _mapToken(node.inKeyword),
+        _cloneNode(node.iterable),
+        _mapToken(node.rightParenthesis),
+        _cloneNode(node.body));
+  }
+
+  @override
+  FormalParameterList visitFormalParameterList(FormalParameterList node) =>
+      new FormalParameterList(
+          _mapToken(node.leftParenthesis),
+          _cloneNodeList(node.parameters),
+          _mapToken(node.leftDelimiter),
+          _mapToken(node.rightDelimiter),
+          _mapToken(node.rightParenthesis));
+
+  @override
+  ForStatement visitForStatement(ForStatement node) => new ForStatement(
+      _mapToken(node.forKeyword),
+      _mapToken(node.leftParenthesis),
+      _cloneNode(node.variables),
+      _cloneNode(node.initialization),
+      _mapToken(node.leftSeparator),
+      _cloneNode(node.condition),
+      _mapToken(node.rightSeparator),
+      _cloneNodeList(node.updaters),
+      _mapToken(node.rightParenthesis),
+      _cloneNode(node.body));
+
+  @override
+  FunctionDeclaration visitFunctionDeclaration(FunctionDeclaration node) =>
+      new FunctionDeclaration(
+          _cloneNode(node.documentationComment),
+          _cloneNodeList(node.metadata),
+          _mapToken(node.externalKeyword),
+          _cloneNode(node.returnType),
+          _mapToken(node.propertyKeyword),
+          _cloneNode(node.name),
+          _cloneNode(node.functionExpression));
+
+  @override
+  FunctionDeclarationStatement visitFunctionDeclarationStatement(
+          FunctionDeclarationStatement node) =>
+      new FunctionDeclarationStatement(_cloneNode(node.functionDeclaration));
+
+  @override
+  FunctionExpression visitFunctionExpression(FunctionExpression node) {
+    FunctionExpression copy = new FunctionExpression(
+        _cloneNode(node.typeParameters),
+        _cloneNode(node.parameters),
+        _cloneNode(node.body));
+    copy.element = node.element;
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  FunctionExpressionInvocation visitFunctionExpressionInvocation(
+      FunctionExpressionInvocation node) {
+    FunctionExpressionInvocation copy = new FunctionExpressionInvocation(
+        _cloneNode(node.function),
+        _cloneNode(node.typeArguments),
+        _cloneNode(node.argumentList));
+    copy.propagatedElement = node.propagatedElement;
+    copy.propagatedType = node.propagatedType;
+    copy.staticElement = node.staticElement;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  FunctionTypeAlias visitFunctionTypeAlias(FunctionTypeAlias node) =>
+      new FunctionTypeAlias(
+          _cloneNode(node.documentationComment),
+          _cloneNodeList(node.metadata),
+          _mapToken(node.typedefKeyword),
+          _cloneNode(node.returnType),
+          _cloneNode(node.name),
+          _cloneNode(node.typeParameters),
+          _cloneNode(node.parameters),
+          _mapToken(node.semicolon));
+
+  @override
+  FunctionTypedFormalParameter visitFunctionTypedFormalParameter(
+          FunctionTypedFormalParameter node) =>
+      new FunctionTypedFormalParameter(
+          _cloneNode(node.documentationComment),
+          _cloneNodeList(node.metadata),
+          _cloneNode(node.returnType),
+          _cloneNode(node.identifier),
+          _cloneNode(node.typeParameters),
+          _cloneNode(node.parameters));
+
+  @override
+  HideCombinator visitHideCombinator(HideCombinator node) => new HideCombinator(
+      _mapToken(node.keyword), _cloneNodeList(node.hiddenNames));
+
+  @override
+  IfStatement visitIfStatement(IfStatement node) => new IfStatement(
+      _mapToken(node.ifKeyword),
+      _mapToken(node.leftParenthesis),
+      _cloneNode(node.condition),
+      _mapToken(node.rightParenthesis),
+      _cloneNode(node.thenStatement),
+      _mapToken(node.elseKeyword),
+      _cloneNode(node.elseStatement));
+
+  @override
+  ImplementsClause visitImplementsClause(ImplementsClause node) =>
+      new ImplementsClause(
+          _mapToken(node.implementsKeyword), _cloneNodeList(node.interfaces));
+
+  @override
+  ImportDirective visitImportDirective(ImportDirective node) =>
+      new ImportDirective(
+          _cloneNode(node.documentationComment),
+          _cloneNodeList(node.metadata),
+          _mapToken(node.keyword),
+          _cloneNode(node.uri),
+          _cloneNodeList(node.configurations),
+          _mapToken(node.deferredKeyword),
+          _mapToken(node.asKeyword),
+          _cloneNode(node.prefix),
+          _cloneNodeList(node.combinators),
+          _mapToken(node.semicolon));
+
+  @override
+  IndexExpression visitIndexExpression(IndexExpression node) {
+    Token period = _mapToken(node.period);
+    IndexExpression copy;
+    if (period == null) {
+      copy = new IndexExpression.forTarget(
+          _cloneNode(node.target),
+          _mapToken(node.leftBracket),
+          _cloneNode(node.index),
+          _mapToken(node.rightBracket));
+    } else {
+      copy = new IndexExpression.forCascade(period, _mapToken(node.leftBracket),
+          _cloneNode(node.index), _mapToken(node.rightBracket));
+    }
+    copy.auxiliaryElements = node.auxiliaryElements;
+    copy.propagatedElement = node.propagatedElement;
+    copy.propagatedType = node.propagatedType;
+    copy.staticElement = node.staticElement;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  InstanceCreationExpression visitInstanceCreationExpression(
+      InstanceCreationExpression node) {
+    InstanceCreationExpression copy = new InstanceCreationExpression(
+        _mapToken(node.keyword),
+        _cloneNode(node.constructorName),
+        _cloneNode(node.argumentList));
+    copy.propagatedType = node.propagatedType;
+    copy.staticElement = node.staticElement;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  IntegerLiteral visitIntegerLiteral(IntegerLiteral node) {
+    IntegerLiteral copy =
+        new IntegerLiteral(_mapToken(node.literal), node.value);
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  InterpolationExpression visitInterpolationExpression(
+          InterpolationExpression node) =>
+      new InterpolationExpression(_mapToken(node.leftBracket),
+          _cloneNode(node.expression), _mapToken(node.rightBracket));
+
+  @override
+  InterpolationString visitInterpolationString(InterpolationString node) =>
+      new InterpolationString(_mapToken(node.contents), node.value);
+
+  @override
+  IsExpression visitIsExpression(IsExpression node) {
+    IsExpression copy = new IsExpression(
+        _cloneNode(node.expression),
+        _mapToken(node.isOperator),
+        _mapToken(node.notOperator),
+        _cloneNode(node.type));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  Label visitLabel(Label node) =>
+      new Label(_cloneNode(node.label), _mapToken(node.colon));
+
+  @override
+  LabeledStatement visitLabeledStatement(LabeledStatement node) =>
+      new LabeledStatement(
+          _cloneNodeList(node.labels), _cloneNode(node.statement));
+
+  @override
+  LibraryDirective visitLibraryDirective(LibraryDirective node) =>
+      new LibraryDirective(
+          _cloneNode(node.documentationComment),
+          _cloneNodeList(node.metadata),
+          _mapToken(node.libraryKeyword),
+          _cloneNode(node.name),
+          _mapToken(node.semicolon));
+
+  @override
+  LibraryIdentifier visitLibraryIdentifier(LibraryIdentifier node) {
+    LibraryIdentifier copy =
+        new LibraryIdentifier(_cloneNodeList(node.components));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  ListLiteral visitListLiteral(ListLiteral node) {
+    ListLiteral copy = new ListLiteral(
+        _mapToken(node.constKeyword),
+        _cloneNode(node.typeArguments),
+        _mapToken(node.leftBracket),
+        _cloneNodeList(node.elements),
+        _mapToken(node.rightBracket));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  MapLiteral visitMapLiteral(MapLiteral node) {
+    MapLiteral copy = new MapLiteral(
+        _mapToken(node.constKeyword),
+        _cloneNode(node.typeArguments),
+        _mapToken(node.leftBracket),
+        _cloneNodeList(node.entries),
+        _mapToken(node.rightBracket));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  MapLiteralEntry visitMapLiteralEntry(MapLiteralEntry node) =>
+      new MapLiteralEntry(_cloneNode(node.key), _mapToken(node.separator),
+          _cloneNode(node.value));
+
+  @override
+  MethodDeclaration visitMethodDeclaration(MethodDeclaration node) =>
+      new MethodDeclaration(
+          _cloneNode(node.documentationComment),
+          _cloneNodeList(node.metadata),
+          _mapToken(node.externalKeyword),
+          _mapToken(node.modifierKeyword),
+          _cloneNode(node.returnType),
+          _mapToken(node.propertyKeyword),
+          _mapToken(node.operatorKeyword),
+          _cloneNode(node.name),
+          _cloneNode(node.typeParameters),
+          _cloneNode(node.parameters),
+          _cloneNode(node.body));
+
+  @override
+  MethodInvocation visitMethodInvocation(MethodInvocation node) {
+    MethodInvocation copy = new MethodInvocation(
+        _cloneNode(node.target),
+        _mapToken(node.operator),
+        _cloneNode(node.methodName),
+        _cloneNode(node.typeArguments),
+        _cloneNode(node.argumentList));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  NamedExpression visitNamedExpression(NamedExpression node) {
+    NamedExpression copy =
+        new NamedExpression(_cloneNode(node.name), _cloneNode(node.expression));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  AstNode visitNativeClause(NativeClause node) =>
+      new NativeClause(_mapToken(node.nativeKeyword), _cloneNode(node.name));
+
+  @override
+  NativeFunctionBody visitNativeFunctionBody(NativeFunctionBody node) =>
+      new NativeFunctionBody(_mapToken(node.nativeKeyword),
+          _cloneNode(node.stringLiteral), _mapToken(node.semicolon));
+
+  @override
+  NullLiteral visitNullLiteral(NullLiteral node) {
+    NullLiteral copy = new NullLiteral(_mapToken(node.literal));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  ParenthesizedExpression visitParenthesizedExpression(
+      ParenthesizedExpression node) {
+    ParenthesizedExpression copy = new ParenthesizedExpression(
+        _mapToken(node.leftParenthesis),
+        _cloneNode(node.expression),
+        _mapToken(node.rightParenthesis));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  PartDirective visitPartDirective(PartDirective node) {
+    PartDirective copy = new PartDirective(
+        _cloneNode(node.documentationComment),
+        _cloneNodeList(node.metadata),
+        _mapToken(node.partKeyword),
+        _cloneNode(node.uri),
+        _mapToken(node.semicolon));
+    copy.element = node.element;
+    return copy;
+  }
+
+  @override
+  PartOfDirective visitPartOfDirective(PartOfDirective node) {
+    PartOfDirective copy = new PartOfDirective(
+        _cloneNode(node.documentationComment),
+        _cloneNodeList(node.metadata),
+        _mapToken(node.partKeyword),
+        _mapToken(node.ofKeyword),
+        _cloneNode(node.libraryName),
+        _mapToken(node.semicolon));
+    copy.element = node.element;
+    return copy;
+  }
+
+  @override
+  PostfixExpression visitPostfixExpression(PostfixExpression node) {
+    PostfixExpression copy = new PostfixExpression(
+        _cloneNode(node.operand), _mapToken(node.operator));
+    copy.propagatedElement = node.propagatedElement;
+    copy.propagatedType = node.propagatedType;
+    copy.staticElement = node.staticElement;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  PrefixedIdentifier visitPrefixedIdentifier(PrefixedIdentifier node) {
+    PrefixedIdentifier copy = new PrefixedIdentifier(_cloneNode(node.prefix),
+        _mapToken(node.period), _cloneNode(node.identifier));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  PrefixExpression visitPrefixExpression(PrefixExpression node) {
+    PrefixExpression copy = new PrefixExpression(
+        _mapToken(node.operator), _cloneNode(node.operand));
+    copy.propagatedElement = node.propagatedElement;
+    copy.propagatedType = node.propagatedType;
+    copy.staticElement = node.staticElement;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  PropertyAccess visitPropertyAccess(PropertyAccess node) {
+    PropertyAccess copy = new PropertyAccess(_cloneNode(node.target),
+        _mapToken(node.operator), _cloneNode(node.propertyName));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
+      RedirectingConstructorInvocation node) {
+    RedirectingConstructorInvocation copy =
+        new RedirectingConstructorInvocation(
+            _mapToken(node.thisKeyword),
+            _mapToken(node.period),
+            _cloneNode(node.constructorName),
+            _cloneNode(node.argumentList));
+    copy.staticElement = node.staticElement;
+    return copy;
+  }
+
+  @override
+  RethrowExpression visitRethrowExpression(RethrowExpression node) {
+    RethrowExpression copy =
+        new RethrowExpression(_mapToken(node.rethrowKeyword));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  ReturnStatement visitReturnStatement(ReturnStatement node) =>
+      new ReturnStatement(_mapToken(node.returnKeyword),
+          _cloneNode(node.expression), _mapToken(node.semicolon));
+
+  @override
+  ScriptTag visitScriptTag(ScriptTag node) =>
+      new ScriptTag(_mapToken(node.scriptTag));
+
+  @override
+  ShowCombinator visitShowCombinator(ShowCombinator node) => new ShowCombinator(
+      _mapToken(node.keyword), _cloneNodeList(node.shownNames));
+
+  @override
+  SimpleFormalParameter visitSimpleFormalParameter(
+          SimpleFormalParameter node) =>
+      new SimpleFormalParameter(
+          _cloneNode(node.documentationComment),
+          _cloneNodeList(node.metadata),
+          _mapToken(node.keyword),
+          _cloneNode(node.type),
+          _cloneNode(node.identifier));
+
+  @override
+  SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
+    Token mappedToken = _mapToken(node.token);
+    if (mappedToken == null) {
+      // This only happens for SimpleIdentifiers created by the parser as part
+      // of scanning documentation comments (the tokens for those identifiers
+      // are not in the original token stream and hence do not get copied).
+      // This extra check can be removed if the scanner is changed to scan
+      // documentation comments for the parser.
+      mappedToken = node.token;
+    }
+    SimpleIdentifier copy = new SimpleIdentifier(mappedToken);
+    copy.auxiliaryElements = node.auxiliaryElements;
+    copy.propagatedElement = node.propagatedElement;
+    copy.propagatedType = node.propagatedType;
+    copy.staticElement = node.staticElement;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  SimpleStringLiteral visitSimpleStringLiteral(SimpleStringLiteral node) {
+    SimpleStringLiteral copy =
+        new SimpleStringLiteral(_mapToken(node.literal), node.value);
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  StringInterpolation visitStringInterpolation(StringInterpolation node) {
+    StringInterpolation copy =
+        new StringInterpolation(_cloneNodeList(node.elements));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  SuperConstructorInvocation visitSuperConstructorInvocation(
+      SuperConstructorInvocation node) {
+    SuperConstructorInvocation copy = new SuperConstructorInvocation(
+        _mapToken(node.superKeyword),
+        _mapToken(node.period),
+        _cloneNode(node.constructorName),
+        _cloneNode(node.argumentList));
+    copy.staticElement = node.staticElement;
+    return copy;
+  }
+
+  @override
+  SuperExpression visitSuperExpression(SuperExpression node) {
+    SuperExpression copy = new SuperExpression(_mapToken(node.superKeyword));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  SwitchCase visitSwitchCase(SwitchCase node) => new SwitchCase(
+      _cloneNodeList(node.labels),
+      _mapToken(node.keyword),
+      _cloneNode(node.expression),
+      _mapToken(node.colon),
+      _cloneNodeList(node.statements));
+
+  @override
+  SwitchDefault visitSwitchDefault(SwitchDefault node) => new SwitchDefault(
+      _cloneNodeList(node.labels),
+      _mapToken(node.keyword),
+      _mapToken(node.colon),
+      _cloneNodeList(node.statements));
+
+  @override
+  SwitchStatement visitSwitchStatement(SwitchStatement node) =>
+      new SwitchStatement(
+          _mapToken(node.switchKeyword),
+          _mapToken(node.leftParenthesis),
+          _cloneNode(node.expression),
+          _mapToken(node.rightParenthesis),
+          _mapToken(node.leftBracket),
+          _cloneNodeList(node.members),
+          _mapToken(node.rightBracket));
+
+  @override
+  AstNode visitSymbolLiteral(SymbolLiteral node) {
+    SymbolLiteral copy = new SymbolLiteral(
+        _mapToken(node.poundSign), _mapTokens(node.components));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  ThisExpression visitThisExpression(ThisExpression node) {
+    ThisExpression copy = new ThisExpression(_mapToken(node.thisKeyword));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  ThrowExpression visitThrowExpression(ThrowExpression node) {
+    ThrowExpression copy = new ThrowExpression(
+        _mapToken(node.throwKeyword), _cloneNode(node.expression));
+    copy.propagatedType = node.propagatedType;
+    copy.staticType = node.staticType;
+    return copy;
+  }
+
+  @override
+  TopLevelVariableDeclaration visitTopLevelVariableDeclaration(
+          TopLevelVariableDeclaration node) =>
+      new TopLevelVariableDeclaration(
+          _cloneNode(node.documentationComment),
+          _cloneNodeList(node.metadata),
+          _cloneNode(node.variables),
+          _mapToken(node.semicolon));
+
+  @override
+  TryStatement visitTryStatement(TryStatement node) => new TryStatement(
+      _mapToken(node.tryKeyword),
+      _cloneNode(node.body),
+      _cloneNodeList(node.catchClauses),
+      _mapToken(node.finallyKeyword),
+      _cloneNode(node.finallyBlock));
+
+  @override
+  TypeArgumentList visitTypeArgumentList(TypeArgumentList node) =>
+      new TypeArgumentList(_mapToken(node.leftBracket),
+          _cloneNodeList(node.arguments), _mapToken(node.rightBracket));
+
+  @override
+  TypeName visitTypeName(TypeName node) {
+    TypeName copy =
+        new TypeName(_cloneNode(node.name), _cloneNode(node.typeArguments));
+    copy.type = node.type;
+    return copy;
+  }
+
+  @override
+  TypeParameter visitTypeParameter(TypeParameter node) => new TypeParameter(
+      _cloneNode(node.documentationComment),
+      _cloneNodeList(node.metadata),
+      _cloneNode(node.name),
+      _mapToken(node.extendsKeyword),
+      _cloneNode(node.bound));
+
+  @override
+  TypeParameterList visitTypeParameterList(TypeParameterList node) =>
+      new TypeParameterList(_mapToken(node.leftBracket),
+          _cloneNodeList(node.typeParameters), _mapToken(node.rightBracket));
+
+  @override
+  VariableDeclaration visitVariableDeclaration(VariableDeclaration node) =>
+      new VariableDeclaration(_cloneNode(node.name), _mapToken(node.equals),
+          _cloneNode(node.initializer));
+
+  @override
+  VariableDeclarationList visitVariableDeclarationList(
+          VariableDeclarationList node) =>
+      new VariableDeclarationList(
+          null,
+          _cloneNodeList(node.metadata),
+          _mapToken(node.keyword),
+          _cloneNode(node.type),
+          _cloneNodeList(node.variables));
+
+  @override
+  VariableDeclarationStatement visitVariableDeclarationStatement(
+          VariableDeclarationStatement node) =>
+      new VariableDeclarationStatement(
+          _cloneNode(node.variables), _mapToken(node.semicolon));
+
+  @override
+  WhileStatement visitWhileStatement(WhileStatement node) => new WhileStatement(
+      _mapToken(node.whileKeyword),
+      _mapToken(node.leftParenthesis),
+      _cloneNode(node.condition),
+      _mapToken(node.rightParenthesis),
+      _cloneNode(node.body));
+
+  @override
+  WithClause visitWithClause(WithClause node) => new WithClause(
+      _mapToken(node.withKeyword), _cloneNodeList(node.mixinTypes));
+
+  @override
+  YieldStatement visitYieldStatement(YieldStatement node) => new YieldStatement(
+      _mapToken(node.yieldKeyword),
+      _mapToken(node.star),
+      _cloneNode(node.expression),
+      _mapToken(node.semicolon));
+
+  AstNode _cloneNode(AstNode node) {
+    if (node == null) {
+      return null;
+    }
+    if (identical(node, _oldNode)) {
+      return _newNode;
+    }
+    return node.accept(this) as AstNode;
+  }
+
+  List _cloneNodeList(NodeList nodes) {
+    List clonedNodes = new List();
+    for (AstNode node in nodes) {
+      clonedNodes.add(_cloneNode(node));
+    }
+    return clonedNodes;
+  }
+
+  Token _mapToken(Token oldToken) {
+    if (oldToken == null) {
+      return null;
+    }
+    return _tokenMap.get(oldToken);
+  }
+
+  List<Token> _mapTokens(List<Token> oldTokens) {
+    List<Token> newTokens = new List<Token>(oldTokens.length);
+    for (int index = 0; index < newTokens.length; index++) {
+      newTokens[index] = _mapToken(oldTokens[index]);
+    }
+    return newTokens;
+  }
+}
+
+/**
+ * An object used to locate the [AstNode] associated with a source range, given
+ * the AST structure built from the source. More specifically, they will return
+ * the [AstNode] with the shortest length whose source range completely
+ * encompasses the specified range.
+ */
+class NodeLocator extends UnifyingAstVisitor<Object> {
+  /**
+   * The start offset of the range used to identify the node.
+   */
+  int _startOffset = 0;
+
+  /**
+   * The end offset of the range used to identify the node.
+   */
+  int _endOffset = 0;
+
+  /**
+   * The element that was found that corresponds to the given source range, or
+   * `null` if there is no such element.
+   */
+  AstNode _foundNode;
+
+  /**
+   * Initialize a newly created locator to locate an [AstNode] by locating the
+   * node within an AST structure that corresponds to the given range of
+   * characters (between the [startOffset] and [endOffset] in the source.
+   */
+  NodeLocator(int startOffset, [int endOffset])
+      : this._startOffset = startOffset,
+        this._endOffset = endOffset == null ? startOffset : endOffset;
+
+  /**
+   * Return the node that was found that corresponds to the given source range
+   * or `null` if there is no such node.
+   */
+  AstNode get foundNode => _foundNode;
+
+  /**
+   * Search within the given AST [node] for an identifier representing an
+   * element in the specified source range. Return the element that was found,
+   * or `null` if no element was found.
+   */
+  AstNode searchWithin(AstNode node) {
+    if (node == null) {
+      return null;
+    }
+    try {
+      node.accept(this);
+    } on NodeLocator_NodeFoundException {
+      // A node with the right source position was found.
+    } catch (exception, stackTrace) {
+      AnalysisEngine.instance.logger.logInformation(
+          "Unable to locate element at offset ($_startOffset - $_endOffset)",
+          new CaughtException(exception, stackTrace));
+      return null;
+    }
+    return _foundNode;
+  }
+
+  @override
+  Object visitNode(AstNode node) {
+    Token beginToken = node.beginToken;
+    Token endToken = node.endToken;
+    // Don't include synthetic tokens.
+    while (endToken != beginToken) {
+      if (endToken.type == TokenType.EOF || !endToken.isSynthetic) {
+        break;
+      }
+      endToken = endToken.previous;
+    }
+    int end = endToken.end;
+    int start = node.offset;
+    if (end < _startOffset) {
+      return null;
+    }
+    if (start > _endOffset) {
+      return null;
+    }
+    try {
+      node.visitChildren(this);
+    } on NodeLocator_NodeFoundException {
+      rethrow;
+    } catch (exception, stackTrace) {
+      // Ignore the exception and proceed in order to visit the rest of the
+      // structure.
+      AnalysisEngine.instance.logger.logInformation(
+          "Exception caught while traversing an AST structure.",
+          new CaughtException(exception, stackTrace));
+    }
+    if (start <= _startOffset && _endOffset <= end) {
+      _foundNode = node;
+      throw new NodeLocator_NodeFoundException();
+    }
+    return null;
+  }
+}
+
+/**
+ * An object used to locate the [AstNode] associated with a source range.
+ * More specifically, they will return the deepest [AstNode] which completely
+ * encompasses the specified range.
+ */
+class NodeLocator2 extends UnifyingAstVisitor<Object> {
+  /**
+   * The inclusive start offset of the range used to identify the node.
+   */
+  int _startOffset = 0;
+
+  /**
+   * The inclusive end offset of the range used to identify the node.
+   */
+  int _endOffset = 0;
+
+  /**
+   * The found node or `null` if there is no such node.
+   */
+  AstNode _foundNode;
+
+  /**
+   * Initialize a newly created locator to locate the deepest [AstNode] for
+   * which `node.offset <= [startOffset]` and `[endOffset] < node.end`.
+   *
+   * If [endOffset] is not provided, then it is considered the same as the
+   * given [startOffset].
+   */
+  NodeLocator2(int startOffset, [int endOffset])
+      : this._startOffset = startOffset,
+        this._endOffset = endOffset == null ? startOffset : endOffset;
+
+  /**
+   * Search within the given AST [node] and return the node that was found,
+   * or `null` if no node was found.
+   */
+  AstNode searchWithin(AstNode node) {
+    if (node == null) {
+      return null;
+    }
+    try {
+      node.accept(this);
+    } on NodeLocator_NodeFoundException {} catch (exception, stackTrace) {
+      AnalysisEngine.instance.logger.logInformation(
+          "Unable to locate element at offset ($_startOffset - $_endOffset)",
+          new CaughtException(exception, stackTrace));
+      return null;
+    }
+    return _foundNode;
+  }
+
+  @override
+  Object visitNode(AstNode node) {
+    Token beginToken = node.beginToken;
+    Token endToken = node.endToken;
+    // Don't include synthetic tokens.
+    while (endToken != beginToken) {
+      if (endToken.type == TokenType.EOF || !endToken.isSynthetic) {
+        break;
+      }
+      endToken = endToken.previous;
+    }
+    int end = endToken.end;
+    int start = node.offset;
+    if (end <= _startOffset) {
+      return null;
+    }
+    if (start > _endOffset) {
+      return null;
+    }
+    try {
+      node.visitChildren(this);
+    } on NodeLocator_NodeFoundException {
+      rethrow;
+    } catch (exception, stackTrace) {
+      // Ignore the exception and proceed in order to visit the rest of the
+      // structure.
+      AnalysisEngine.instance.logger.logInformation(
+          "Exception caught while traversing an AST structure.",
+          new CaughtException(exception, stackTrace));
+    }
+    if (start <= _startOffset && _endOffset < end) {
+      _foundNode = node;
+      throw new NodeLocator_NodeFoundException();
+    }
+    return null;
+  }
+}
+
+/**
+ * An exception used by [NodeLocator] to cancel visiting after a node has been
+ * found.
+ */
+class NodeLocator_NodeFoundException extends RuntimeException {}
+
+/**
+ * An object that will replace one child node in an AST node with another node.
+ */
+class NodeReplacer implements AstVisitor<bool> {
+  /**
+   * The node being replaced.
+   */
+  final AstNode _oldNode;
+
+  /**
+   * The node that is replacing the old node.
+   */
+  final AstNode _newNode;
+
+  /**
+   * Initialize a newly created node locator to replace the [_oldNode] with the
+   * [_newNode].
+   */
+  NodeReplacer(this._oldNode, this._newNode);
+
+  @override
+  bool visitAdjacentStrings(AdjacentStrings node) {
+    if (_replaceInList(node.strings)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  bool visitAnnotatedNode(AnnotatedNode node) {
+    if (identical(node.documentationComment, _oldNode)) {
+      node.documentationComment = _newNode as Comment;
+      return true;
+    } else if (_replaceInList(node.metadata)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitAnnotation(Annotation node) {
+    if (identical(node.arguments, _oldNode)) {
+      node.arguments = _newNode as ArgumentList;
+      return true;
+    } else if (identical(node.constructorName, _oldNode)) {
+      node.constructorName = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.name, _oldNode)) {
+      node.name = _newNode as Identifier;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitArgumentList(ArgumentList node) {
+    if (_replaceInList(node.arguments)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitAsExpression(AsExpression node) {
+    if (identical(node.expression, _oldNode)) {
+      node.expression = _newNode as Expression;
+      return true;
+    } else if (identical(node.type, _oldNode)) {
+      node.type = _newNode as TypeName;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitAssertStatement(AssertStatement node) {
+    if (identical(node.condition, _oldNode)) {
+      node.condition = _newNode as Expression;
+      return true;
+    }
+    if (identical(node.message, _oldNode)) {
+      node.message = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitAssignmentExpression(AssignmentExpression node) {
+    if (identical(node.leftHandSide, _oldNode)) {
+      node.leftHandSide = _newNode as Expression;
+      return true;
+    } else if (identical(node.rightHandSide, _oldNode)) {
+      node.rightHandSide = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitAwaitExpression(AwaitExpression node) {
+    if (identical(node.expression, _oldNode)) {
+      node.expression = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitBinaryExpression(BinaryExpression node) {
+    if (identical(node.leftOperand, _oldNode)) {
+      node.leftOperand = _newNode as Expression;
+      return true;
+    } else if (identical(node.rightOperand, _oldNode)) {
+      node.rightOperand = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitBlock(Block node) {
+    if (_replaceInList(node.statements)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitBlockFunctionBody(BlockFunctionBody node) {
+    if (identical(node.block, _oldNode)) {
+      node.block = _newNode as Block;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitBooleanLiteral(BooleanLiteral node) => visitNode(node);
+
+  @override
+  bool visitBreakStatement(BreakStatement node) {
+    if (identical(node.label, _oldNode)) {
+      node.label = _newNode as SimpleIdentifier;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitCascadeExpression(CascadeExpression node) {
+    if (identical(node.target, _oldNode)) {
+      node.target = _newNode as Expression;
+      return true;
+    } else if (_replaceInList(node.cascadeSections)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitCatchClause(CatchClause node) {
+    if (identical(node.exceptionType, _oldNode)) {
+      node.exceptionType = _newNode as TypeName;
+      return true;
+    } else if (identical(node.exceptionParameter, _oldNode)) {
+      node.exceptionParameter = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.stackTraceParameter, _oldNode)) {
+      node.stackTraceParameter = _newNode as SimpleIdentifier;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitClassDeclaration(ClassDeclaration node) {
+    if (identical(node.name, _oldNode)) {
+      node.name = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.typeParameters, _oldNode)) {
+      node.typeParameters = _newNode as TypeParameterList;
+      return true;
+    } else if (identical(node.extendsClause, _oldNode)) {
+      node.extendsClause = _newNode as ExtendsClause;
+      return true;
+    } else if (identical(node.withClause, _oldNode)) {
+      node.withClause = _newNode as WithClause;
+      return true;
+    } else if (identical(node.implementsClause, _oldNode)) {
+      node.implementsClause = _newNode as ImplementsClause;
+      return true;
+    } else if (identical(node.nativeClause, _oldNode)) {
+      node.nativeClause = _newNode as NativeClause;
+      return true;
+    } else if (_replaceInList(node.members)) {
+      return true;
+    }
+    return visitAnnotatedNode(node);
+  }
+
+  @override
+  bool visitClassTypeAlias(ClassTypeAlias node) {
+    if (identical(node.name, _oldNode)) {
+      node.name = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.typeParameters, _oldNode)) {
+      node.typeParameters = _newNode as TypeParameterList;
+      return true;
+    } else if (identical(node.superclass, _oldNode)) {
+      node.superclass = _newNode as TypeName;
+      return true;
+    } else if (identical(node.withClause, _oldNode)) {
+      node.withClause = _newNode as WithClause;
+      return true;
+    } else if (identical(node.implementsClause, _oldNode)) {
+      node.implementsClause = _newNode as ImplementsClause;
+      return true;
+    }
+    return visitAnnotatedNode(node);
+  }
+
+  @override
+  bool visitComment(Comment node) {
+    if (_replaceInList(node.references)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitCommentReference(CommentReference node) {
+    if (identical(node.identifier, _oldNode)) {
+      node.identifier = _newNode as Identifier;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitCompilationUnit(CompilationUnit node) {
+    if (identical(node.scriptTag, _oldNode)) {
+      node.scriptTag = _newNode as ScriptTag;
+      return true;
+    } else if (_replaceInList(node.directives)) {
+      return true;
+    } else if (_replaceInList(node.declarations)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitConditionalExpression(ConditionalExpression node) {
+    if (identical(node.condition, _oldNode)) {
+      node.condition = _newNode as Expression;
+      return true;
+    } else if (identical(node.thenExpression, _oldNode)) {
+      node.thenExpression = _newNode as Expression;
+      return true;
+    } else if (identical(node.elseExpression, _oldNode)) {
+      node.elseExpression = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitConfiguration(Configuration node) {
+    if (identical(node.name, _oldNode)) {
+      node.name = _newNode as DottedName;
+      return true;
+    } else if (identical(node.value, _oldNode)) {
+      node.value = _newNode as StringLiteral;
+      return true;
+    } else if (identical(node.libraryUri, _oldNode)) {
+      node.libraryUri = _newNode as StringLiteral;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitConstructorDeclaration(ConstructorDeclaration node) {
+    if (identical(node.returnType, _oldNode)) {
+      node.returnType = _newNode as Identifier;
+      return true;
+    } else if (identical(node.name, _oldNode)) {
+      node.name = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.parameters, _oldNode)) {
+      node.parameters = _newNode as FormalParameterList;
+      return true;
+    } else if (identical(node.redirectedConstructor, _oldNode)) {
+      node.redirectedConstructor = _newNode as ConstructorName;
+      return true;
+    } else if (identical(node.body, _oldNode)) {
+      node.body = _newNode as FunctionBody;
+      return true;
+    } else if (_replaceInList(node.initializers)) {
+      return true;
+    }
+    return visitAnnotatedNode(node);
+  }
+
+  @override
+  bool visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+    if (identical(node.fieldName, _oldNode)) {
+      node.fieldName = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.expression, _oldNode)) {
+      node.expression = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitConstructorName(ConstructorName node) {
+    if (identical(node.type, _oldNode)) {
+      node.type = _newNode as TypeName;
+      return true;
+    } else if (identical(node.name, _oldNode)) {
+      node.name = _newNode as SimpleIdentifier;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitContinueStatement(ContinueStatement node) {
+    if (identical(node.label, _oldNode)) {
+      node.label = _newNode as SimpleIdentifier;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitDeclaredIdentifier(DeclaredIdentifier node) {
+    if (identical(node.type, _oldNode)) {
+      node.type = _newNode as TypeName;
+      return true;
+    } else if (identical(node.identifier, _oldNode)) {
+      node.identifier = _newNode as SimpleIdentifier;
+      return true;
+    }
+    return visitAnnotatedNode(node);
+  }
+
+  @override
+  bool visitDefaultFormalParameter(DefaultFormalParameter node) {
+    if (identical(node.parameter, _oldNode)) {
+      node.parameter = _newNode as NormalFormalParameter;
+      return true;
+    } else if (identical(node.defaultValue, _oldNode)) {
+      node.defaultValue = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitDoStatement(DoStatement node) {
+    if (identical(node.body, _oldNode)) {
+      node.body = _newNode as Statement;
+      return true;
+    } else if (identical(node.condition, _oldNode)) {
+      node.condition = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitDottedName(DottedName node) {
+    if (_replaceInList(node.components)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitDoubleLiteral(DoubleLiteral node) => visitNode(node);
+
+  @override
+  bool visitEmptyFunctionBody(EmptyFunctionBody node) => visitNode(node);
+
+  @override
+  bool visitEmptyStatement(EmptyStatement node) => visitNode(node);
+
+  @override
+  bool visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+    if (identical(node.name, _oldNode)) {
+      node.name = _newNode as SimpleIdentifier;
+      return true;
+    }
+    return visitAnnotatedNode(node);
+  }
+
+  @override
+  bool visitEnumDeclaration(EnumDeclaration node) {
+    if (identical(node.name, _oldNode)) {
+      node.name = _newNode as SimpleIdentifier;
+      return true;
+    } else if (_replaceInList(node.constants)) {
+      return true;
+    }
+    return visitAnnotatedNode(node);
+  }
+
+  @override
+  bool visitExportDirective(ExportDirective node) =>
+      visitNamespaceDirective(node);
+
+  @override
+  bool visitExpressionFunctionBody(ExpressionFunctionBody node) {
+    if (identical(node.expression, _oldNode)) {
+      node.expression = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitExpressionStatement(ExpressionStatement node) {
+    if (identical(node.expression, _oldNode)) {
+      node.expression = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitExtendsClause(ExtendsClause node) {
+    if (identical(node.superclass, _oldNode)) {
+      node.superclass = _newNode as TypeName;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitFieldDeclaration(FieldDeclaration node) {
+    if (identical(node.fields, _oldNode)) {
+      node.fields = _newNode as VariableDeclarationList;
+      return true;
+    }
+    return visitAnnotatedNode(node);
+  }
+
+  @override
+  bool visitFieldFormalParameter(FieldFormalParameter node) {
+    if (identical(node.type, _oldNode)) {
+      node.type = _newNode as TypeName;
+      return true;
+    } else if (identical(node.parameters, _oldNode)) {
+      node.parameters = _newNode as FormalParameterList;
+      return true;
+    }
+    return visitNormalFormalParameter(node);
+  }
+
+  @override
+  bool visitForEachStatement(ForEachStatement node) {
+    if (identical(node.loopVariable, _oldNode)) {
+      node.loopVariable = _newNode as DeclaredIdentifier;
+      return true;
+    } else if (identical(node.identifier, _oldNode)) {
+      node.identifier = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.iterable, _oldNode)) {
+      node.iterable = _newNode as Expression;
+      return true;
+    } else if (identical(node.body, _oldNode)) {
+      node.body = _newNode as Statement;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitFormalParameterList(FormalParameterList node) {
+    if (_replaceInList(node.parameters)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitForStatement(ForStatement node) {
+    if (identical(node.variables, _oldNode)) {
+      node.variables = _newNode as VariableDeclarationList;
+      return true;
+    } else if (identical(node.initialization, _oldNode)) {
+      node.initialization = _newNode as Expression;
+      return true;
+    } else if (identical(node.condition, _oldNode)) {
+      node.condition = _newNode as Expression;
+      return true;
+    } else if (identical(node.body, _oldNode)) {
+      node.body = _newNode as Statement;
+      return true;
+    } else if (_replaceInList(node.updaters)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitFunctionDeclaration(FunctionDeclaration node) {
+    if (identical(node.returnType, _oldNode)) {
+      node.returnType = _newNode as TypeName;
+      return true;
+    } else if (identical(node.name, _oldNode)) {
+      node.name = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.functionExpression, _oldNode)) {
+      node.functionExpression = _newNode as FunctionExpression;
+      return true;
+    }
+    return visitAnnotatedNode(node);
+  }
+
+  @override
+  bool visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+    if (identical(node.functionDeclaration, _oldNode)) {
+      node.functionDeclaration = _newNode as FunctionDeclaration;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitFunctionExpression(FunctionExpression node) {
+    if (identical(node.parameters, _oldNode)) {
+      node.parameters = _newNode as FormalParameterList;
+      return true;
+    } else if (identical(node.body, _oldNode)) {
+      node.body = _newNode as FunctionBody;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+    if (identical(node.function, _oldNode)) {
+      node.function = _newNode as Expression;
+      return true;
+    } else if (identical(node.argumentList, _oldNode)) {
+      node.argumentList = _newNode as ArgumentList;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitFunctionTypeAlias(FunctionTypeAlias node) {
+    if (identical(node.returnType, _oldNode)) {
+      node.returnType = _newNode as TypeName;
+      return true;
+    } else if (identical(node.name, _oldNode)) {
+      node.name = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.typeParameters, _oldNode)) {
+      node.typeParameters = _newNode as TypeParameterList;
+      return true;
+    } else if (identical(node.parameters, _oldNode)) {
+      node.parameters = _newNode as FormalParameterList;
+      return true;
+    }
+    return visitAnnotatedNode(node);
+  }
+
+  @override
+  bool visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+    if (identical(node.returnType, _oldNode)) {
+      node.returnType = _newNode as TypeName;
+      return true;
+    } else if (identical(node.parameters, _oldNode)) {
+      node.parameters = _newNode as FormalParameterList;
+      return true;
+    }
+    return visitNormalFormalParameter(node);
+  }
+
+  @override
+  bool visitHideCombinator(HideCombinator node) {
+    if (_replaceInList(node.hiddenNames)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitIfStatement(IfStatement node) {
+    if (identical(node.condition, _oldNode)) {
+      node.condition = _newNode as Expression;
+      return true;
+    } else if (identical(node.thenStatement, _oldNode)) {
+      node.thenStatement = _newNode as Statement;
+      return true;
+    } else if (identical(node.elseStatement, _oldNode)) {
+      node.elseStatement = _newNode as Statement;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitImplementsClause(ImplementsClause node) {
+    if (_replaceInList(node.interfaces)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitImportDirective(ImportDirective node) {
+    if (identical(node.prefix, _oldNode)) {
+      node.prefix = _newNode as SimpleIdentifier;
+      return true;
+    }
+    return visitNamespaceDirective(node);
+  }
+
+  @override
+  bool visitIndexExpression(IndexExpression node) {
+    if (identical(node.target, _oldNode)) {
+      node.target = _newNode as Expression;
+      return true;
+    } else if (identical(node.index, _oldNode)) {
+      node.index = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitInstanceCreationExpression(InstanceCreationExpression node) {
+    if (identical(node.constructorName, _oldNode)) {
+      node.constructorName = _newNode as ConstructorName;
+      return true;
+    } else if (identical(node.argumentList, _oldNode)) {
+      node.argumentList = _newNode as ArgumentList;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitIntegerLiteral(IntegerLiteral node) => visitNode(node);
+
+  @override
+  bool visitInterpolationExpression(InterpolationExpression node) {
+    if (identical(node.expression, _oldNode)) {
+      node.expression = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitInterpolationString(InterpolationString node) => visitNode(node);
+
+  @override
+  bool visitIsExpression(IsExpression node) {
+    if (identical(node.expression, _oldNode)) {
+      node.expression = _newNode as Expression;
+      return true;
+    } else if (identical(node.type, _oldNode)) {
+      node.type = _newNode as TypeName;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitLabel(Label node) {
+    if (identical(node.label, _oldNode)) {
+      node.label = _newNode as SimpleIdentifier;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitLabeledStatement(LabeledStatement node) {
+    if (identical(node.statement, _oldNode)) {
+      node.statement = _newNode as Statement;
+      return true;
+    } else if (_replaceInList(node.labels)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitLibraryDirective(LibraryDirective node) {
+    if (identical(node.name, _oldNode)) {
+      node.name = _newNode as LibraryIdentifier;
+      return true;
+    }
+    return visitAnnotatedNode(node);
+  }
+
+  @override
+  bool visitLibraryIdentifier(LibraryIdentifier node) {
+    if (_replaceInList(node.components)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitListLiteral(ListLiteral node) {
+    if (_replaceInList(node.elements)) {
+      return true;
+    }
+    return visitTypedLiteral(node);
+  }
+
+  @override
+  bool visitMapLiteral(MapLiteral node) {
+    if (_replaceInList(node.entries)) {
+      return true;
+    }
+    return visitTypedLiteral(node);
+  }
+
+  @override
+  bool visitMapLiteralEntry(MapLiteralEntry node) {
+    if (identical(node.key, _oldNode)) {
+      node.key = _newNode as Expression;
+      return true;
+    } else if (identical(node.value, _oldNode)) {
+      node.value = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitMethodDeclaration(MethodDeclaration node) {
+    if (identical(node.returnType, _oldNode)) {
+      node.returnType = _newNode as TypeName;
+      return true;
+    } else if (identical(node.name, _oldNode)) {
+      node.name = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.parameters, _oldNode)) {
+      node.parameters = _newNode as FormalParameterList;
+      return true;
+    } else if (identical(node.body, _oldNode)) {
+      node.body = _newNode as FunctionBody;
+      return true;
+    }
+    return visitAnnotatedNode(node);
+  }
+
+  @override
+  bool visitMethodInvocation(MethodInvocation node) {
+    if (identical(node.target, _oldNode)) {
+      node.target = _newNode as Expression;
+      return true;
+    } else if (identical(node.methodName, _oldNode)) {
+      node.methodName = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.argumentList, _oldNode)) {
+      node.argumentList = _newNode as ArgumentList;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitNamedExpression(NamedExpression node) {
+    if (identical(node.name, _oldNode)) {
+      node.name = _newNode as Label;
+      return true;
+    } else if (identical(node.expression, _oldNode)) {
+      node.expression = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  bool visitNamespaceDirective(NamespaceDirective node) {
+    if (_replaceInList(node.combinators)) {
+      return true;
+    }
+    return visitUriBasedDirective(node);
+  }
+
+  @override
+  bool visitNativeClause(NativeClause node) {
+    if (identical(node.name, _oldNode)) {
+      node.name = _newNode as StringLiteral;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitNativeFunctionBody(NativeFunctionBody node) {
+    if (identical(node.stringLiteral, _oldNode)) {
+      node.stringLiteral = _newNode as StringLiteral;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  bool visitNode(AstNode node) {
+    throw new IllegalArgumentException(
+        "The old node is not a child of it's parent");
+  }
+
+  bool visitNormalFormalParameter(NormalFormalParameter node) {
+    if (identical(node.documentationComment, _oldNode)) {
+      node.documentationComment = _newNode as Comment;
+      return true;
+    } else if (identical(node.identifier, _oldNode)) {
+      node.identifier = _newNode as SimpleIdentifier;
+      return true;
+    } else if (_replaceInList(node.metadata)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitNullLiteral(NullLiteral node) => visitNode(node);
+
+  @override
+  bool visitParenthesizedExpression(ParenthesizedExpression node) {
+    if (identical(node.expression, _oldNode)) {
+      node.expression = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitPartDirective(PartDirective node) => visitUriBasedDirective(node);
+
+  @override
+  bool visitPartOfDirective(PartOfDirective node) {
+    if (identical(node.libraryName, _oldNode)) {
+      node.libraryName = _newNode as LibraryIdentifier;
+      return true;
+    }
+    return visitAnnotatedNode(node);
+  }
+
+  @override
+  bool visitPostfixExpression(PostfixExpression node) {
+    if (identical(node.operand, _oldNode)) {
+      node.operand = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitPrefixedIdentifier(PrefixedIdentifier node) {
+    if (identical(node.prefix, _oldNode)) {
+      node.prefix = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.identifier, _oldNode)) {
+      node.identifier = _newNode as SimpleIdentifier;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitPrefixExpression(PrefixExpression node) {
+    if (identical(node.operand, _oldNode)) {
+      node.operand = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitPropertyAccess(PropertyAccess node) {
+    if (identical(node.target, _oldNode)) {
+      node.target = _newNode as Expression;
+      return true;
+    } else if (identical(node.propertyName, _oldNode)) {
+      node.propertyName = _newNode as SimpleIdentifier;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitRedirectingConstructorInvocation(
+      RedirectingConstructorInvocation node) {
+    if (identical(node.constructorName, _oldNode)) {
+      node.constructorName = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.argumentList, _oldNode)) {
+      node.argumentList = _newNode as ArgumentList;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitRethrowExpression(RethrowExpression node) => visitNode(node);
+
+  @override
+  bool visitReturnStatement(ReturnStatement node) {
+    if (identical(node.expression, _oldNode)) {
+      node.expression = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitScriptTag(ScriptTag scriptTag) => visitNode(scriptTag);
+
+  @override
+  bool visitShowCombinator(ShowCombinator node) {
+    if (_replaceInList(node.shownNames)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitSimpleFormalParameter(SimpleFormalParameter node) {
+    if (identical(node.type, _oldNode)) {
+      node.type = _newNode as TypeName;
+      return true;
+    }
+    return visitNormalFormalParameter(node);
+  }
+
+  @override
+  bool visitSimpleIdentifier(SimpleIdentifier node) => visitNode(node);
+
+  @override
+  bool visitSimpleStringLiteral(SimpleStringLiteral node) => visitNode(node);
+
+  @override
+  bool visitStringInterpolation(StringInterpolation node) {
+    if (_replaceInList(node.elements)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+    if (identical(node.constructorName, _oldNode)) {
+      node.constructorName = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.argumentList, _oldNode)) {
+      node.argumentList = _newNode as ArgumentList;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitSuperExpression(SuperExpression node) => visitNode(node);
+
+  @override
+  bool visitSwitchCase(SwitchCase node) {
+    if (identical(node.expression, _oldNode)) {
+      node.expression = _newNode as Expression;
+      return true;
+    }
+    return visitSwitchMember(node);
+  }
+
+  @override
+  bool visitSwitchDefault(SwitchDefault node) => visitSwitchMember(node);
+
+  bool visitSwitchMember(SwitchMember node) {
+    if (_replaceInList(node.labels)) {
+      return true;
+    } else if (_replaceInList(node.statements)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitSwitchStatement(SwitchStatement node) {
+    if (identical(node.expression, _oldNode)) {
+      node.expression = _newNode as Expression;
+      return true;
+    } else if (_replaceInList(node.members)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitSymbolLiteral(SymbolLiteral node) => visitNode(node);
+
+  @override
+  bool visitThisExpression(ThisExpression node) => visitNode(node);
+
+  @override
+  bool visitThrowExpression(ThrowExpression node) {
+    if (identical(node.expression, _oldNode)) {
+      node.expression = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    if (identical(node.variables, _oldNode)) {
+      node.variables = _newNode as VariableDeclarationList;
+      return true;
+    }
+    return visitAnnotatedNode(node);
+  }
+
+  @override
+  bool visitTryStatement(TryStatement node) {
+    if (identical(node.body, _oldNode)) {
+      node.body = _newNode as Block;
+      return true;
+    } else if (identical(node.finallyBlock, _oldNode)) {
+      node.finallyBlock = _newNode as Block;
+      return true;
+    } else if (_replaceInList(node.catchClauses)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitTypeArgumentList(TypeArgumentList node) {
+    if (_replaceInList(node.arguments)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  bool visitTypedLiteral(TypedLiteral node) {
+    if (identical(node.typeArguments, _oldNode)) {
+      node.typeArguments = _newNode as TypeArgumentList;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitTypeName(TypeName node) {
+    if (identical(node.name, _oldNode)) {
+      node.name = _newNode as Identifier;
+      return true;
+    } else if (identical(node.typeArguments, _oldNode)) {
+      node.typeArguments = _newNode as TypeArgumentList;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitTypeParameter(TypeParameter node) {
+    if (identical(node.name, _oldNode)) {
+      node.name = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.bound, _oldNode)) {
+      node.bound = _newNode as TypeName;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitTypeParameterList(TypeParameterList node) {
+    if (_replaceInList(node.typeParameters)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  bool visitUriBasedDirective(UriBasedDirective node) {
+    if (identical(node.uri, _oldNode)) {
+      node.uri = _newNode as StringLiteral;
+      return true;
+    }
+    return visitAnnotatedNode(node);
+  }
+
+  @override
+  bool visitVariableDeclaration(VariableDeclaration node) {
+    if (identical(node.name, _oldNode)) {
+      node.name = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.initializer, _oldNode)) {
+      node.initializer = _newNode as Expression;
+      return true;
+    }
+    return visitAnnotatedNode(node);
+  }
+
+  @override
+  bool visitVariableDeclarationList(VariableDeclarationList node) {
+    if (identical(node.type, _oldNode)) {
+      node.type = _newNode as TypeName;
+      return true;
+    } else if (_replaceInList(node.variables)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+    if (identical(node.variables, _oldNode)) {
+      node.variables = _newNode as VariableDeclarationList;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitWhileStatement(WhileStatement node) {
+    if (identical(node.condition, _oldNode)) {
+      node.condition = _newNode as Expression;
+      return true;
+    } else if (identical(node.body, _oldNode)) {
+      node.body = _newNode as Statement;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitWithClause(WithClause node) {
+    if (_replaceInList(node.mixinTypes)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
+  bool visitYieldStatement(YieldStatement node) {
+    if (identical(node.expression, _oldNode)) {
+      node.expression = _newNode as Expression;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  bool _replaceInList(NodeList list) {
+    int count = list.length;
+    for (int i = 0; i < count; i++) {
+      if (identical(_oldNode, list[i])) {
+        list[i] = _newNode;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Replace the [oldNode] with the [newNode] in the AST structure containing
+   * the old node. Return `true` if the replacement was successful.
+   *
+   * Throws an [IllegalArgumentException] if either node is `null`, if the old
+   * node does not have a parent node, or if the AST structure has been
+   * corrupted.
+   */
+  static bool replace(AstNode oldNode, AstNode newNode) {
+    if (oldNode == null || newNode == null) {
+      throw new IllegalArgumentException(
+          "The old and new nodes must be non-null");
+    } else if (identical(oldNode, newNode)) {
+      return true;
+    }
+    AstNode parent = oldNode.parent;
+    if (parent == null) {
+      throw new IllegalArgumentException(
+          "The old node is not a child of another node");
+    }
+    NodeReplacer replacer = new NodeReplacer(oldNode, newNode);
+    return parent.accept(replacer);
+  }
+}
+
+/**
+ * Traverse the AST from initial child node to successive parents, building a
+ * collection of local variable and parameter names visible to the initial child
+ * node. In case of name shadowing, the first name seen is the most specific one
+ * so names are not redefined.
+ *
+ * Completion test code coverage is 95%. The two basic blocks that are not
+ * executed cannot be executed. They are included for future reference.
+ */
+class ScopedNameFinder extends GeneralizingAstVisitor<Object> {
+  Declaration _declarationNode;
+
+  AstNode _immediateChild;
+
+  Map<String, SimpleIdentifier> _locals =
+      new HashMap<String, SimpleIdentifier>();
+
+  final int _position;
+
+  bool _referenceIsWithinLocalFunction = false;
+
+  ScopedNameFinder(this._position);
+
+  Declaration get declaration => _declarationNode;
+
+  Map<String, SimpleIdentifier> get locals => _locals;
+
+  @override
+  Object visitBlock(Block node) {
+    _checkStatements(node.statements);
+    return super.visitBlock(node);
+  }
+
+  @override
+  Object visitCatchClause(CatchClause node) {
+    _addToScope(node.exceptionParameter);
+    _addToScope(node.stackTraceParameter);
+    return super.visitCatchClause(node);
+  }
+
+  @override
+  Object visitConstructorDeclaration(ConstructorDeclaration node) {
+    if (!identical(_immediateChild, node.parameters)) {
+      _addParameters(node.parameters.parameters);
+    }
+    _declarationNode = node;
+    return null;
+  }
+
+  @override
+  Object visitFieldDeclaration(FieldDeclaration node) {
+    _declarationNode = node;
+    return null;
+  }
+
+  @override
+  Object visitForEachStatement(ForEachStatement node) {
+    DeclaredIdentifier loopVariable = node.loopVariable;
+    if (loopVariable != null) {
+      _addToScope(loopVariable.identifier);
+    }
+    return super.visitForEachStatement(node);
+  }
+
+  @override
+  Object visitForStatement(ForStatement node) {
+    if (!identical(_immediateChild, node.variables) && node.variables != null) {
+      _addVariables(node.variables.variables);
+    }
+    return super.visitForStatement(node);
+  }
+
+  @override
+  Object visitFunctionDeclaration(FunctionDeclaration node) {
+    if (node.parent is! FunctionDeclarationStatement) {
+      _declarationNode = node;
+      return null;
+    }
+    return super.visitFunctionDeclaration(node);
+  }
+
+  @override
+  Object visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+    _referenceIsWithinLocalFunction = true;
+    return super.visitFunctionDeclarationStatement(node);
+  }
+
+  @override
+  Object visitFunctionExpression(FunctionExpression node) {
+    if (node.parameters != null &&
+        !identical(_immediateChild, node.parameters)) {
+      _addParameters(node.parameters.parameters);
+    }
+    return super.visitFunctionExpression(node);
+  }
+
+  @override
+  Object visitMethodDeclaration(MethodDeclaration node) {
+    _declarationNode = node;
+    if (node.parameters == null) {
+      return null;
+    }
+    if (!identical(_immediateChild, node.parameters)) {
+      _addParameters(node.parameters.parameters);
+    }
+    return null;
+  }
+
+  @override
+  Object visitNode(AstNode node) {
+    _immediateChild = node;
+    AstNode parent = node.parent;
+    if (parent != null) {
+      parent.accept(this);
+    }
+    return null;
+  }
+
+  @override
+  Object visitSwitchMember(SwitchMember node) {
+    _checkStatements(node.statements);
+    return super.visitSwitchMember(node);
+  }
+
+  @override
+  Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    _declarationNode = node;
+    return null;
+  }
+
+  @override
+  Object visitTypeAlias(TypeAlias node) {
+    _declarationNode = node;
+    return null;
+  }
+
+  void _addParameters(NodeList<FormalParameter> vars) {
+    for (FormalParameter var2 in vars) {
+      _addToScope(var2.identifier);
+    }
+  }
+
+  void _addToScope(SimpleIdentifier identifier) {
+    if (identifier != null && _isInRange(identifier)) {
+      String name = identifier.name;
+      if (!_locals.containsKey(name)) {
+        _locals[name] = identifier;
+      }
+    }
+  }
+
+  void _addVariables(NodeList<VariableDeclaration> variables) {
+    for (VariableDeclaration variable in variables) {
+      _addToScope(variable.name);
+    }
+  }
+
+  /**
+   * Check the given list of [statements] for any that come before the immediate
+   * child and that define a name that would be visible to the immediate child.
+   */
+  void _checkStatements(List<Statement> statements) {
+    for (Statement statement in statements) {
+      if (identical(statement, _immediateChild)) {
+        return;
+      }
+      if (statement is VariableDeclarationStatement) {
+        _addVariables(statement.variables.variables);
+      } else if (statement is FunctionDeclarationStatement &&
+          !_referenceIsWithinLocalFunction) {
+        _addToScope(statement.functionDeclaration.name);
+      }
+    }
+  }
+
+  bool _isInRange(AstNode node) {
+    if (_position < 0) {
+      // if source position is not set then all nodes are in range
+      return true;
+      // not reached
+    }
+    return node.end < _position;
+  }
+}
+
+/**
+ * A visitor used to write a source representation of a visited AST node (and
+ * all of it's children) to a writer.
+ */
+class ToSourceVisitor implements AstVisitor<Object> {
+  /**
+   * The writer to which the source is to be written.
+   */
+  final PrintWriter _writer;
+
+  /**
+   * Initialize a newly created visitor to write source code representing the
+   * visited nodes to the given [writer].
+   */
+  ToSourceVisitor(this._writer);
+
+  @override
+  Object visitAdjacentStrings(AdjacentStrings node) {
+    _visitNodeListWithSeparator(node.strings, " ");
+    return null;
+  }
+
+  @override
+  Object visitAnnotation(Annotation node) {
+    _writer.print('@');
+    _visitNode(node.name);
+    _visitNodeWithPrefix(".", node.constructorName);
+    _visitNode(node.arguments);
+    return null;
+  }
+
+  @override
+  Object visitArgumentList(ArgumentList node) {
+    _writer.print('(');
+    _visitNodeListWithSeparator(node.arguments, ", ");
+    _writer.print(')');
+    return null;
+  }
+
+  @override
+  Object visitAsExpression(AsExpression node) {
+    _visitNode(node.expression);
+    _writer.print(" as ");
+    _visitNode(node.type);
+    return null;
+  }
+
+  @override
+  Object visitAssertStatement(AssertStatement node) {
+    _writer.print("assert (");
+    _visitNode(node.condition);
+    if (node.message != null) {
+      _writer.print(', ');
+      _visitNode(node.message);
+    }
+    _writer.print(");");
+    return null;
+  }
+
+  @override
+  Object visitAssignmentExpression(AssignmentExpression node) {
+    _visitNode(node.leftHandSide);
+    _writer.print(' ');
+    _writer.print(node.operator.lexeme);
+    _writer.print(' ');
+    _visitNode(node.rightHandSide);
+    return null;
+  }
+
+  @override
+  Object visitAwaitExpression(AwaitExpression node) {
+    _writer.print("await ");
+    _visitNode(node.expression);
+    return null;
+  }
+
+  @override
+  Object visitBinaryExpression(BinaryExpression node) {
+    _visitNode(node.leftOperand);
+    _writer.print(' ');
+    _writer.print(node.operator.lexeme);
+    _writer.print(' ');
+    _visitNode(node.rightOperand);
+    return null;
+  }
+
+  @override
+  Object visitBlock(Block node) {
+    _writer.print('{');
+    _visitNodeListWithSeparator(node.statements, " ");
+    _writer.print('}');
+    return null;
+  }
+
+  @override
+  Object visitBlockFunctionBody(BlockFunctionBody node) {
+    Token keyword = node.keyword;
+    if (keyword != null) {
+      _writer.print(keyword.lexeme);
+      if (node.star != null) {
+        _writer.print('*');
+      }
+      _writer.print(' ');
+    }
+    _visitNode(node.block);
+    return null;
+  }
+
+  @override
+  Object visitBooleanLiteral(BooleanLiteral node) {
+    _writer.print(node.literal.lexeme);
+    return null;
+  }
+
+  @override
+  Object visitBreakStatement(BreakStatement node) {
+    _writer.print("break");
+    _visitNodeWithPrefix(" ", node.label);
+    _writer.print(";");
+    return null;
+  }
+
+  @override
+  Object visitCascadeExpression(CascadeExpression node) {
+    _visitNode(node.target);
+    _visitNodeList(node.cascadeSections);
+    return null;
+  }
+
+  @override
+  Object visitCatchClause(CatchClause node) {
+    _visitNodeWithPrefix("on ", node.exceptionType);
+    if (node.catchKeyword != null) {
+      if (node.exceptionType != null) {
+        _writer.print(' ');
+      }
+      _writer.print("catch (");
+      _visitNode(node.exceptionParameter);
+      _visitNodeWithPrefix(", ", node.stackTraceParameter);
+      _writer.print(") ");
+    } else {
+      _writer.print(" ");
+    }
+    _visitNode(node.body);
+    return null;
+  }
+
+  @override
+  Object visitClassDeclaration(ClassDeclaration node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _visitTokenWithSuffix(node.abstractKeyword, " ");
+    _writer.print("class ");
+    _visitNode(node.name);
+    _visitNode(node.typeParameters);
+    _visitNodeWithPrefix(" ", node.extendsClause);
+    _visitNodeWithPrefix(" ", node.withClause);
+    _visitNodeWithPrefix(" ", node.implementsClause);
+    _writer.print(" {");
+    _visitNodeListWithSeparator(node.members, " ");
+    _writer.print("}");
+    return null;
+  }
+
+  @override
+  Object visitClassTypeAlias(ClassTypeAlias node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    if (node.abstractKeyword != null) {
+      _writer.print("abstract ");
+    }
+    _writer.print("class ");
+    _visitNode(node.name);
+    _visitNode(node.typeParameters);
+    _writer.print(" = ");
+    _visitNode(node.superclass);
+    _visitNodeWithPrefix(" ", node.withClause);
+    _visitNodeWithPrefix(" ", node.implementsClause);
+    _writer.print(";");
+    return null;
+  }
+
+  @override
+  Object visitComment(Comment node) => null;
+
+  @override
+  Object visitCommentReference(CommentReference node) => null;
+
+  @override
+  Object visitCompilationUnit(CompilationUnit node) {
+    ScriptTag scriptTag = node.scriptTag;
+    NodeList<Directive> directives = node.directives;
+    _visitNode(scriptTag);
+    String prefix = scriptTag == null ? "" : " ";
+    _visitNodeListWithSeparatorAndPrefix(prefix, directives, " ");
+    prefix = scriptTag == null && directives.isEmpty ? "" : " ";
+    _visitNodeListWithSeparatorAndPrefix(prefix, node.declarations, " ");
+    return null;
+  }
+
+  @override
+  Object visitConditionalExpression(ConditionalExpression node) {
+    _visitNode(node.condition);
+    _writer.print(" ? ");
+    _visitNode(node.thenExpression);
+    _writer.print(" : ");
+    _visitNode(node.elseExpression);
+    return null;
+  }
+
+  @override
+  Object visitConfiguration(Configuration node) {
+    _writer.print('if (');
+    _visitNode(node.name);
+    _visitNodeWithPrefix(" == ", node.value);
+    _writer.print(') ');
+    _visitNode(node.libraryUri);
+    return null;
+  }
+
+  @override
+  Object visitConstructorDeclaration(ConstructorDeclaration node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _visitTokenWithSuffix(node.externalKeyword, " ");
+    _visitTokenWithSuffix(node.constKeyword, " ");
+    _visitTokenWithSuffix(node.factoryKeyword, " ");
+    _visitNode(node.returnType);
+    _visitNodeWithPrefix(".", node.name);
+    _visitNode(node.parameters);
+    _visitNodeListWithSeparatorAndPrefix(" : ", node.initializers, ", ");
+    _visitNodeWithPrefix(" = ", node.redirectedConstructor);
+    _visitFunctionWithPrefix(" ", node.body);
+    return null;
+  }
+
+  @override
+  Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+    _visitTokenWithSuffix(node.thisKeyword, ".");
+    _visitNode(node.fieldName);
+    _writer.print(" = ");
+    _visitNode(node.expression);
+    return null;
+  }
+
+  @override
+  Object visitConstructorName(ConstructorName node) {
+    _visitNode(node.type);
+    _visitNodeWithPrefix(".", node.name);
+    return null;
+  }
+
+  @override
+  Object visitContinueStatement(ContinueStatement node) {
+    _writer.print("continue");
+    _visitNodeWithPrefix(" ", node.label);
+    _writer.print(";");
+    return null;
+  }
+
+  @override
+  Object visitDeclaredIdentifier(DeclaredIdentifier node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _visitTokenWithSuffix(node.keyword, " ");
+    _visitNodeWithSuffix(node.type, " ");
+    _visitNode(node.identifier);
+    return null;
+  }
+
+  @override
+  Object visitDefaultFormalParameter(DefaultFormalParameter node) {
+    _visitNode(node.parameter);
+    if (node.separator != null) {
+      _writer.print(" ");
+      _writer.print(node.separator.lexeme);
+      _visitNodeWithPrefix(" ", node.defaultValue);
+    }
+    return null;
+  }
+
+  @override
+  Object visitDoStatement(DoStatement node) {
+    _writer.print("do ");
+    _visitNode(node.body);
+    _writer.print(" while (");
+    _visitNode(node.condition);
+    _writer.print(");");
+    return null;
+  }
+
+  @override
+  Object visitDottedName(DottedName node) {
+    _visitNodeListWithSeparator(node.components, ".");
+    return null;
+  }
+
+  @override
+  Object visitDoubleLiteral(DoubleLiteral node) {
+    _writer.print(node.literal.lexeme);
+    return null;
+  }
+
+  @override
+  Object visitEmptyFunctionBody(EmptyFunctionBody node) {
+    _writer.print(';');
+    return null;
+  }
+
+  @override
+  Object visitEmptyStatement(EmptyStatement node) {
+    _writer.print(';');
+    return null;
+  }
+
+  @override
+  Object visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _visitNode(node.name);
+    return null;
+  }
+
+  @override
+  Object visitEnumDeclaration(EnumDeclaration node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _writer.print("enum ");
+    _visitNode(node.name);
+    _writer.print(" {");
+    _visitNodeListWithSeparator(node.constants, ", ");
+    _writer.print("}");
+    return null;
+  }
+
+  @override
+  Object visitExportDirective(ExportDirective node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _writer.print("export ");
+    _visitNode(node.uri);
+    _visitNodeListWithSeparatorAndPrefix(" ", node.combinators, " ");
+    _writer.print(';');
+    return null;
+  }
+
+  @override
+  Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
+    Token keyword = node.keyword;
+    if (keyword != null) {
+      _writer.print(keyword.lexeme);
+      _writer.print(' ');
+    }
+    _writer.print("=> ");
+    _visitNode(node.expression);
+    if (node.semicolon != null) {
+      _writer.print(';');
+    }
+    return null;
+  }
+
+  @override
+  Object visitExpressionStatement(ExpressionStatement node) {
+    _visitNode(node.expression);
+    _writer.print(';');
+    return null;
+  }
+
+  @override
+  Object visitExtendsClause(ExtendsClause node) {
+    _writer.print("extends ");
+    _visitNode(node.superclass);
+    return null;
+  }
+
+  @override
+  Object visitFieldDeclaration(FieldDeclaration node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _visitTokenWithSuffix(node.staticKeyword, " ");
+    _visitNode(node.fields);
+    _writer.print(";");
+    return null;
+  }
+
+  @override
+  Object visitFieldFormalParameter(FieldFormalParameter node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
+    _visitTokenWithSuffix(node.keyword, " ");
+    _visitNodeWithSuffix(node.type, " ");
+    _writer.print("this.");
+    _visitNode(node.identifier);
+    _visitNode(node.typeParameters);
+    _visitNode(node.parameters);
+    return null;
+  }
+
+  @override
+  Object visitForEachStatement(ForEachStatement node) {
+    DeclaredIdentifier loopVariable = node.loopVariable;
+    if (node.awaitKeyword != null) {
+      _writer.print("await ");
+    }
+    _writer.print("for (");
+    if (loopVariable == null) {
+      _visitNode(node.identifier);
+    } else {
+      _visitNode(loopVariable);
+    }
+    _writer.print(" in ");
+    _visitNode(node.iterable);
+    _writer.print(") ");
+    _visitNode(node.body);
+    return null;
+  }
+
+  @override
+  Object visitFormalParameterList(FormalParameterList node) {
+    String groupEnd = null;
+    _writer.print('(');
+    NodeList<FormalParameter> parameters = node.parameters;
+    int size = parameters.length;
+    for (int i = 0; i < size; i++) {
+      FormalParameter parameter = parameters[i];
+      if (i > 0) {
+        _writer.print(", ");
+      }
+      if (groupEnd == null && parameter is DefaultFormalParameter) {
+        if (parameter.kind == ParameterKind.NAMED) {
+          groupEnd = "}";
+          _writer.print('{');
+        } else {
+          groupEnd = "]";
+          _writer.print('[');
+        }
+      }
+      parameter.accept(this);
+    }
+    if (groupEnd != null) {
+      _writer.print(groupEnd);
+    }
+    _writer.print(')');
+    return null;
+  }
+
+  @override
+  Object visitForStatement(ForStatement node) {
+    Expression initialization = node.initialization;
+    _writer.print("for (");
+    if (initialization != null) {
+      _visitNode(initialization);
+    } else {
+      _visitNode(node.variables);
+    }
+    _writer.print(";");
+    _visitNodeWithPrefix(" ", node.condition);
+    _writer.print(";");
+    _visitNodeListWithSeparatorAndPrefix(" ", node.updaters, ", ");
+    _writer.print(") ");
+    _visitNode(node.body);
+    return null;
+  }
+
+  @override
+  Object visitFunctionDeclaration(FunctionDeclaration node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _visitTokenWithSuffix(node.externalKeyword, " ");
+    _visitNodeWithSuffix(node.returnType, " ");
+    _visitTokenWithSuffix(node.propertyKeyword, " ");
+    _visitNode(node.name);
+    _visitNode(node.functionExpression);
+    return null;
+  }
+
+  @override
+  Object visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+    _visitNode(node.functionDeclaration);
+    return null;
+  }
+
+  @override
+  Object visitFunctionExpression(FunctionExpression node) {
+    _visitNode(node.typeParameters);
+    _visitNode(node.parameters);
+    if (node.body is! EmptyFunctionBody) {
+      _writer.print(' ');
+    }
+    _visitNode(node.body);
+    return null;
+  }
+
+  @override
+  Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+    _visitNode(node.function);
+    _visitNode(node.typeArguments);
+    _visitNode(node.argumentList);
+    return null;
+  }
+
+  @override
+  Object visitFunctionTypeAlias(FunctionTypeAlias node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _writer.print("typedef ");
+    _visitNodeWithSuffix(node.returnType, " ");
+    _visitNode(node.name);
+    _visitNode(node.typeParameters);
+    _visitNode(node.parameters);
+    _writer.print(";");
+    return null;
+  }
+
+  @override
+  Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
+    _visitNodeWithSuffix(node.returnType, " ");
+    _visitNode(node.identifier);
+    _visitNode(node.typeParameters);
+    _visitNode(node.parameters);
+    return null;
+  }
+
+  @override
+  Object visitHideCombinator(HideCombinator node) {
+    _writer.print("hide ");
+    _visitNodeListWithSeparator(node.hiddenNames, ", ");
+    return null;
+  }
+
+  @override
+  Object visitIfStatement(IfStatement node) {
+    _writer.print("if (");
+    _visitNode(node.condition);
+    _writer.print(") ");
+    _visitNode(node.thenStatement);
+    _visitNodeWithPrefix(" else ", node.elseStatement);
+    return null;
+  }
+
+  @override
+  Object visitImplementsClause(ImplementsClause node) {
+    _writer.print("implements ");
+    _visitNodeListWithSeparator(node.interfaces, ", ");
+    return null;
+  }
+
+  @override
+  Object visitImportDirective(ImportDirective node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _writer.print("import ");
+    _visitNode(node.uri);
+    if (node.deferredKeyword != null) {
+      _writer.print(" deferred");
+    }
+    _visitNodeWithPrefix(" as ", node.prefix);
+    _visitNodeListWithSeparatorAndPrefix(" ", node.combinators, " ");
+    _writer.print(';');
+    return null;
+  }
+
+  @override
+  Object visitIndexExpression(IndexExpression node) {
+    if (node.isCascaded) {
+      _writer.print("..");
+    } else {
+      _visitNode(node.target);
+    }
+    _writer.print('[');
+    _visitNode(node.index);
+    _writer.print(']');
+    return null;
+  }
+
+  @override
+  Object visitInstanceCreationExpression(InstanceCreationExpression node) {
+    _visitTokenWithSuffix(node.keyword, " ");
+    _visitNode(node.constructorName);
+    _visitNode(node.argumentList);
+    return null;
+  }
+
+  @override
+  Object visitIntegerLiteral(IntegerLiteral node) {
+    _writer.print(node.literal.lexeme);
+    return null;
+  }
+
+  @override
+  Object visitInterpolationExpression(InterpolationExpression node) {
+    if (node.rightBracket != null) {
+      _writer.print("\${");
+      _visitNode(node.expression);
+      _writer.print("}");
+    } else {
+      _writer.print("\$");
+      _visitNode(node.expression);
+    }
+    return null;
+  }
+
+  @override
+  Object visitInterpolationString(InterpolationString node) {
+    _writer.print(node.contents.lexeme);
+    return null;
+  }
+
+  @override
+  Object visitIsExpression(IsExpression node) {
+    _visitNode(node.expression);
+    if (node.notOperator == null) {
+      _writer.print(" is ");
+    } else {
+      _writer.print(" is! ");
+    }
+    _visitNode(node.type);
+    return null;
+  }
+
+  @override
+  Object visitLabel(Label node) {
+    _visitNode(node.label);
+    _writer.print(":");
+    return null;
+  }
+
+  @override
+  Object visitLabeledStatement(LabeledStatement node) {
+    _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
+    _visitNode(node.statement);
+    return null;
+  }
+
+  @override
+  Object visitLibraryDirective(LibraryDirective node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _writer.print("library ");
+    _visitNode(node.name);
+    _writer.print(';');
+    return null;
+  }
+
+  @override
+  Object visitLibraryIdentifier(LibraryIdentifier node) {
+    _writer.print(node.name);
+    return null;
+  }
+
+  @override
+  Object visitListLiteral(ListLiteral node) {
+    if (node.constKeyword != null) {
+      _writer.print(node.constKeyword.lexeme);
+      _writer.print(' ');
+    }
+    _visitNodeWithSuffix(node.typeArguments, " ");
+    _writer.print("[");
+    _visitNodeListWithSeparator(node.elements, ", ");
+    _writer.print("]");
+    return null;
+  }
+
+  @override
+  Object visitMapLiteral(MapLiteral node) {
+    if (node.constKeyword != null) {
+      _writer.print(node.constKeyword.lexeme);
+      _writer.print(' ');
+    }
+    _visitNodeWithSuffix(node.typeArguments, " ");
+    _writer.print("{");
+    _visitNodeListWithSeparator(node.entries, ", ");
+    _writer.print("}");
+    return null;
+  }
+
+  @override
+  Object visitMapLiteralEntry(MapLiteralEntry node) {
+    _visitNode(node.key);
+    _writer.print(" : ");
+    _visitNode(node.value);
+    return null;
+  }
+
+  @override
+  Object visitMethodDeclaration(MethodDeclaration node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _visitTokenWithSuffix(node.externalKeyword, " ");
+    _visitTokenWithSuffix(node.modifierKeyword, " ");
+    _visitNodeWithSuffix(node.returnType, " ");
+    _visitTokenWithSuffix(node.propertyKeyword, " ");
+    _visitTokenWithSuffix(node.operatorKeyword, " ");
+    _visitNode(node.name);
+    if (!node.isGetter) {
+      _visitNode(node.typeParameters);
+      _visitNode(node.parameters);
+    }
+    _visitFunctionWithPrefix(" ", node.body);
+    return null;
+  }
+
+  @override
+  Object visitMethodInvocation(MethodInvocation node) {
+    if (node.isCascaded) {
+      _writer.print("..");
+    } else {
+      if (node.target != null) {
+        node.target.accept(this);
+        _writer.print(node.operator.lexeme);
+      }
+    }
+    _visitNode(node.methodName);
+    _visitNode(node.typeArguments);
+    _visitNode(node.argumentList);
+    return null;
+  }
+
+  @override
+  Object visitNamedExpression(NamedExpression node) {
+    _visitNode(node.name);
+    _visitNodeWithPrefix(" ", node.expression);
+    return null;
+  }
+
+  @override
+  Object visitNativeClause(NativeClause node) {
+    _writer.print("native ");
+    _visitNode(node.name);
+    return null;
+  }
+
+  @override
+  Object visitNativeFunctionBody(NativeFunctionBody node) {
+    _writer.print("native ");
+    _visitNode(node.stringLiteral);
+    _writer.print(';');
+    return null;
+  }
+
+  @override
+  Object visitNullLiteral(NullLiteral node) {
+    _writer.print("null");
+    return null;
+  }
+
+  @override
+  Object visitParenthesizedExpression(ParenthesizedExpression node) {
+    _writer.print('(');
+    _visitNode(node.expression);
+    _writer.print(')');
+    return null;
+  }
+
+  @override
+  Object visitPartDirective(PartDirective node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _writer.print("part ");
+    _visitNode(node.uri);
+    _writer.print(';');
+    return null;
+  }
+
+  @override
+  Object visitPartOfDirective(PartOfDirective node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _writer.print("part of ");
+    _visitNode(node.libraryName);
+    _writer.print(';');
+    return null;
+  }
+
+  @override
+  Object visitPostfixExpression(PostfixExpression node) {
+    _visitNode(node.operand);
+    _writer.print(node.operator.lexeme);
+    return null;
+  }
+
+  @override
+  Object visitPrefixedIdentifier(PrefixedIdentifier node) {
+    _visitNode(node.prefix);
+    _writer.print('.');
+    _visitNode(node.identifier);
+    return null;
+  }
+
+  @override
+  Object visitPrefixExpression(PrefixExpression node) {
+    _writer.print(node.operator.lexeme);
+    _visitNode(node.operand);
+    return null;
+  }
+
+  @override
+  Object visitPropertyAccess(PropertyAccess node) {
+    if (node.isCascaded) {
+      _writer.print("..");
+    } else {
+      _visitNode(node.target);
+      _writer.print(node.operator.lexeme);
+    }
+    _visitNode(node.propertyName);
+    return null;
+  }
+
+  @override
+  Object visitRedirectingConstructorInvocation(
+      RedirectingConstructorInvocation node) {
+    _writer.print("this");
+    _visitNodeWithPrefix(".", node.constructorName);
+    _visitNode(node.argumentList);
+    return null;
+  }
+
+  @override
+  Object visitRethrowExpression(RethrowExpression node) {
+    _writer.print("rethrow");
+    return null;
+  }
+
+  @override
+  Object visitReturnStatement(ReturnStatement node) {
+    Expression expression = node.expression;
+    if (expression == null) {
+      _writer.print("return;");
+    } else {
+      _writer.print("return ");
+      expression.accept(this);
+      _writer.print(";");
+    }
+    return null;
+  }
+
+  @override
+  Object visitScriptTag(ScriptTag node) {
+    _writer.print(node.scriptTag.lexeme);
+    return null;
+  }
+
+  @override
+  Object visitShowCombinator(ShowCombinator node) {
+    _writer.print("show ");
+    _visitNodeListWithSeparator(node.shownNames, ", ");
+    return null;
+  }
+
+  @override
+  Object visitSimpleFormalParameter(SimpleFormalParameter node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
+    _visitTokenWithSuffix(node.keyword, " ");
+    _visitNodeWithSuffix(node.type, " ");
+    _visitNode(node.identifier);
+    return null;
+  }
+
+  @override
+  Object visitSimpleIdentifier(SimpleIdentifier node) {
+    _writer.print(node.token.lexeme);
+    return null;
+  }
+
+  @override
+  Object visitSimpleStringLiteral(SimpleStringLiteral node) {
+    _writer.print(node.literal.lexeme);
+    return null;
+  }
+
+  @override
+  Object visitStringInterpolation(StringInterpolation node) {
+    _visitNodeList(node.elements);
+    return null;
+  }
+
+  @override
+  Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+    _writer.print("super");
+    _visitNodeWithPrefix(".", node.constructorName);
+    _visitNode(node.argumentList);
+    return null;
+  }
+
+  @override
+  Object visitSuperExpression(SuperExpression node) {
+    _writer.print("super");
+    return null;
+  }
+
+  @override
+  Object visitSwitchCase(SwitchCase node) {
+    _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
+    _writer.print("case ");
+    _visitNode(node.expression);
+    _writer.print(": ");
+    _visitNodeListWithSeparator(node.statements, " ");
+    return null;
+  }
+
+  @override
+  Object visitSwitchDefault(SwitchDefault node) {
+    _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
+    _writer.print("default: ");
+    _visitNodeListWithSeparator(node.statements, " ");
+    return null;
+  }
+
+  @override
+  Object visitSwitchStatement(SwitchStatement node) {
+    _writer.print("switch (");
+    _visitNode(node.expression);
+    _writer.print(") {");
+    _visitNodeListWithSeparator(node.members, " ");
+    _writer.print("}");
+    return null;
+  }
+
+  @override
+  Object visitSymbolLiteral(SymbolLiteral node) {
+    _writer.print("#");
+    List<Token> components = node.components;
+    for (int i = 0; i < components.length; i++) {
+      if (i > 0) {
+        _writer.print(".");
+      }
+      _writer.print(components[i].lexeme);
+    }
+    return null;
+  }
+
+  @override
+  Object visitThisExpression(ThisExpression node) {
+    _writer.print("this");
+    return null;
+  }
+
+  @override
+  Object visitThrowExpression(ThrowExpression node) {
+    _writer.print("throw ");
+    _visitNode(node.expression);
+    return null;
+  }
+
+  @override
+  Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    _visitNodeWithSuffix(node.variables, ";");
+    return null;
+  }
+
+  @override
+  Object visitTryStatement(TryStatement node) {
+    _writer.print("try ");
+    _visitNode(node.body);
+    _visitNodeListWithSeparatorAndPrefix(" ", node.catchClauses, " ");
+    _visitNodeWithPrefix(" finally ", node.finallyBlock);
+    return null;
+  }
+
+  @override
+  Object visitTypeArgumentList(TypeArgumentList node) {
+    _writer.print('<');
+    _visitNodeListWithSeparator(node.arguments, ", ");
+    _writer.print('>');
+    return null;
+  }
+
+  @override
+  Object visitTypeName(TypeName node) {
+    _visitNode(node.name);
+    _visitNode(node.typeArguments);
+    return null;
+  }
+
+  @override
+  Object visitTypeParameter(TypeParameter node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _visitNode(node.name);
+    _visitNodeWithPrefix(" extends ", node.bound);
+    return null;
+  }
+
+  @override
+  Object visitTypeParameterList(TypeParameterList node) {
+    _writer.print('<');
+    _visitNodeListWithSeparator(node.typeParameters, ", ");
+    _writer.print('>');
+    return null;
+  }
+
+  @override
+  Object visitVariableDeclaration(VariableDeclaration node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _visitNode(node.name);
+    _visitNodeWithPrefix(" = ", node.initializer);
+    return null;
+  }
+
+  @override
+  Object visitVariableDeclarationList(VariableDeclarationList node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _visitTokenWithSuffix(node.keyword, " ");
+    _visitNodeWithSuffix(node.type, " ");
+    _visitNodeListWithSeparator(node.variables, ", ");
+    return null;
+  }
+
+  @override
+  Object visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+    _visitNode(node.variables);
+    _writer.print(";");
+    return null;
+  }
+
+  @override
+  Object visitWhileStatement(WhileStatement node) {
+    _writer.print("while (");
+    _visitNode(node.condition);
+    _writer.print(") ");
+    _visitNode(node.body);
+    return null;
+  }
+
+  @override
+  Object visitWithClause(WithClause node) {
+    _writer.print("with ");
+    _visitNodeListWithSeparator(node.mixinTypes, ", ");
+    return null;
+  }
+
+  @override
+  Object visitYieldStatement(YieldStatement node) {
+    if (node.star != null) {
+      _writer.print("yield* ");
+    } else {
+      _writer.print("yield ");
+    }
+    _visitNode(node.expression);
+    _writer.print(";");
+    return null;
+  }
+
+  /**
+   * Visit the given function [body], printing the [prefix] before if the body
+   * is not empty.
+   */
+  void _visitFunctionWithPrefix(String prefix, FunctionBody body) {
+    if (body is! EmptyFunctionBody) {
+      _writer.print(prefix);
+    }
+    _visitNode(body);
+  }
+
+  /**
+   * Safely visit the given [node].
+   */
+  void _visitNode(AstNode node) {
+    if (node != null) {
+      node.accept(this);
+    }
+  }
+
+  /**
+   * Print a list of [nodes] without any separation.
+   */
+  void _visitNodeList(NodeList<AstNode> nodes) {
+    _visitNodeListWithSeparator(nodes, "");
+  }
+
+  /**
+   * Print a list of [nodes], separated by the given [separator].
+   */
+  void _visitNodeListWithSeparator(NodeList<AstNode> nodes, String separator) {
+    if (nodes != null) {
+      int size = nodes.length;
+      for (int i = 0; i < size; i++) {
+        if (i > 0) {
+          _writer.print(separator);
+        }
+        nodes[i].accept(this);
+      }
+    }
+  }
+
+  /**
+   * Print a list of [nodes], prefixed by the given [prefix] if the list is not
+   * empty, and separated by the given [separator].
+   */
+  void _visitNodeListWithSeparatorAndPrefix(
+      String prefix, NodeList<AstNode> nodes, String separator) {
+    if (nodes != null) {
+      int size = nodes.length;
+      if (size > 0) {
+        _writer.print(prefix);
+        for (int i = 0; i < size; i++) {
+          if (i > 0) {
+            _writer.print(separator);
+          }
+          nodes[i].accept(this);
+        }
+      }
+    }
+  }
+
+  /**
+   * Print a list of [nodes], separated by the given [separator], followed by
+   * the given [suffix] if the list is not empty.
+   */
+  void _visitNodeListWithSeparatorAndSuffix(
+      NodeList<AstNode> nodes, String separator, String suffix) {
+    if (nodes != null) {
+      int size = nodes.length;
+      if (size > 0) {
+        for (int i = 0; i < size; i++) {
+          if (i > 0) {
+            _writer.print(separator);
+          }
+          nodes[i].accept(this);
+        }
+        _writer.print(suffix);
+      }
+    }
+  }
+
+  /**
+   * Safely visit the given [node], printing the [prefix] before the node if it
+   * is non-`null`.
+   */
+  void _visitNodeWithPrefix(String prefix, AstNode node) {
+    if (node != null) {
+      _writer.print(prefix);
+      node.accept(this);
+    }
+  }
+
+  /**
+   * Safely visit the given [node], printing the [suffix] after the node if it
+   * is non-`null`.
+   */
+  void _visitNodeWithSuffix(AstNode node, String suffix) {
+    if (node != null) {
+      node.accept(this);
+      _writer.print(suffix);
+    }
+  }
+
+  /**
+   * Safely visit the given [token], printing the [suffix] after the token if it
+   * is non-`null`.
+   */
+  void _visitTokenWithSuffix(Token token, String suffix) {
+    if (token != null) {
+      _writer.print(token.lexeme);
+      _writer.print(suffix);
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index ff39868..00e4fe2 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1807,6 +1807,9 @@
   @override
   ElementLocation get location {
     if (_cachedLocation == null) {
+      if (library == null) {
+        return new ElementLocationImpl.con1(this);
+      }
       _cachedLocation = new ElementLocationImpl.con1(this);
     }
     return _cachedLocation;
@@ -1860,11 +1863,9 @@
     if (identical(this, object)) {
       return true;
     }
-    if (object == null || hashCode != object.hashCode) {
-      return false;
-    }
-    return object.runtimeType == runtimeType &&
-        (object as Element).location == location;
+    return object is Element &&
+        object.kind == kind &&
+        object.location == location;
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index fea415f..9599775 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -439,6 +439,7 @@
   @override
   String get displayName => _baseElement.displayName;
 
+  @deprecated
   @override
   SourceRange get docRange => _baseElement.docRange;
 
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 4268f1c..03c361d 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -169,14 +169,17 @@
   List<DartType> _typeArguments;
 
   /**
-   * The list of [typeParameters].
+   * The list of [typeParameters], if it has been computed already.  Otherwise
+   * `null`.
    */
   List<TypeParameterElement> _typeParameters;
 
   /**
-   * The list of [boundTypeParameters].
+   * True if this type is the result of instantiating type parameters (and thus
+   * any type parameters bound by the typedef should be considered part of
+   * [typeParameters] rather than [boundTypeParameters]).
    */
-  List<TypeParameterElement> _boundTypeParameters;
+  final bool _isInstantiated;
 
   /**
    * The set of typedefs which should not be expanded when exploring this type,
@@ -191,15 +194,15 @@
    */
   FunctionTypeImpl(ExecutableElement element,
       [List<FunctionTypeAliasElement> prunedTypedefs])
-      : this._(element, null, prunedTypedefs, null, null, null);
+      : this._(element, null, prunedTypedefs, null, false);
 
   /**
    * Initialize a newly created function type to be declared by the given
-   * [element], with the given [name].
+   * [element], with the given [name] and [typeArguments].
    */
-  FunctionTypeImpl.elementWithName(Element element, String name)
-      : prunedTypedefs = null,
-        super(element, name);
+  FunctionTypeImpl.elementWithNameAndArgs(
+      Element element, String name, List<DartType> typeArguments)
+      : this._(element, name, null, typeArguments, true);
 
   /**
    * Initialize a newly created function type to be declared by the given
@@ -207,38 +210,14 @@
    */
   FunctionTypeImpl.forTypedef(FunctionTypeAliasElement element,
       [List<FunctionTypeAliasElement> prunedTypedefs])
-      : this._(element, element?.name, prunedTypedefs, null, null, null);
+      : this._(element, element?.name, prunedTypedefs, null, false);
 
   /**
    * Private constructor.
    */
-  FunctionTypeImpl._(
-      TypeParameterizedElement element,
-      String name,
-      this.prunedTypedefs,
-      List<DartType> typeArguments,
-      List<TypeParameterElement> typeParameters,
-      List<TypeParameterElement> boundTypeParameters)
+  FunctionTypeImpl._(TypeParameterizedElement element, String name,
+      this.prunedTypedefs, List<DartType> typeArguments, this._isInstantiated)
       : super(element, name) {
-    _boundTypeParameters = boundTypeParameters ??
-        element?.typeParameters ??
-        TypeParameterElement.EMPTY_LIST;
-
-    if (typeParameters == null) {
-      // Combine the generic type variables from all enclosing contexts, except
-      // for this generic function's type variables. Those variables are
-      // tracked in [boundTypeParameters].
-      typeParameters = <TypeParameterElement>[];
-      Element e = element?.enclosingElement;
-      while (e != null) {
-        if (e is TypeParameterizedElement) {
-          typeParameters.addAll((e as TypeParameterizedElement).typeParameters);
-        }
-        e = e.enclosingElement;
-      }
-    }
-    _typeParameters = typeParameters;
-
     if (typeArguments == null) {
       // TODO(jmesserly): reuse TypeParameterTypeImpl.getTypes once we can
       // make it generic, which will allow it to return List<DartType> instead
@@ -265,7 +244,13 @@
   DartType get baseReturnType => element.returnType;
 
   @override
-  List<TypeParameterElement> get boundTypeParameters => _boundTypeParameters;
+  List<TypeParameterElement> get boundTypeParameters {
+    if (_isInstantiated) {
+      return TypeParameterElement.EMPTY_LIST;
+    } else {
+      return element?.typeParameters ?? TypeParameterElement.EMPTY_LIST;
+    }
+  }
 
   @override
   String get displayName {
@@ -536,7 +521,31 @@
   List<DartType> get typeArguments => _typeArguments;
 
   @override
-  List<TypeParameterElement> get typeParameters => _typeParameters;
+  List<TypeParameterElement> get typeParameters {
+    if (_typeParameters == null) {
+      // Combine the generic type variables from all enclosing contexts, except
+      // for this generic function's type variables. Those variables are
+      // tracked in [boundTypeParameters].
+      _typeParameters = <TypeParameterElement>[];
+      Element e = element?.enclosingElement;
+      while (e != null) {
+        if (e is TypeParameterizedElement) {
+          _typeParameters.addAll(e.typeParameters);
+        }
+        e = e.enclosingElement;
+      }
+      if (_isInstantiated) {
+        // Once the type has been instantiated, type parameters defined at the
+        // site of the declaration of the method are no longer considered part
+        // [boundTypeParameters]; they are part of [typeParameters].
+        List<TypeParameterElement> parametersToAdd = element?.typeParameters;
+        if (parametersToAdd != null) {
+          _typeParameters.addAll(parametersToAdd);
+        }
+      }
+    }
+    return _typeParameters;
+  }
 
   @override
   bool operator ==(Object object) {
@@ -715,13 +724,11 @@
     //
     // Now instantiate([V]), and the result should be:
     //     {U/T, V/S} T -> S.
-    List<TypeParameterElement> newTypeParams = typeParameters.toList();
     List<DartType> newTypeArgs = typeArguments.toList();
-    newTypeParams.addAll(boundTypeParameters);
     newTypeArgs.addAll(argumentTypes);
 
-    return new FunctionTypeImpl._(element, name, prunedTypedefs, newTypeArgs,
-        newTypeParams, TypeParameterElement.EMPTY_LIST);
+    return new FunctionTypeImpl._(
+        element, name, prunedTypedefs, newTypeArgs, true);
   }
 
   @override
@@ -973,8 +980,8 @@
       List<DartType> typeArgs = typeArguments
           .map((TypeImpl t) => t.pruned(prune))
           .toList(growable: false);
-      return new FunctionTypeImpl._(element, name, prune, typeArgs,
-          _typeParameters, _boundTypeParameters);
+      return new FunctionTypeImpl._(
+          element, name, prune, typeArgs, _isInstantiated);
     }
   }
 
@@ -1001,7 +1008,7 @@
     List<DartType> typeArgs =
         TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
     return new FunctionTypeImpl._(
-        element, name, prune, typeArgs, _typeParameters, _boundTypeParameters);
+        element, name, prune, typeArgs, _isInstantiated);
   }
 
   @override
@@ -1107,11 +1114,14 @@
 
   /**
    * Initialize a newly created type to be declared by the given [element],
-   * with the given [name].
+   * with the given [name] and [typeArguents].
    */
-  InterfaceTypeImpl.elementWithName(ClassElement element, String name)
+  InterfaceTypeImpl.elementWithNameAndArgs(
+      ClassElement element, String name, List<DartType> typeArguments)
       : prunedTypedefs = null,
-        super(element, name);
+        super(element, name) {
+    this.typeArguments = typeArguments;
+  }
 
   /**
    * Initialize a newly created type to have the given [name]. This constructor
@@ -1295,16 +1305,16 @@
   }
 
   @override
-  PropertyAccessorElement getGetter(String getterName) => PropertyAccessorMember
-      .from((element as ClassElementImpl).getGetter(getterName), this);
+  PropertyAccessorElement getGetter(String getterName) =>
+      PropertyAccessorMember.from(element.getGetter(getterName), this);
 
   @override
-  MethodElement getMethod(String methodName) => MethodMember.from(
-      (element as ClassElementImpl).getMethod(methodName), this);
+  MethodElement getMethod(String methodName) =>
+      MethodMember.from(element.getMethod(methodName), this);
 
   @override
-  PropertyAccessorElement getSetter(String setterName) => PropertyAccessorMember
-      .from((element as ClassElementImpl).getSetter(setterName), this);
+  PropertyAccessorElement getSetter(String setterName) =>
+      PropertyAccessorMember.from(element.getSetter(setterName), this);
 
   @override
   bool isDirectSupertypeOf(InterfaceType type) {
diff --git a/pkg/analyzer/lib/src/generated/ast.dart b/pkg/analyzer/lib/src/generated/ast.dart
index 06ae37c..9d8ddcb 100644
--- a/pkg/analyzer/lib/src/generated/ast.dart
+++ b/pkg/analyzer/lib/src/generated/ast.dart
@@ -8,6 +8,7 @@
 
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
@@ -16,9 +17,11 @@
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart' show LineInfo, Source;
-import 'package:analyzer/src/generated/utilities_collection.dart' show TokenMap;
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
+export 'package:analyzer/dart/ast/visitor.dart';
+export 'package:analyzer/src/dart/ast/utilities.dart';
+
 /**
  * Two or more string literals that are implicitly concatenated because of being
  * adjacent (separated only by whitespace).
@@ -906,1961 +909,6 @@
 }
 
 /**
- * An AST visitor that will clone any AST structure that it visits. The cloner
- * will only clone the structure, it will not preserve any resolution results or
- * properties associated with the nodes.
- */
-class AstCloner implements AstVisitor<AstNode> {
-  /**
-   * A flag indicating whether tokens should be cloned while cloning an AST
-   * structure.
-   */
-  final bool cloneTokens;
-
-  /**
-   * Initialize a newly created AST cloner to optionally clone tokens while
-   * cloning AST nodes if [cloneTokens] is `true`.
-   */
-  AstCloner(
-      [this.cloneTokens =
-          false]); // TODO(brianwilkerson) Change this to be a named parameter.
-
-  /**
-   * Return a clone of the given [node].
-   */
-  AstNode cloneNode(AstNode node) {
-    if (node == null) {
-      return null;
-    }
-    return node.accept(this) as AstNode;
-  }
-
-  /**
-   * Return a list containing cloned versions of the nodes in the given list of
-   * [nodes].
-   */
-  List<AstNode> cloneNodeList(NodeList nodes) {
-    int count = nodes.length;
-    List clonedNodes = new List();
-    for (int i = 0; i < count; i++) {
-      clonedNodes.add((nodes[i]).accept(this) as AstNode);
-    }
-    return clonedNodes;
-  }
-
-  /**
-   * Clone the given [token] if tokens are supposed to be cloned.
-   */
-  Token cloneToken(Token token) {
-    if (cloneTokens) {
-      return (token == null ? null : token.copy());
-    } else {
-      return token;
-    }
-  }
-
-  /**
-   * Clone the given [tokens] if tokens are supposed to be cloned.
-   */
-  List<Token> cloneTokenList(List<Token> tokens) {
-    if (cloneTokens) {
-      return tokens.map((Token token) => token.copy()).toList();
-    }
-    return tokens;
-  }
-
-  @override
-  AdjacentStrings visitAdjacentStrings(AdjacentStrings node) =>
-      new AdjacentStrings(cloneNodeList(node.strings));
-
-  @override
-  Annotation visitAnnotation(Annotation node) => new Annotation(
-      cloneToken(node.atSign),
-      cloneNode(node.name),
-      cloneToken(node.period),
-      cloneNode(node.constructorName),
-      cloneNode(node.arguments));
-
-  @override
-  ArgumentList visitArgumentList(ArgumentList node) => new ArgumentList(
-      cloneToken(node.leftParenthesis),
-      cloneNodeList(node.arguments),
-      cloneToken(node.rightParenthesis));
-
-  @override
-  AsExpression visitAsExpression(AsExpression node) => new AsExpression(
-      cloneNode(node.expression),
-      cloneToken(node.asOperator),
-      cloneNode(node.type));
-
-  @override
-  AstNode visitAssertStatement(AssertStatement node) => new AssertStatement(
-      cloneToken(node.assertKeyword),
-      cloneToken(node.leftParenthesis),
-      cloneNode(node.condition),
-      cloneToken(node.comma),
-      cloneNode(node.message),
-      cloneToken(node.rightParenthesis),
-      cloneToken(node.semicolon));
-
-  @override
-  AssignmentExpression visitAssignmentExpression(AssignmentExpression node) =>
-      new AssignmentExpression(cloneNode(node.leftHandSide),
-          cloneToken(node.operator), cloneNode(node.rightHandSide));
-
-  @override
-  AwaitExpression visitAwaitExpression(AwaitExpression node) =>
-      new AwaitExpression(
-          cloneToken(node.awaitKeyword), cloneNode(node.expression));
-
-  @override
-  BinaryExpression visitBinaryExpression(BinaryExpression node) =>
-      new BinaryExpression(cloneNode(node.leftOperand),
-          cloneToken(node.operator), cloneNode(node.rightOperand));
-
-  @override
-  Block visitBlock(Block node) => new Block(cloneToken(node.leftBracket),
-      cloneNodeList(node.statements), cloneToken(node.rightBracket));
-
-  @override
-  BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) =>
-      new BlockFunctionBody(cloneToken(node.keyword), cloneToken(node.star),
-          cloneNode(node.block));
-
-  @override
-  BooleanLiteral visitBooleanLiteral(BooleanLiteral node) =>
-      new BooleanLiteral(cloneToken(node.literal), node.value);
-
-  @override
-  BreakStatement visitBreakStatement(BreakStatement node) => new BreakStatement(
-      cloneToken(node.breakKeyword),
-      cloneNode(node.label),
-      cloneToken(node.semicolon));
-
-  @override
-  CascadeExpression visitCascadeExpression(CascadeExpression node) =>
-      new CascadeExpression(
-          cloneNode(node.target), cloneNodeList(node.cascadeSections));
-
-  @override
-  CatchClause visitCatchClause(CatchClause node) => new CatchClause(
-      cloneToken(node.onKeyword),
-      cloneNode(node.exceptionType),
-      cloneToken(node.catchKeyword),
-      cloneToken(node.leftParenthesis),
-      cloneNode(node.exceptionParameter),
-      cloneToken(node.comma),
-      cloneNode(node.stackTraceParameter),
-      cloneToken(node.rightParenthesis),
-      cloneNode(node.body));
-
-  @override
-  ClassDeclaration visitClassDeclaration(ClassDeclaration node) {
-    ClassDeclaration copy = new ClassDeclaration(
-        cloneNode(node.documentationComment),
-        cloneNodeList(node.metadata),
-        cloneToken(node.abstractKeyword),
-        cloneToken(node.classKeyword),
-        cloneNode(node.name),
-        cloneNode(node.typeParameters),
-        cloneNode(node.extendsClause),
-        cloneNode(node.withClause),
-        cloneNode(node.implementsClause),
-        cloneToken(node.leftBracket),
-        cloneNodeList(node.members),
-        cloneToken(node.rightBracket));
-    copy.nativeClause = cloneNode(node.nativeClause);
-    return copy;
-  }
-
-  @override
-  ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) => new ClassTypeAlias(
-      cloneNode(node.documentationComment),
-      cloneNodeList(node.metadata),
-      cloneToken(node.typedefKeyword),
-      cloneNode(node.name),
-      cloneNode(node.typeParameters),
-      cloneToken(node.equals),
-      cloneToken(node.abstractKeyword),
-      cloneNode(node.superclass),
-      cloneNode(node.withClause),
-      cloneNode(node.implementsClause),
-      cloneToken(node.semicolon));
-
-  @override
-  Comment visitComment(Comment node) {
-    if (node.isDocumentation) {
-      return Comment.createDocumentationCommentWithReferences(
-          cloneTokenList(node.tokens), cloneNodeList(node.references));
-    } else if (node.isBlock) {
-      return Comment.createBlockComment(cloneTokenList(node.tokens));
-    }
-    return Comment.createEndOfLineComment(cloneTokenList(node.tokens));
-  }
-
-  @override
-  CommentReference visitCommentReference(CommentReference node) =>
-      new CommentReference(
-          cloneToken(node.newKeyword), cloneNode(node.identifier));
-
-  @override
-  CompilationUnit visitCompilationUnit(CompilationUnit node) {
-    CompilationUnit clone = new CompilationUnit(
-        cloneToken(node.beginToken),
-        cloneNode(node.scriptTag),
-        cloneNodeList(node.directives),
-        cloneNodeList(node.declarations),
-        cloneToken(node.endToken));
-    clone.lineInfo = node.lineInfo;
-    return clone;
-  }
-
-  @override
-  ConditionalExpression visitConditionalExpression(
-          ConditionalExpression node) =>
-      new ConditionalExpression(
-          cloneNode(node.condition),
-          cloneToken(node.question),
-          cloneNode(node.thenExpression),
-          cloneToken(node.colon),
-          cloneNode(node.elseExpression));
-
-  @override
-  Configuration visitConfiguration(Configuration node) => new Configuration(
-      cloneToken(node.ifKeyword),
-      cloneToken(node.leftParenthesis),
-      cloneNode(node.name),
-      cloneToken(node.equalToken),
-      cloneNode(node.value),
-      cloneToken(node.rightParenthesis),
-      cloneNode(node.libraryUri));
-
-  @override
-  ConstructorDeclaration visitConstructorDeclaration(
-          ConstructorDeclaration node) =>
-      new ConstructorDeclaration(
-          cloneNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.externalKeyword),
-          cloneToken(node.constKeyword),
-          cloneToken(node.factoryKeyword),
-          cloneNode(node.returnType),
-          cloneToken(node.period),
-          cloneNode(node.name),
-          cloneNode(node.parameters),
-          cloneToken(node.separator),
-          cloneNodeList(node.initializers),
-          cloneNode(node.redirectedConstructor),
-          cloneNode(node.body));
-
-  @override
-  ConstructorFieldInitializer visitConstructorFieldInitializer(
-          ConstructorFieldInitializer node) =>
-      new ConstructorFieldInitializer(
-          cloneToken(node.thisKeyword),
-          cloneToken(node.period),
-          cloneNode(node.fieldName),
-          cloneToken(node.equals),
-          cloneNode(node.expression));
-
-  @override
-  ConstructorName visitConstructorName(ConstructorName node) =>
-      new ConstructorName(
-          cloneNode(node.type), cloneToken(node.period), cloneNode(node.name));
-
-  @override
-  ContinueStatement visitContinueStatement(ContinueStatement node) =>
-      new ContinueStatement(cloneToken(node.continueKeyword),
-          cloneNode(node.label), cloneToken(node.semicolon));
-
-  @override
-  DeclaredIdentifier visitDeclaredIdentifier(DeclaredIdentifier node) =>
-      new DeclaredIdentifier(
-          cloneNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.keyword),
-          cloneNode(node.type),
-          cloneNode(node.identifier));
-
-  @override
-  DefaultFormalParameter visitDefaultFormalParameter(
-          DefaultFormalParameter node) =>
-      new DefaultFormalParameter(cloneNode(node.parameter), node.kind,
-          cloneToken(node.separator), cloneNode(node.defaultValue));
-
-  @override
-  DoStatement visitDoStatement(DoStatement node) => new DoStatement(
-      cloneToken(node.doKeyword),
-      cloneNode(node.body),
-      cloneToken(node.whileKeyword),
-      cloneToken(node.leftParenthesis),
-      cloneNode(node.condition),
-      cloneToken(node.rightParenthesis),
-      cloneToken(node.semicolon));
-
-  @override
-  DottedName visitDottedName(DottedName node) =>
-      new DottedName(cloneNodeList(node.components));
-
-  @override
-  DoubleLiteral visitDoubleLiteral(DoubleLiteral node) =>
-      new DoubleLiteral(cloneToken(node.literal), node.value);
-
-  @override
-  EmptyFunctionBody visitEmptyFunctionBody(EmptyFunctionBody node) =>
-      new EmptyFunctionBody(cloneToken(node.semicolon));
-
-  @override
-  EmptyStatement visitEmptyStatement(EmptyStatement node) =>
-      new EmptyStatement(cloneToken(node.semicolon));
-
-  @override
-  AstNode visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
-      new EnumConstantDeclaration(cloneNode(node.documentationComment),
-          cloneNodeList(node.metadata), cloneNode(node.name));
-
-  @override
-  EnumDeclaration visitEnumDeclaration(EnumDeclaration node) =>
-      new EnumDeclaration(
-          cloneNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.enumKeyword),
-          cloneNode(node.name),
-          cloneToken(node.leftBracket),
-          cloneNodeList(node.constants),
-          cloneToken(node.rightBracket));
-
-  @override
-  ExportDirective visitExportDirective(ExportDirective node) {
-    ExportDirective directive = new ExportDirective(
-        cloneNode(node.documentationComment),
-        cloneNodeList(node.metadata),
-        cloneToken(node.keyword),
-        cloneNode(node.uri),
-        cloneNodeList(node.configurations),
-        cloneNodeList(node.combinators),
-        cloneToken(node.semicolon));
-    directive.source = node.source;
-    directive.uriContent = node.uriContent;
-    return directive;
-  }
-
-  @override
-  ExpressionFunctionBody visitExpressionFunctionBody(
-          ExpressionFunctionBody node) =>
-      new ExpressionFunctionBody(
-          cloneToken(node.keyword),
-          cloneToken(node.functionDefinition),
-          cloneNode(node.expression),
-          cloneToken(node.semicolon));
-
-  @override
-  ExpressionStatement visitExpressionStatement(ExpressionStatement node) =>
-      new ExpressionStatement(
-          cloneNode(node.expression), cloneToken(node.semicolon));
-
-  @override
-  ExtendsClause visitExtendsClause(ExtendsClause node) => new ExtendsClause(
-      cloneToken(node.extendsKeyword), cloneNode(node.superclass));
-
-  @override
-  FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
-      new FieldDeclaration(
-          cloneNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.staticKeyword),
-          cloneNode(node.fields),
-          cloneToken(node.semicolon));
-
-  @override
-  FieldFormalParameter visitFieldFormalParameter(FieldFormalParameter node) =>
-      new FieldFormalParameter(
-          cloneNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.keyword),
-          cloneNode(node.type),
-          cloneToken(node.thisKeyword),
-          cloneToken(node.period),
-          cloneNode(node.identifier),
-          cloneNode(node.typeParameters),
-          cloneNode(node.parameters));
-
-  @override
-  ForEachStatement visitForEachStatement(ForEachStatement node) {
-    DeclaredIdentifier loopVariable = node.loopVariable;
-    if (loopVariable == null) {
-      return new ForEachStatement.withReference(
-          cloneToken(node.awaitKeyword),
-          cloneToken(node.forKeyword),
-          cloneToken(node.leftParenthesis),
-          cloneNode(node.identifier),
-          cloneToken(node.inKeyword),
-          cloneNode(node.iterable),
-          cloneToken(node.rightParenthesis),
-          cloneNode(node.body));
-    }
-    return new ForEachStatement.withDeclaration(
-        cloneToken(node.awaitKeyword),
-        cloneToken(node.forKeyword),
-        cloneToken(node.leftParenthesis),
-        cloneNode(loopVariable),
-        cloneToken(node.inKeyword),
-        cloneNode(node.iterable),
-        cloneToken(node.rightParenthesis),
-        cloneNode(node.body));
-  }
-
-  @override
-  FormalParameterList visitFormalParameterList(FormalParameterList node) =>
-      new FormalParameterList(
-          cloneToken(node.leftParenthesis),
-          cloneNodeList(node.parameters),
-          cloneToken(node.leftDelimiter),
-          cloneToken(node.rightDelimiter),
-          cloneToken(node.rightParenthesis));
-
-  @override
-  ForStatement visitForStatement(ForStatement node) => new ForStatement(
-      cloneToken(node.forKeyword),
-      cloneToken(node.leftParenthesis),
-      cloneNode(node.variables),
-      cloneNode(node.initialization),
-      cloneToken(node.leftSeparator),
-      cloneNode(node.condition),
-      cloneToken(node.rightSeparator),
-      cloneNodeList(node.updaters),
-      cloneToken(node.rightParenthesis),
-      cloneNode(node.body));
-
-  @override
-  FunctionDeclaration visitFunctionDeclaration(FunctionDeclaration node) =>
-      new FunctionDeclaration(
-          cloneNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.externalKeyword),
-          cloneNode(node.returnType),
-          cloneToken(node.propertyKeyword),
-          cloneNode(node.name),
-          cloneNode(node.functionExpression));
-
-  @override
-  FunctionDeclarationStatement visitFunctionDeclarationStatement(
-          FunctionDeclarationStatement node) =>
-      new FunctionDeclarationStatement(cloneNode(node.functionDeclaration));
-
-  @override
-  FunctionExpression visitFunctionExpression(FunctionExpression node) =>
-      new FunctionExpression(cloneNode(node.typeParameters),
-          cloneNode(node.parameters), cloneNode(node.body));
-
-  @override
-  FunctionExpressionInvocation visitFunctionExpressionInvocation(
-          FunctionExpressionInvocation node) =>
-      new FunctionExpressionInvocation(cloneNode(node.function),
-          cloneNode(node.typeArguments), cloneNode(node.argumentList));
-
-  @override
-  FunctionTypeAlias visitFunctionTypeAlias(FunctionTypeAlias node) =>
-      new FunctionTypeAlias(
-          cloneNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.typedefKeyword),
-          cloneNode(node.returnType),
-          cloneNode(node.name),
-          cloneNode(node.typeParameters),
-          cloneNode(node.parameters),
-          cloneToken(node.semicolon));
-
-  @override
-  FunctionTypedFormalParameter visitFunctionTypedFormalParameter(
-          FunctionTypedFormalParameter node) =>
-      new FunctionTypedFormalParameter(
-          cloneNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneNode(node.returnType),
-          cloneNode(node.identifier),
-          cloneNode(node.typeParameters),
-          cloneNode(node.parameters));
-
-  @override
-  HideCombinator visitHideCombinator(HideCombinator node) => new HideCombinator(
-      cloneToken(node.keyword), cloneNodeList(node.hiddenNames));
-
-  @override
-  IfStatement visitIfStatement(IfStatement node) => new IfStatement(
-      cloneToken(node.ifKeyword),
-      cloneToken(node.leftParenthesis),
-      cloneNode(node.condition),
-      cloneToken(node.rightParenthesis),
-      cloneNode(node.thenStatement),
-      cloneToken(node.elseKeyword),
-      cloneNode(node.elseStatement));
-
-  @override
-  ImplementsClause visitImplementsClause(ImplementsClause node) =>
-      new ImplementsClause(
-          cloneToken(node.implementsKeyword), cloneNodeList(node.interfaces));
-
-  @override
-  ImportDirective visitImportDirective(ImportDirective node) {
-    ImportDirective directive = new ImportDirective(
-        cloneNode(node.documentationComment),
-        cloneNodeList(node.metadata),
-        cloneToken(node.keyword),
-        cloneNode(node.uri),
-        cloneNodeList(node.configurations),
-        cloneToken(node.deferredKeyword),
-        cloneToken(node.asKeyword),
-        cloneNode(node.prefix),
-        cloneNodeList(node.combinators),
-        cloneToken(node.semicolon));
-    directive.source = node.source;
-    directive.uriContent = node.uriContent;
-    return directive;
-  }
-
-  @override
-  IndexExpression visitIndexExpression(IndexExpression node) {
-    Token period = node.period;
-    if (period == null) {
-      return new IndexExpression.forTarget(
-          cloneNode(node.target),
-          cloneToken(node.leftBracket),
-          cloneNode(node.index),
-          cloneToken(node.rightBracket));
-    } else {
-      return new IndexExpression.forCascade(
-          cloneToken(period),
-          cloneToken(node.leftBracket),
-          cloneNode(node.index),
-          cloneToken(node.rightBracket));
-    }
-  }
-
-  @override
-  InstanceCreationExpression visitInstanceCreationExpression(
-          InstanceCreationExpression node) =>
-      new InstanceCreationExpression(cloneToken(node.keyword),
-          cloneNode(node.constructorName), cloneNode(node.argumentList));
-
-  @override
-  IntegerLiteral visitIntegerLiteral(IntegerLiteral node) =>
-      new IntegerLiteral(cloneToken(node.literal), node.value);
-
-  @override
-  InterpolationExpression visitInterpolationExpression(
-          InterpolationExpression node) =>
-      new InterpolationExpression(cloneToken(node.leftBracket),
-          cloneNode(node.expression), cloneToken(node.rightBracket));
-
-  @override
-  InterpolationString visitInterpolationString(InterpolationString node) =>
-      new InterpolationString(cloneToken(node.contents), node.value);
-
-  @override
-  IsExpression visitIsExpression(IsExpression node) => new IsExpression(
-      cloneNode(node.expression),
-      cloneToken(node.isOperator),
-      cloneToken(node.notOperator),
-      cloneNode(node.type));
-
-  @override
-  Label visitLabel(Label node) =>
-      new Label(cloneNode(node.label), cloneToken(node.colon));
-
-  @override
-  LabeledStatement visitLabeledStatement(LabeledStatement node) =>
-      new LabeledStatement(
-          cloneNodeList(node.labels), cloneNode(node.statement));
-
-  @override
-  LibraryDirective visitLibraryDirective(LibraryDirective node) =>
-      new LibraryDirective(
-          cloneNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.libraryKeyword),
-          cloneNode(node.name),
-          cloneToken(node.semicolon));
-
-  @override
-  LibraryIdentifier visitLibraryIdentifier(LibraryIdentifier node) =>
-      new LibraryIdentifier(cloneNodeList(node.components));
-
-  @override
-  ListLiteral visitListLiteral(ListLiteral node) => new ListLiteral(
-      cloneToken(node.constKeyword),
-      cloneNode(node.typeArguments),
-      cloneToken(node.leftBracket),
-      cloneNodeList(node.elements),
-      cloneToken(node.rightBracket));
-
-  @override
-  MapLiteral visitMapLiteral(MapLiteral node) => new MapLiteral(
-      cloneToken(node.constKeyword),
-      cloneNode(node.typeArguments),
-      cloneToken(node.leftBracket),
-      cloneNodeList(node.entries),
-      cloneToken(node.rightBracket));
-
-  @override
-  MapLiteralEntry visitMapLiteralEntry(MapLiteralEntry node) =>
-      new MapLiteralEntry(cloneNode(node.key), cloneToken(node.separator),
-          cloneNode(node.value));
-
-  @override
-  MethodDeclaration visitMethodDeclaration(MethodDeclaration node) =>
-      new MethodDeclaration(
-          cloneNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.externalKeyword),
-          cloneToken(node.modifierKeyword),
-          cloneNode(node.returnType),
-          cloneToken(node.propertyKeyword),
-          cloneToken(node.operatorKeyword),
-          cloneNode(node.name),
-          cloneNode(node.typeParameters),
-          cloneNode(node.parameters),
-          cloneNode(node.body));
-
-  @override
-  MethodInvocation visitMethodInvocation(MethodInvocation node) =>
-      new MethodInvocation(
-          cloneNode(node.target),
-          cloneToken(node.operator),
-          cloneNode(node.methodName),
-          cloneNode(node.typeArguments),
-          cloneNode(node.argumentList));
-
-  @override
-  NamedExpression visitNamedExpression(NamedExpression node) =>
-      new NamedExpression(cloneNode(node.name), cloneNode(node.expression));
-
-  @override
-  AstNode visitNativeClause(NativeClause node) =>
-      new NativeClause(cloneToken(node.nativeKeyword), cloneNode(node.name));
-
-  @override
-  NativeFunctionBody visitNativeFunctionBody(NativeFunctionBody node) =>
-      new NativeFunctionBody(cloneToken(node.nativeKeyword),
-          cloneNode(node.stringLiteral), cloneToken(node.semicolon));
-
-  @override
-  NullLiteral visitNullLiteral(NullLiteral node) =>
-      new NullLiteral(cloneToken(node.literal));
-
-  @override
-  ParenthesizedExpression visitParenthesizedExpression(
-          ParenthesizedExpression node) =>
-      new ParenthesizedExpression(cloneToken(node.leftParenthesis),
-          cloneNode(node.expression), cloneToken(node.rightParenthesis));
-
-  @override
-  PartDirective visitPartDirective(PartDirective node) {
-    PartDirective directive = new PartDirective(
-        cloneNode(node.documentationComment),
-        cloneNodeList(node.metadata),
-        cloneToken(node.partKeyword),
-        cloneNode(node.uri),
-        cloneToken(node.semicolon));
-    directive.source = node.source;
-    directive.uriContent = node.uriContent;
-    return directive;
-  }
-
-  @override
-  PartOfDirective visitPartOfDirective(PartOfDirective node) =>
-      new PartOfDirective(
-          cloneNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.partKeyword),
-          cloneToken(node.ofKeyword),
-          cloneNode(node.libraryName),
-          cloneToken(node.semicolon));
-
-  @override
-  PostfixExpression visitPostfixExpression(PostfixExpression node) =>
-      new PostfixExpression(cloneNode(node.operand), cloneToken(node.operator));
-
-  @override
-  PrefixedIdentifier visitPrefixedIdentifier(PrefixedIdentifier node) =>
-      new PrefixedIdentifier(cloneNode(node.prefix), cloneToken(node.period),
-          cloneNode(node.identifier));
-
-  @override
-  PrefixExpression visitPrefixExpression(PrefixExpression node) =>
-      new PrefixExpression(cloneToken(node.operator), cloneNode(node.operand));
-
-  @override
-  PropertyAccess visitPropertyAccess(PropertyAccess node) => new PropertyAccess(
-      cloneNode(node.target),
-      cloneToken(node.operator),
-      cloneNode(node.propertyName));
-
-  @override
-  RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
-          RedirectingConstructorInvocation node) =>
-      new RedirectingConstructorInvocation(
-          cloneToken(node.thisKeyword),
-          cloneToken(node.period),
-          cloneNode(node.constructorName),
-          cloneNode(node.argumentList));
-
-  @override
-  RethrowExpression visitRethrowExpression(RethrowExpression node) =>
-      new RethrowExpression(cloneToken(node.rethrowKeyword));
-
-  @override
-  ReturnStatement visitReturnStatement(ReturnStatement node) =>
-      new ReturnStatement(cloneToken(node.returnKeyword),
-          cloneNode(node.expression), cloneToken(node.semicolon));
-
-  @override
-  ScriptTag visitScriptTag(ScriptTag node) =>
-      new ScriptTag(cloneToken(node.scriptTag));
-
-  @override
-  ShowCombinator visitShowCombinator(ShowCombinator node) => new ShowCombinator(
-      cloneToken(node.keyword), cloneNodeList(node.shownNames));
-
-  @override
-  SimpleFormalParameter visitSimpleFormalParameter(
-          SimpleFormalParameter node) =>
-      new SimpleFormalParameter(
-          cloneNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.keyword),
-          cloneNode(node.type),
-          cloneNode(node.identifier));
-
-  @override
-  SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) =>
-      new SimpleIdentifier(cloneToken(node.token));
-
-  @override
-  SimpleStringLiteral visitSimpleStringLiteral(SimpleStringLiteral node) =>
-      new SimpleStringLiteral(cloneToken(node.literal), node.value);
-
-  @override
-  StringInterpolation visitStringInterpolation(StringInterpolation node) =>
-      new StringInterpolation(cloneNodeList(node.elements));
-
-  @override
-  SuperConstructorInvocation visitSuperConstructorInvocation(
-          SuperConstructorInvocation node) =>
-      new SuperConstructorInvocation(
-          cloneToken(node.superKeyword),
-          cloneToken(node.period),
-          cloneNode(node.constructorName),
-          cloneNode(node.argumentList));
-
-  @override
-  SuperExpression visitSuperExpression(SuperExpression node) =>
-      new SuperExpression(cloneToken(node.superKeyword));
-
-  @override
-  SwitchCase visitSwitchCase(SwitchCase node) => new SwitchCase(
-      cloneNodeList(node.labels),
-      cloneToken(node.keyword),
-      cloneNode(node.expression),
-      cloneToken(node.colon),
-      cloneNodeList(node.statements));
-
-  @override
-  SwitchDefault visitSwitchDefault(SwitchDefault node) => new SwitchDefault(
-      cloneNodeList(node.labels),
-      cloneToken(node.keyword),
-      cloneToken(node.colon),
-      cloneNodeList(node.statements));
-
-  @override
-  SwitchStatement visitSwitchStatement(SwitchStatement node) =>
-      new SwitchStatement(
-          cloneToken(node.switchKeyword),
-          cloneToken(node.leftParenthesis),
-          cloneNode(node.expression),
-          cloneToken(node.rightParenthesis),
-          cloneToken(node.leftBracket),
-          cloneNodeList(node.members),
-          cloneToken(node.rightBracket));
-
-  @override
-  SymbolLiteral visitSymbolLiteral(SymbolLiteral node) => new SymbolLiteral(
-      cloneToken(node.poundSign), cloneTokenList(node.components));
-
-  @override
-  ThisExpression visitThisExpression(ThisExpression node) =>
-      new ThisExpression(cloneToken(node.thisKeyword));
-
-  @override
-  ThrowExpression visitThrowExpression(ThrowExpression node) =>
-      new ThrowExpression(
-          cloneToken(node.throwKeyword), cloneNode(node.expression));
-
-  @override
-  TopLevelVariableDeclaration visitTopLevelVariableDeclaration(
-          TopLevelVariableDeclaration node) =>
-      new TopLevelVariableDeclaration(
-          cloneNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneNode(node.variables),
-          cloneToken(node.semicolon));
-
-  @override
-  TryStatement visitTryStatement(TryStatement node) => new TryStatement(
-      cloneToken(node.tryKeyword),
-      cloneNode(node.body),
-      cloneNodeList(node.catchClauses),
-      cloneToken(node.finallyKeyword),
-      cloneNode(node.finallyBlock));
-
-  @override
-  TypeArgumentList visitTypeArgumentList(TypeArgumentList node) =>
-      new TypeArgumentList(cloneToken(node.leftBracket),
-          cloneNodeList(node.arguments), cloneToken(node.rightBracket));
-
-  @override
-  TypeName visitTypeName(TypeName node) =>
-      new TypeName(cloneNode(node.name), cloneNode(node.typeArguments));
-
-  @override
-  TypeParameter visitTypeParameter(TypeParameter node) => new TypeParameter(
-      cloneNode(node.documentationComment),
-      cloneNodeList(node.metadata),
-      cloneNode(node.name),
-      cloneToken(node.extendsKeyword),
-      cloneNode(node.bound));
-
-  @override
-  TypeParameterList visitTypeParameterList(TypeParameterList node) =>
-      new TypeParameterList(cloneToken(node.leftBracket),
-          cloneNodeList(node.typeParameters), cloneToken(node.rightBracket));
-
-  @override
-  VariableDeclaration visitVariableDeclaration(VariableDeclaration node) =>
-      new VariableDeclaration(cloneNode(node.name), cloneToken(node.equals),
-          cloneNode(node.initializer));
-
-  @override
-  VariableDeclarationList visitVariableDeclarationList(
-          VariableDeclarationList node) =>
-      new VariableDeclarationList(
-          cloneNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.keyword),
-          cloneNode(node.type),
-          cloneNodeList(node.variables));
-
-  @override
-  VariableDeclarationStatement visitVariableDeclarationStatement(
-          VariableDeclarationStatement node) =>
-      new VariableDeclarationStatement(
-          cloneNode(node.variables), cloneToken(node.semicolon));
-
-  @override
-  WhileStatement visitWhileStatement(WhileStatement node) => new WhileStatement(
-      cloneToken(node.whileKeyword),
-      cloneToken(node.leftParenthesis),
-      cloneNode(node.condition),
-      cloneToken(node.rightParenthesis),
-      cloneNode(node.body));
-
-  @override
-  WithClause visitWithClause(WithClause node) => new WithClause(
-      cloneToken(node.withKeyword), cloneNodeList(node.mixinTypes));
-
-  @override
-  YieldStatement visitYieldStatement(YieldStatement node) => new YieldStatement(
-      cloneToken(node.yieldKeyword),
-      cloneToken(node.star),
-      cloneNode(node.expression),
-      cloneToken(node.semicolon));
-
-  /**
-   * Return a clone of the given [node].
-   */
-  static AstNode clone(AstNode node) {
-    return node.accept(new AstCloner());
-  }
-}
-
-/**
- * An AstVisitor that compares the structure of two AstNodes to see whether they
- * are equal.
- */
-class AstComparator implements AstVisitor<bool> {
-  /**
-   * The AST node with which the node being visited is to be compared. This is
-   * only valid at the beginning of each visit method (until [isEqualNodes] is
-   * invoked).
-   */
-  AstNode _other;
-
-  /**
-   * Return `true` if the [first] node and the [second] node have the same
-   * structure.
-   *
-   * *Note:* This method is only visible for testing purposes and should not be
-   * used by clients.
-   */
-  bool isEqualNodes(AstNode first, AstNode second) {
-    if (first == null) {
-      return second == null;
-    } else if (second == null) {
-      return false;
-    } else if (first.runtimeType != second.runtimeType) {
-      return false;
-    }
-    _other = second;
-    return first.accept(this);
-  }
-
-  /**
-   * Return `true` if the [first] token and the [second] token have the same
-   * structure.
-   *
-   * *Note:* This method is only visible for testing purposes and should not be
-   * used by clients.
-   */
-  bool isEqualTokens(Token first, Token second) {
-    if (first == null) {
-      return second == null;
-    } else if (second == null) {
-      return false;
-    } else if (identical(first, second)) {
-      return true;
-    }
-    return first.offset == second.offset &&
-        first.length == second.length &&
-        first.lexeme == second.lexeme;
-  }
-
-  @override
-  bool visitAdjacentStrings(AdjacentStrings node) {
-    AdjacentStrings other = _other as AdjacentStrings;
-    return _isEqualNodeLists(node.strings, other.strings);
-  }
-
-  @override
-  bool visitAnnotation(Annotation node) {
-    Annotation other = _other as Annotation;
-    return isEqualTokens(node.atSign, other.atSign) &&
-        isEqualNodes(node.name, other.name) &&
-        isEqualTokens(node.period, other.period) &&
-        isEqualNodes(node.constructorName, other.constructorName) &&
-        isEqualNodes(node.arguments, other.arguments);
-  }
-
-  @override
-  bool visitArgumentList(ArgumentList node) {
-    ArgumentList other = _other as ArgumentList;
-    return isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        _isEqualNodeLists(node.arguments, other.arguments) &&
-        isEqualTokens(node.rightParenthesis, other.rightParenthesis);
-  }
-
-  @override
-  bool visitAsExpression(AsExpression node) {
-    AsExpression other = _other as AsExpression;
-    return isEqualNodes(node.expression, other.expression) &&
-        isEqualTokens(node.asOperator, other.asOperator) &&
-        isEqualNodes(node.type, other.type);
-  }
-
-  @override
-  bool visitAssertStatement(AssertStatement node) {
-    AssertStatement other = _other as AssertStatement;
-    return isEqualTokens(node.assertKeyword, other.assertKeyword) &&
-        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        isEqualNodes(node.condition, other.condition) &&
-        isEqualTokens(node.comma, other.comma) &&
-        isEqualNodes(node.message, other.message) &&
-        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitAssignmentExpression(AssignmentExpression node) {
-    AssignmentExpression other = _other as AssignmentExpression;
-    return isEqualNodes(node.leftHandSide, other.leftHandSide) &&
-        isEqualTokens(node.operator, other.operator) &&
-        isEqualNodes(node.rightHandSide, other.rightHandSide);
-  }
-
-  @override
-  bool visitAwaitExpression(AwaitExpression node) {
-    AwaitExpression other = _other as AwaitExpression;
-    return isEqualTokens(node.awaitKeyword, other.awaitKeyword) &&
-        isEqualNodes(node.expression, other.expression);
-  }
-
-  @override
-  bool visitBinaryExpression(BinaryExpression node) {
-    BinaryExpression other = _other as BinaryExpression;
-    return isEqualNodes(node.leftOperand, other.leftOperand) &&
-        isEqualTokens(node.operator, other.operator) &&
-        isEqualNodes(node.rightOperand, other.rightOperand);
-  }
-
-  @override
-  bool visitBlock(Block node) {
-    Block other = _other as Block;
-    return isEqualTokens(node.leftBracket, other.leftBracket) &&
-        _isEqualNodeLists(node.statements, other.statements) &&
-        isEqualTokens(node.rightBracket, other.rightBracket);
-  }
-
-  @override
-  bool visitBlockFunctionBody(BlockFunctionBody node) {
-    BlockFunctionBody other = _other as BlockFunctionBody;
-    return isEqualNodes(node.block, other.block);
-  }
-
-  @override
-  bool visitBooleanLiteral(BooleanLiteral node) {
-    BooleanLiteral other = _other as BooleanLiteral;
-    return isEqualTokens(node.literal, other.literal) &&
-        node.value == other.value;
-  }
-
-  @override
-  bool visitBreakStatement(BreakStatement node) {
-    BreakStatement other = _other as BreakStatement;
-    return isEqualTokens(node.breakKeyword, other.breakKeyword) &&
-        isEqualNodes(node.label, other.label) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitCascadeExpression(CascadeExpression node) {
-    CascadeExpression other = _other as CascadeExpression;
-    return isEqualNodes(node.target, other.target) &&
-        _isEqualNodeLists(node.cascadeSections, other.cascadeSections);
-  }
-
-  @override
-  bool visitCatchClause(CatchClause node) {
-    CatchClause other = _other as CatchClause;
-    return isEqualTokens(node.onKeyword, other.onKeyword) &&
-        isEqualNodes(node.exceptionType, other.exceptionType) &&
-        isEqualTokens(node.catchKeyword, other.catchKeyword) &&
-        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        isEqualNodes(node.exceptionParameter, other.exceptionParameter) &&
-        isEqualTokens(node.comma, other.comma) &&
-        isEqualNodes(node.stackTraceParameter, other.stackTraceParameter) &&
-        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
-        isEqualNodes(node.body, other.body);
-  }
-
-  @override
-  bool visitClassDeclaration(ClassDeclaration node) {
-    ClassDeclaration other = _other as ClassDeclaration;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.abstractKeyword, other.abstractKeyword) &&
-        isEqualTokens(node.classKeyword, other.classKeyword) &&
-        isEqualNodes(node.name, other.name) &&
-        isEqualNodes(node.typeParameters, other.typeParameters) &&
-        isEqualNodes(node.extendsClause, other.extendsClause) &&
-        isEqualNodes(node.withClause, other.withClause) &&
-        isEqualNodes(node.implementsClause, other.implementsClause) &&
-        isEqualTokens(node.leftBracket, other.leftBracket) &&
-        _isEqualNodeLists(node.members, other.members) &&
-        isEqualTokens(node.rightBracket, other.rightBracket);
-  }
-
-  @override
-  bool visitClassTypeAlias(ClassTypeAlias node) {
-    ClassTypeAlias other = _other as ClassTypeAlias;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.typedefKeyword, other.typedefKeyword) &&
-        isEqualNodes(node.name, other.name) &&
-        isEqualNodes(node.typeParameters, other.typeParameters) &&
-        isEqualTokens(node.equals, other.equals) &&
-        isEqualTokens(node.abstractKeyword, other.abstractKeyword) &&
-        isEqualNodes(node.superclass, other.superclass) &&
-        isEqualNodes(node.withClause, other.withClause) &&
-        isEqualNodes(node.implementsClause, other.implementsClause) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitComment(Comment node) {
-    Comment other = _other as Comment;
-    return _isEqualNodeLists(node.references, other.references);
-  }
-
-  @override
-  bool visitCommentReference(CommentReference node) {
-    CommentReference other = _other as CommentReference;
-    return isEqualTokens(node.newKeyword, other.newKeyword) &&
-        isEqualNodes(node.identifier, other.identifier);
-  }
-
-  @override
-  bool visitCompilationUnit(CompilationUnit node) {
-    CompilationUnit other = _other as CompilationUnit;
-    return isEqualTokens(node.beginToken, other.beginToken) &&
-        isEqualNodes(node.scriptTag, other.scriptTag) &&
-        _isEqualNodeLists(node.directives, other.directives) &&
-        _isEqualNodeLists(node.declarations, other.declarations) &&
-        isEqualTokens(node.endToken, other.endToken);
-  }
-
-  @override
-  bool visitConditionalExpression(ConditionalExpression node) {
-    ConditionalExpression other = _other as ConditionalExpression;
-    return isEqualNodes(node.condition, other.condition) &&
-        isEqualTokens(node.question, other.question) &&
-        isEqualNodes(node.thenExpression, other.thenExpression) &&
-        isEqualTokens(node.colon, other.colon) &&
-        isEqualNodes(node.elseExpression, other.elseExpression);
-  }
-
-  @override
-  bool visitConfiguration(Configuration node) {
-    Configuration other = _other as Configuration;
-    return isEqualTokens(node.ifKeyword, other.ifKeyword) &&
-        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        isEqualNodes(node.name, other.name) &&
-        isEqualTokens(node.equalToken, other.equalToken) &&
-        isEqualNodes(node.value, other.value) &&
-        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
-        isEqualNodes(node.libraryUri, other.libraryUri);
-  }
-
-  @override
-  bool visitConstructorDeclaration(ConstructorDeclaration node) {
-    ConstructorDeclaration other = _other as ConstructorDeclaration;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.externalKeyword, other.externalKeyword) &&
-        isEqualTokens(node.constKeyword, other.constKeyword) &&
-        isEqualTokens(node.factoryKeyword, other.factoryKeyword) &&
-        isEqualNodes(node.returnType, other.returnType) &&
-        isEqualTokens(node.period, other.period) &&
-        isEqualNodes(node.name, other.name) &&
-        isEqualNodes(node.parameters, other.parameters) &&
-        isEqualTokens(node.separator, other.separator) &&
-        _isEqualNodeLists(node.initializers, other.initializers) &&
-        isEqualNodes(node.redirectedConstructor, other.redirectedConstructor) &&
-        isEqualNodes(node.body, other.body);
-  }
-
-  @override
-  bool visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
-    ConstructorFieldInitializer other = _other as ConstructorFieldInitializer;
-    return isEqualTokens(node.thisKeyword, other.thisKeyword) &&
-        isEqualTokens(node.period, other.period) &&
-        isEqualNodes(node.fieldName, other.fieldName) &&
-        isEqualTokens(node.equals, other.equals) &&
-        isEqualNodes(node.expression, other.expression);
-  }
-
-  @override
-  bool visitConstructorName(ConstructorName node) {
-    ConstructorName other = _other as ConstructorName;
-    return isEqualNodes(node.type, other.type) &&
-        isEqualTokens(node.period, other.period) &&
-        isEqualNodes(node.name, other.name);
-  }
-
-  @override
-  bool visitContinueStatement(ContinueStatement node) {
-    ContinueStatement other = _other as ContinueStatement;
-    return isEqualTokens(node.continueKeyword, other.continueKeyword) &&
-        isEqualNodes(node.label, other.label) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitDeclaredIdentifier(DeclaredIdentifier node) {
-    DeclaredIdentifier other = _other as DeclaredIdentifier;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.keyword, other.keyword) &&
-        isEqualNodes(node.type, other.type) &&
-        isEqualNodes(node.identifier, other.identifier);
-  }
-
-  @override
-  bool visitDefaultFormalParameter(DefaultFormalParameter node) {
-    DefaultFormalParameter other = _other as DefaultFormalParameter;
-    return isEqualNodes(node.parameter, other.parameter) &&
-        node.kind == other.kind &&
-        isEqualTokens(node.separator, other.separator) &&
-        isEqualNodes(node.defaultValue, other.defaultValue);
-  }
-
-  @override
-  bool visitDoStatement(DoStatement node) {
-    DoStatement other = _other as DoStatement;
-    return isEqualTokens(node.doKeyword, other.doKeyword) &&
-        isEqualNodes(node.body, other.body) &&
-        isEqualTokens(node.whileKeyword, other.whileKeyword) &&
-        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        isEqualNodes(node.condition, other.condition) &&
-        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitDottedName(DottedName node) {
-    DottedName other = _other as DottedName;
-    return _isEqualNodeLists(node.components, other.components);
-  }
-
-  @override
-  bool visitDoubleLiteral(DoubleLiteral node) {
-    DoubleLiteral other = _other as DoubleLiteral;
-    return isEqualTokens(node.literal, other.literal) &&
-        node.value == other.value;
-  }
-
-  @override
-  bool visitEmptyFunctionBody(EmptyFunctionBody node) {
-    EmptyFunctionBody other = _other as EmptyFunctionBody;
-    return isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitEmptyStatement(EmptyStatement node) {
-    EmptyStatement other = _other as EmptyStatement;
-    return isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitEnumConstantDeclaration(EnumConstantDeclaration node) {
-    EnumConstantDeclaration other = _other as EnumConstantDeclaration;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualNodes(node.name, other.name);
-  }
-
-  @override
-  bool visitEnumDeclaration(EnumDeclaration node) {
-    EnumDeclaration other = _other as EnumDeclaration;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.enumKeyword, other.enumKeyword) &&
-        isEqualNodes(node.name, other.name) &&
-        isEqualTokens(node.leftBracket, other.leftBracket) &&
-        _isEqualNodeLists(node.constants, other.constants) &&
-        isEqualTokens(node.rightBracket, other.rightBracket);
-  }
-
-  @override
-  bool visitExportDirective(ExportDirective node) {
-    ExportDirective other = _other as ExportDirective;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.keyword, other.keyword) &&
-        isEqualNodes(node.uri, other.uri) &&
-        _isEqualNodeLists(node.combinators, other.combinators) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitExpressionFunctionBody(ExpressionFunctionBody node) {
-    ExpressionFunctionBody other = _other as ExpressionFunctionBody;
-    return isEqualTokens(node.functionDefinition, other.functionDefinition) &&
-        isEqualNodes(node.expression, other.expression) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitExpressionStatement(ExpressionStatement node) {
-    ExpressionStatement other = _other as ExpressionStatement;
-    return isEqualNodes(node.expression, other.expression) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitExtendsClause(ExtendsClause node) {
-    ExtendsClause other = _other as ExtendsClause;
-    return isEqualTokens(node.extendsKeyword, other.extendsKeyword) &&
-        isEqualNodes(node.superclass, other.superclass);
-  }
-
-  @override
-  bool visitFieldDeclaration(FieldDeclaration node) {
-    FieldDeclaration other = _other as FieldDeclaration;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.staticKeyword, other.staticKeyword) &&
-        isEqualNodes(node.fields, other.fields) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitFieldFormalParameter(FieldFormalParameter node) {
-    FieldFormalParameter other = _other as FieldFormalParameter;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.keyword, other.keyword) &&
-        isEqualNodes(node.type, other.type) &&
-        isEqualTokens(node.thisKeyword, other.thisKeyword) &&
-        isEqualTokens(node.period, other.period) &&
-        isEqualNodes(node.identifier, other.identifier);
-  }
-
-  @override
-  bool visitForEachStatement(ForEachStatement node) {
-    ForEachStatement other = _other as ForEachStatement;
-    return isEqualTokens(node.forKeyword, other.forKeyword) &&
-        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        isEqualNodes(node.loopVariable, other.loopVariable) &&
-        isEqualTokens(node.inKeyword, other.inKeyword) &&
-        isEqualNodes(node.iterable, other.iterable) &&
-        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
-        isEqualNodes(node.body, other.body);
-  }
-
-  @override
-  bool visitFormalParameterList(FormalParameterList node) {
-    FormalParameterList other = _other as FormalParameterList;
-    return isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        _isEqualNodeLists(node.parameters, other.parameters) &&
-        isEqualTokens(node.leftDelimiter, other.leftDelimiter) &&
-        isEqualTokens(node.rightDelimiter, other.rightDelimiter) &&
-        isEqualTokens(node.rightParenthesis, other.rightParenthesis);
-  }
-
-  @override
-  bool visitForStatement(ForStatement node) {
-    ForStatement other = _other as ForStatement;
-    return isEqualTokens(node.forKeyword, other.forKeyword) &&
-        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        isEqualNodes(node.variables, other.variables) &&
-        isEqualNodes(node.initialization, other.initialization) &&
-        isEqualTokens(node.leftSeparator, other.leftSeparator) &&
-        isEqualNodes(node.condition, other.condition) &&
-        isEqualTokens(node.rightSeparator, other.rightSeparator) &&
-        _isEqualNodeLists(node.updaters, other.updaters) &&
-        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
-        isEqualNodes(node.body, other.body);
-  }
-
-  @override
-  bool visitFunctionDeclaration(FunctionDeclaration node) {
-    FunctionDeclaration other = _other as FunctionDeclaration;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.externalKeyword, other.externalKeyword) &&
-        isEqualNodes(node.returnType, other.returnType) &&
-        isEqualTokens(node.propertyKeyword, other.propertyKeyword) &&
-        isEqualNodes(node.name, other.name) &&
-        isEqualNodes(node.functionExpression, other.functionExpression);
-  }
-
-  @override
-  bool visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
-    FunctionDeclarationStatement other = _other as FunctionDeclarationStatement;
-    return isEqualNodes(node.functionDeclaration, other.functionDeclaration);
-  }
-
-  @override
-  bool visitFunctionExpression(FunctionExpression node) {
-    FunctionExpression other = _other as FunctionExpression;
-    return isEqualNodes(node.parameters, other.parameters) &&
-        isEqualNodes(node.body, other.body);
-  }
-
-  @override
-  bool visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
-    FunctionExpressionInvocation other = _other as FunctionExpressionInvocation;
-    return isEqualNodes(node.function, other.function) &&
-        isEqualNodes(node.argumentList, other.argumentList);
-  }
-
-  @override
-  bool visitFunctionTypeAlias(FunctionTypeAlias node) {
-    FunctionTypeAlias other = _other as FunctionTypeAlias;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.typedefKeyword, other.typedefKeyword) &&
-        isEqualNodes(node.returnType, other.returnType) &&
-        isEqualNodes(node.name, other.name) &&
-        isEqualNodes(node.typeParameters, other.typeParameters) &&
-        isEqualNodes(node.parameters, other.parameters) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
-    FunctionTypedFormalParameter other = _other as FunctionTypedFormalParameter;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualNodes(node.returnType, other.returnType) &&
-        isEqualNodes(node.identifier, other.identifier) &&
-        isEqualNodes(node.parameters, other.parameters);
-  }
-
-  @override
-  bool visitHideCombinator(HideCombinator node) {
-    HideCombinator other = _other as HideCombinator;
-    return isEqualTokens(node.keyword, other.keyword) &&
-        _isEqualNodeLists(node.hiddenNames, other.hiddenNames);
-  }
-
-  @override
-  bool visitIfStatement(IfStatement node) {
-    IfStatement other = _other as IfStatement;
-    return isEqualTokens(node.ifKeyword, other.ifKeyword) &&
-        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        isEqualNodes(node.condition, other.condition) &&
-        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
-        isEqualNodes(node.thenStatement, other.thenStatement) &&
-        isEqualTokens(node.elseKeyword, other.elseKeyword) &&
-        isEqualNodes(node.elseStatement, other.elseStatement);
-  }
-
-  @override
-  bool visitImplementsClause(ImplementsClause node) {
-    ImplementsClause other = _other as ImplementsClause;
-    return isEqualTokens(node.implementsKeyword, other.implementsKeyword) &&
-        _isEqualNodeLists(node.interfaces, other.interfaces);
-  }
-
-  @override
-  bool visitImportDirective(ImportDirective node) {
-    ImportDirective other = _other as ImportDirective;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.keyword, other.keyword) &&
-        isEqualNodes(node.uri, other.uri) &&
-        isEqualTokens(node.deferredKeyword, other.deferredKeyword) &&
-        isEqualTokens(node.asKeyword, other.asKeyword) &&
-        isEqualNodes(node.prefix, other.prefix) &&
-        _isEqualNodeLists(node.combinators, other.combinators) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitIndexExpression(IndexExpression node) {
-    IndexExpression other = _other as IndexExpression;
-    return isEqualNodes(node.target, other.target) &&
-        isEqualTokens(node.leftBracket, other.leftBracket) &&
-        isEqualNodes(node.index, other.index) &&
-        isEqualTokens(node.rightBracket, other.rightBracket);
-  }
-
-  @override
-  bool visitInstanceCreationExpression(InstanceCreationExpression node) {
-    InstanceCreationExpression other = _other as InstanceCreationExpression;
-    return isEqualTokens(node.keyword, other.keyword) &&
-        isEqualNodes(node.constructorName, other.constructorName) &&
-        isEqualNodes(node.argumentList, other.argumentList);
-  }
-
-  @override
-  bool visitIntegerLiteral(IntegerLiteral node) {
-    IntegerLiteral other = _other as IntegerLiteral;
-    return isEqualTokens(node.literal, other.literal) &&
-        (node.value == other.value);
-  }
-
-  @override
-  bool visitInterpolationExpression(InterpolationExpression node) {
-    InterpolationExpression other = _other as InterpolationExpression;
-    return isEqualTokens(node.leftBracket, other.leftBracket) &&
-        isEqualNodes(node.expression, other.expression) &&
-        isEqualTokens(node.rightBracket, other.rightBracket);
-  }
-
-  @override
-  bool visitInterpolationString(InterpolationString node) {
-    InterpolationString other = _other as InterpolationString;
-    return isEqualTokens(node.contents, other.contents) &&
-        node.value == other.value;
-  }
-
-  @override
-  bool visitIsExpression(IsExpression node) {
-    IsExpression other = _other as IsExpression;
-    return isEqualNodes(node.expression, other.expression) &&
-        isEqualTokens(node.isOperator, other.isOperator) &&
-        isEqualTokens(node.notOperator, other.notOperator) &&
-        isEqualNodes(node.type, other.type);
-  }
-
-  @override
-  bool visitLabel(Label node) {
-    Label other = _other as Label;
-    return isEqualNodes(node.label, other.label) &&
-        isEqualTokens(node.colon, other.colon);
-  }
-
-  @override
-  bool visitLabeledStatement(LabeledStatement node) {
-    LabeledStatement other = _other as LabeledStatement;
-    return _isEqualNodeLists(node.labels, other.labels) &&
-        isEqualNodes(node.statement, other.statement);
-  }
-
-  @override
-  bool visitLibraryDirective(LibraryDirective node) {
-    LibraryDirective other = _other as LibraryDirective;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.libraryKeyword, other.libraryKeyword) &&
-        isEqualNodes(node.name, other.name) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitLibraryIdentifier(LibraryIdentifier node) {
-    LibraryIdentifier other = _other as LibraryIdentifier;
-    return _isEqualNodeLists(node.components, other.components);
-  }
-
-  @override
-  bool visitListLiteral(ListLiteral node) {
-    ListLiteral other = _other as ListLiteral;
-    return isEqualTokens(node.constKeyword, other.constKeyword) &&
-        isEqualNodes(node.typeArguments, other.typeArguments) &&
-        isEqualTokens(node.leftBracket, other.leftBracket) &&
-        _isEqualNodeLists(node.elements, other.elements) &&
-        isEqualTokens(node.rightBracket, other.rightBracket);
-  }
-
-  @override
-  bool visitMapLiteral(MapLiteral node) {
-    MapLiteral other = _other as MapLiteral;
-    return isEqualTokens(node.constKeyword, other.constKeyword) &&
-        isEqualNodes(node.typeArguments, other.typeArguments) &&
-        isEqualTokens(node.leftBracket, other.leftBracket) &&
-        _isEqualNodeLists(node.entries, other.entries) &&
-        isEqualTokens(node.rightBracket, other.rightBracket);
-  }
-
-  @override
-  bool visitMapLiteralEntry(MapLiteralEntry node) {
-    MapLiteralEntry other = _other as MapLiteralEntry;
-    return isEqualNodes(node.key, other.key) &&
-        isEqualTokens(node.separator, other.separator) &&
-        isEqualNodes(node.value, other.value);
-  }
-
-  @override
-  bool visitMethodDeclaration(MethodDeclaration node) {
-    MethodDeclaration other = _other as MethodDeclaration;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.externalKeyword, other.externalKeyword) &&
-        isEqualTokens(node.modifierKeyword, other.modifierKeyword) &&
-        isEqualNodes(node.returnType, other.returnType) &&
-        isEqualTokens(node.propertyKeyword, other.propertyKeyword) &&
-        isEqualTokens(node.propertyKeyword, other.propertyKeyword) &&
-        isEqualNodes(node.name, other.name) &&
-        isEqualNodes(node.parameters, other.parameters) &&
-        isEqualNodes(node.body, other.body);
-  }
-
-  @override
-  bool visitMethodInvocation(MethodInvocation node) {
-    MethodInvocation other = _other as MethodInvocation;
-    return isEqualNodes(node.target, other.target) &&
-        isEqualTokens(node.operator, other.operator) &&
-        isEqualNodes(node.methodName, other.methodName) &&
-        isEqualNodes(node.argumentList, other.argumentList);
-  }
-
-  @override
-  bool visitNamedExpression(NamedExpression node) {
-    NamedExpression other = _other as NamedExpression;
-    return isEqualNodes(node.name, other.name) &&
-        isEqualNodes(node.expression, other.expression);
-  }
-
-  @override
-  bool visitNativeClause(NativeClause node) {
-    NativeClause other = _other as NativeClause;
-    return isEqualTokens(node.nativeKeyword, other.nativeKeyword) &&
-        isEqualNodes(node.name, other.name);
-  }
-
-  @override
-  bool visitNativeFunctionBody(NativeFunctionBody node) {
-    NativeFunctionBody other = _other as NativeFunctionBody;
-    return isEqualTokens(node.nativeKeyword, other.nativeKeyword) &&
-        isEqualNodes(node.stringLiteral, other.stringLiteral) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitNullLiteral(NullLiteral node) {
-    NullLiteral other = _other as NullLiteral;
-    return isEqualTokens(node.literal, other.literal);
-  }
-
-  @override
-  bool visitParenthesizedExpression(ParenthesizedExpression node) {
-    ParenthesizedExpression other = _other as ParenthesizedExpression;
-    return isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        isEqualNodes(node.expression, other.expression) &&
-        isEqualTokens(node.rightParenthesis, other.rightParenthesis);
-  }
-
-  @override
-  bool visitPartDirective(PartDirective node) {
-    PartDirective other = _other as PartDirective;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.partKeyword, other.partKeyword) &&
-        isEqualNodes(node.uri, other.uri) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitPartOfDirective(PartOfDirective node) {
-    PartOfDirective other = _other as PartOfDirective;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.partKeyword, other.partKeyword) &&
-        isEqualTokens(node.ofKeyword, other.ofKeyword) &&
-        isEqualNodes(node.libraryName, other.libraryName) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitPostfixExpression(PostfixExpression node) {
-    PostfixExpression other = _other as PostfixExpression;
-    return isEqualNodes(node.operand, other.operand) &&
-        isEqualTokens(node.operator, other.operator);
-  }
-
-  @override
-  bool visitPrefixedIdentifier(PrefixedIdentifier node) {
-    PrefixedIdentifier other = _other as PrefixedIdentifier;
-    return isEqualNodes(node.prefix, other.prefix) &&
-        isEqualTokens(node.period, other.period) &&
-        isEqualNodes(node.identifier, other.identifier);
-  }
-
-  @override
-  bool visitPrefixExpression(PrefixExpression node) {
-    PrefixExpression other = _other as PrefixExpression;
-    return isEqualTokens(node.operator, other.operator) &&
-        isEqualNodes(node.operand, other.operand);
-  }
-
-  @override
-  bool visitPropertyAccess(PropertyAccess node) {
-    PropertyAccess other = _other as PropertyAccess;
-    return isEqualNodes(node.target, other.target) &&
-        isEqualTokens(node.operator, other.operator) &&
-        isEqualNodes(node.propertyName, other.propertyName);
-  }
-
-  @override
-  bool visitRedirectingConstructorInvocation(
-      RedirectingConstructorInvocation node) {
-    RedirectingConstructorInvocation other =
-        _other as RedirectingConstructorInvocation;
-    return isEqualTokens(node.thisKeyword, other.thisKeyword) &&
-        isEqualTokens(node.period, other.period) &&
-        isEqualNodes(node.constructorName, other.constructorName) &&
-        isEqualNodes(node.argumentList, other.argumentList);
-  }
-
-  @override
-  bool visitRethrowExpression(RethrowExpression node) {
-    RethrowExpression other = _other as RethrowExpression;
-    return isEqualTokens(node.rethrowKeyword, other.rethrowKeyword);
-  }
-
-  @override
-  bool visitReturnStatement(ReturnStatement node) {
-    ReturnStatement other = _other as ReturnStatement;
-    return isEqualTokens(node.returnKeyword, other.returnKeyword) &&
-        isEqualNodes(node.expression, other.expression) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitScriptTag(ScriptTag node) {
-    ScriptTag other = _other as ScriptTag;
-    return isEqualTokens(node.scriptTag, other.scriptTag);
-  }
-
-  @override
-  bool visitShowCombinator(ShowCombinator node) {
-    ShowCombinator other = _other as ShowCombinator;
-    return isEqualTokens(node.keyword, other.keyword) &&
-        _isEqualNodeLists(node.shownNames, other.shownNames);
-  }
-
-  @override
-  bool visitSimpleFormalParameter(SimpleFormalParameter node) {
-    SimpleFormalParameter other = _other as SimpleFormalParameter;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.keyword, other.keyword) &&
-        isEqualNodes(node.type, other.type) &&
-        isEqualNodes(node.identifier, other.identifier);
-  }
-
-  @override
-  bool visitSimpleIdentifier(SimpleIdentifier node) {
-    SimpleIdentifier other = _other as SimpleIdentifier;
-    return isEqualTokens(node.token, other.token);
-  }
-
-  @override
-  bool visitSimpleStringLiteral(SimpleStringLiteral node) {
-    SimpleStringLiteral other = _other as SimpleStringLiteral;
-    return isEqualTokens(node.literal, other.literal) &&
-        (node.value == other.value);
-  }
-
-  @override
-  bool visitStringInterpolation(StringInterpolation node) {
-    StringInterpolation other = _other as StringInterpolation;
-    return _isEqualNodeLists(node.elements, other.elements);
-  }
-
-  @override
-  bool visitSuperConstructorInvocation(SuperConstructorInvocation node) {
-    SuperConstructorInvocation other = _other as SuperConstructorInvocation;
-    return isEqualTokens(node.superKeyword, other.superKeyword) &&
-        isEqualTokens(node.period, other.period) &&
-        isEqualNodes(node.constructorName, other.constructorName) &&
-        isEqualNodes(node.argumentList, other.argumentList);
-  }
-
-  @override
-  bool visitSuperExpression(SuperExpression node) {
-    SuperExpression other = _other as SuperExpression;
-    return isEqualTokens(node.superKeyword, other.superKeyword);
-  }
-
-  @override
-  bool visitSwitchCase(SwitchCase node) {
-    SwitchCase other = _other as SwitchCase;
-    return _isEqualNodeLists(node.labels, other.labels) &&
-        isEqualTokens(node.keyword, other.keyword) &&
-        isEqualNodes(node.expression, other.expression) &&
-        isEqualTokens(node.colon, other.colon) &&
-        _isEqualNodeLists(node.statements, other.statements);
-  }
-
-  @override
-  bool visitSwitchDefault(SwitchDefault node) {
-    SwitchDefault other = _other as SwitchDefault;
-    return _isEqualNodeLists(node.labels, other.labels) &&
-        isEqualTokens(node.keyword, other.keyword) &&
-        isEqualTokens(node.colon, other.colon) &&
-        _isEqualNodeLists(node.statements, other.statements);
-  }
-
-  @override
-  bool visitSwitchStatement(SwitchStatement node) {
-    SwitchStatement other = _other as SwitchStatement;
-    return isEqualTokens(node.switchKeyword, other.switchKeyword) &&
-        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        isEqualNodes(node.expression, other.expression) &&
-        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
-        isEqualTokens(node.leftBracket, other.leftBracket) &&
-        _isEqualNodeLists(node.members, other.members) &&
-        isEqualTokens(node.rightBracket, other.rightBracket);
-  }
-
-  @override
-  bool visitSymbolLiteral(SymbolLiteral node) {
-    SymbolLiteral other = _other as SymbolLiteral;
-    return isEqualTokens(node.poundSign, other.poundSign) &&
-        _isEqualTokenLists(node.components, other.components);
-  }
-
-  @override
-  bool visitThisExpression(ThisExpression node) {
-    ThisExpression other = _other as ThisExpression;
-    return isEqualTokens(node.thisKeyword, other.thisKeyword);
-  }
-
-  @override
-  bool visitThrowExpression(ThrowExpression node) {
-    ThrowExpression other = _other as ThrowExpression;
-    return isEqualTokens(node.throwKeyword, other.throwKeyword) &&
-        isEqualNodes(node.expression, other.expression);
-  }
-
-  @override
-  bool visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    TopLevelVariableDeclaration other = _other as TopLevelVariableDeclaration;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualNodes(node.variables, other.variables) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitTryStatement(TryStatement node) {
-    TryStatement other = _other as TryStatement;
-    return isEqualTokens(node.tryKeyword, other.tryKeyword) &&
-        isEqualNodes(node.body, other.body) &&
-        _isEqualNodeLists(node.catchClauses, other.catchClauses) &&
-        isEqualTokens(node.finallyKeyword, other.finallyKeyword) &&
-        isEqualNodes(node.finallyBlock, other.finallyBlock);
-  }
-
-  @override
-  bool visitTypeArgumentList(TypeArgumentList node) {
-    TypeArgumentList other = _other as TypeArgumentList;
-    return isEqualTokens(node.leftBracket, other.leftBracket) &&
-        _isEqualNodeLists(node.arguments, other.arguments) &&
-        isEqualTokens(node.rightBracket, other.rightBracket);
-  }
-
-  @override
-  bool visitTypeName(TypeName node) {
-    TypeName other = _other as TypeName;
-    return isEqualNodes(node.name, other.name) &&
-        isEqualNodes(node.typeArguments, other.typeArguments);
-  }
-
-  @override
-  bool visitTypeParameter(TypeParameter node) {
-    TypeParameter other = _other as TypeParameter;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualNodes(node.name, other.name) &&
-        isEqualTokens(node.extendsKeyword, other.extendsKeyword) &&
-        isEqualNodes(node.bound, other.bound);
-  }
-
-  @override
-  bool visitTypeParameterList(TypeParameterList node) {
-    TypeParameterList other = _other as TypeParameterList;
-    return isEqualTokens(node.leftBracket, other.leftBracket) &&
-        _isEqualNodeLists(node.typeParameters, other.typeParameters) &&
-        isEqualTokens(node.rightBracket, other.rightBracket);
-  }
-
-  @override
-  bool visitVariableDeclaration(VariableDeclaration node) {
-    VariableDeclaration other = _other as VariableDeclaration;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualNodes(node.name, other.name) &&
-        isEqualTokens(node.equals, other.equals) &&
-        isEqualNodes(node.initializer, other.initializer);
-  }
-
-  @override
-  bool visitVariableDeclarationList(VariableDeclarationList node) {
-    VariableDeclarationList other = _other as VariableDeclarationList;
-    return isEqualNodes(
-            node.documentationComment, other.documentationComment) &&
-        _isEqualNodeLists(node.metadata, other.metadata) &&
-        isEqualTokens(node.keyword, other.keyword) &&
-        isEqualNodes(node.type, other.type) &&
-        _isEqualNodeLists(node.variables, other.variables);
-  }
-
-  @override
-  bool visitVariableDeclarationStatement(VariableDeclarationStatement node) {
-    VariableDeclarationStatement other = _other as VariableDeclarationStatement;
-    return isEqualNodes(node.variables, other.variables) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  @override
-  bool visitWhileStatement(WhileStatement node) {
-    WhileStatement other = _other as WhileStatement;
-    return isEqualTokens(node.whileKeyword, other.whileKeyword) &&
-        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        isEqualNodes(node.condition, other.condition) &&
-        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
-        isEqualNodes(node.body, other.body);
-  }
-
-  @override
-  bool visitWithClause(WithClause node) {
-    WithClause other = _other as WithClause;
-    return isEqualTokens(node.withKeyword, other.withKeyword) &&
-        _isEqualNodeLists(node.mixinTypes, other.mixinTypes);
-  }
-
-  @override
-  bool visitYieldStatement(YieldStatement node) {
-    YieldStatement other = _other as YieldStatement;
-    return isEqualTokens(node.yieldKeyword, other.yieldKeyword) &&
-        isEqualNodes(node.expression, other.expression) &&
-        isEqualTokens(node.semicolon, other.semicolon);
-  }
-
-  /**
-   * Return `true` if the [first] and [second] lists of AST nodes have the same
-   * size and corresponding elements are equal.
-   */
-  bool _isEqualNodeLists(NodeList first, NodeList second) {
-    if (first == null) {
-      return second == null;
-    } else if (second == null) {
-      return false;
-    }
-    int size = first.length;
-    if (second.length != size) {
-      return false;
-    }
-    for (int i = 0; i < size; i++) {
-      if (!isEqualNodes(first[i], second[i])) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  /**
-   * Return `true` if the [first] and [second] lists of tokens have the same
-   * length and corresponding elements are equal.
-   */
-  bool _isEqualTokenLists(List<Token> first, List<Token> second) {
-    int length = first.length;
-    if (second.length != length) {
-      return false;
-    }
-    for (int i = 0; i < length; i++) {
-      if (!isEqualTokens(first[i], second[i])) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  /**
-   * Return `true` if the [first] and [second] nodes are equal.
-   */
-  static bool equalNodes(AstNode first, AstNode second) {
-    AstComparator comparator = new AstComparator();
-    return comparator.isEqualNodes(first, second);
-  }
-}
-
-/**
  * A node in the AST structure for a Dart program.
  */
 abstract class AstNode {
@@ -3671,61 +1719,6 @@
 }
 
 /**
- * An AST visitor that will recursively visit all of the nodes in an AST
- * structure, similar to [GeneralizingAstVisitor]. This visitor uses a
- * breadth-first ordering rather than the depth-first ordering of
- * [GeneralizingAstVisitor].
- *
- * Subclasses that override a visit method must either invoke the overridden
- * visit method or explicitly invoke the more general visit method. Failure to
- * do so will cause the visit methods for superclasses of the node to not be
- * invoked and will cause the children of the visited node to not be visited.
- *
- * In addition, subclasses should <b>not</b> explicitly visit the children of a
- * node, but should ensure that the method [visitNode] is used to visit the
- * children (either directly or indirectly). Failure to do will break the order
- * in which nodes are visited.
- */
-class BreadthFirstVisitor<R> extends GeneralizingAstVisitor<R> {
-  /**
-   * A queue holding the nodes that have not yet been visited in the order in
-   * which they ought to be visited.
-   */
-  Queue<AstNode> _queue = new Queue<AstNode>();
-
-  /**
-   * A visitor, used to visit the children of the current node, that will add
-   * the nodes it visits to the [_queue].
-   */
-  GeneralizingAstVisitor<Object> _childVisitor;
-
-  /**
-   * Initialize a newly created visitor.
-   */
-  BreadthFirstVisitor() {
-    _childVisitor = new GeneralizingAstVisitor_BreadthFirstVisitor(this);
-  }
-
-  /**
-   * Visit all nodes in the tree starting at the given [root] node, in
-   * breadth-first order.
-   */
-  void visitAllNodes(AstNode root) {
-    _queue.add(root);
-    while (!_queue.isEmpty) {
-      AstNode next = _queue.removeFirst();
-      next.accept(this);
-    }
-  }
-
-  @override
-  R visitNode(AstNode node) {
-    node.visitChildren(_childVisitor);
-    return null;
-  }
-}
-
-/**
  * A break statement.
  *
  * > breakStatement ::=
@@ -5129,373 +3122,6 @@
   }
 }
 
-/// Instances of the class [ConstantEvaluator] evaluate constant expressions to
-/// produce their compile-time value.
-///
-/// According to the Dart Language Specification:
-///
-/// > A constant expression is one of the following:
-/// >
-/// > * A literal number.
-/// > * A literal boolean.
-/// > * A literal string where any interpolated expression is a compile-time
-/// >   constant that evaluates to a numeric, string or boolean value or to
-/// >   **null**.
-/// > * A literal symbol.
-/// > * **null**.
-/// > * A qualified reference to a static constant variable.
-/// > * An identifier expression that denotes a constant variable, class or type
-/// >   alias.
-/// > * A constant constructor invocation.
-/// > * A constant list literal.
-/// > * A constant map literal.
-/// > * A simple or qualified identifier denoting a top-level function or a
-/// >   static method.
-/// > * A parenthesized expression _(e)_ where _e_ is a constant expression.
-/// > * <span>
-/// >   An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i>
-/// >   where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
-/// >   expressions and <i>identical()</i> is statically bound to the predefined
-/// >   dart function <i>identical()</i> discussed above.
-/// >   </span>
-/// > * <span>
-/// >   An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i>
-/// >   or <i>e<sub>1</sub> != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and
-/// >   <i>e<sub>2</sub></i> are constant expressions that evaluate to a
-/// >   numeric, string or boolean value.
-/// >   </span>
-/// > * <span>
-/// >   An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> &amp;&amp;
-/// >   e<sub>2</sub></i> or <i>e<sub>1</sub> || e<sub>2</sub></i>, where
-/// >   <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
-/// >   expressions that evaluate to a boolean value.
-/// >   </span>
-/// > * <span>
-/// >   An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^
-/// >   e<sub>2</sub></i>, <i>e<sub>1</sub> &amp; e<sub>2</sub></i>,
-/// >   <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;&gt;
-/// >   e<sub>2</sub></i> or <i>e<sub>1</sub> &lt;&lt; e<sub>2</sub></i>, where
-/// >   <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
-/// >   expressions that evaluate to an integer value or to <b>null</b>.
-/// >   </span>
-/// > * <span>
-/// >   An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> +
-/// >   e<sub>2</sub></i>, <i>e<sub>1</sub> -e<sub>2</sub></i>,
-/// >   <i>e<sub>1</sub> * e<sub>2</sub></i>, <i>e<sub>1</sub> /
-/// >   e<sub>2</sub></i>, <i>e<sub>1</sub> ~/ e<sub>2</sub></i>,
-/// >   <i>e<sub>1</sub> &gt; e<sub>2</sub></i>, <i>e<sub>1</sub> &lt;
-/// >   e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;= e<sub>2</sub></i>,
-/// >   <i>e<sub>1</sub> &lt;= e<sub>2</sub></i> or <i>e<sub>1</sub> %
-/// >   e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i> and
-/// >   <i>e<sub>2</sub></i> are constant expressions that evaluate to a numeric
-/// >   value or to <b>null</b>.
-/// >   </span>
-/// > * <span>
-/// >   An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> :
-/// >   e<sub>3</sub></i> where <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and
-/// >   <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i>
-/// >   evaluates to a boolean value.
-/// >   </span>
-///
-/// The values returned by instances of this class are therefore `null` and
-/// instances of the classes `Boolean`, `BigInteger`, `Double`, `String`, and
-/// `DartObject`.
-///
-/// In addition, this class defines several values that can be returned to
-/// indicate various conditions encountered during evaluation. These are
-/// documented with the static fields that define those values.
-class ConstantEvaluator extends GeneralizingAstVisitor<Object> {
-  /**
-   * The value returned for expressions (or non-expression nodes) that are not
-   * compile-time constant expressions.
-   */
-  static Object NOT_A_CONSTANT = new Object();
-
-  @override
-  Object visitAdjacentStrings(AdjacentStrings node) {
-    StringBuffer buffer = new StringBuffer();
-    for (StringLiteral string in node.strings) {
-      Object value = string.accept(this);
-      if (identical(value, NOT_A_CONSTANT)) {
-        return value;
-      }
-      buffer.write(value);
-    }
-    return buffer.toString();
-  }
-
-  @override
-  Object visitBinaryExpression(BinaryExpression node) {
-    Object leftOperand = node.leftOperand.accept(this);
-    if (identical(leftOperand, NOT_A_CONSTANT)) {
-      return leftOperand;
-    }
-    Object rightOperand = node.rightOperand.accept(this);
-    if (identical(rightOperand, NOT_A_CONSTANT)) {
-      return rightOperand;
-    }
-    while (true) {
-      if (node.operator.type == TokenType.AMPERSAND) {
-        // integer or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand & rightOperand;
-        }
-      } else if (node.operator.type == TokenType.AMPERSAND_AMPERSAND) {
-        // boolean or {@code null}
-        if (leftOperand is bool && rightOperand is bool) {
-          return leftOperand && rightOperand;
-        }
-      } else if (node.operator.type == TokenType.BANG_EQ) {
-        // numeric, string, boolean, or {@code null}
-        if (leftOperand is bool && rightOperand is bool) {
-          return leftOperand != rightOperand;
-        } else if (leftOperand is num && rightOperand is num) {
-          return leftOperand != rightOperand;
-        } else if (leftOperand is String && rightOperand is String) {
-          return leftOperand != rightOperand;
-        }
-      } else if (node.operator.type == TokenType.BAR) {
-        // integer or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand | rightOperand;
-        }
-      } else if (node.operator.type == TokenType.BAR_BAR) {
-        // boolean or {@code null}
-        if (leftOperand is bool && rightOperand is bool) {
-          return leftOperand || rightOperand;
-        }
-      } else if (node.operator.type == TokenType.CARET) {
-        // integer or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand ^ rightOperand;
-        }
-      } else if (node.operator.type == TokenType.EQ_EQ) {
-        // numeric, string, boolean, or {@code null}
-        if (leftOperand is bool && rightOperand is bool) {
-          return leftOperand == rightOperand;
-        } else if (leftOperand is num && rightOperand is num) {
-          return leftOperand == rightOperand;
-        } else if (leftOperand is String && rightOperand is String) {
-          return leftOperand == rightOperand;
-        }
-      } else if (node.operator.type == TokenType.GT) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand.compareTo(rightOperand) > 0;
-        }
-      } else if (node.operator.type == TokenType.GT_EQ) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand.compareTo(rightOperand) >= 0;
-        }
-      } else if (node.operator.type == TokenType.GT_GT) {
-        // integer or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand >> rightOperand;
-        }
-      } else if (node.operator.type == TokenType.LT) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand.compareTo(rightOperand) < 0;
-        }
-      } else if (node.operator.type == TokenType.LT_EQ) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand.compareTo(rightOperand) <= 0;
-        }
-      } else if (node.operator.type == TokenType.LT_LT) {
-        // integer or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand << rightOperand;
-        }
-      } else if (node.operator.type == TokenType.MINUS) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand - rightOperand;
-        }
-      } else if (node.operator.type == TokenType.PERCENT) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand.remainder(rightOperand);
-        }
-      } else if (node.operator.type == TokenType.PLUS) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand + rightOperand;
-        }
-      } else if (node.operator.type == TokenType.STAR) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand * rightOperand;
-        }
-      } else if (node.operator.type == TokenType.SLASH) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand / rightOperand;
-        }
-      } else if (node.operator.type == TokenType.TILDE_SLASH) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand ~/ rightOperand;
-        }
-      } else {}
-      break;
-    }
-    // TODO(brianwilkerson) This doesn't handle numeric conversions.
-    return visitExpression(node);
-  }
-
-  @override
-  Object visitBooleanLiteral(BooleanLiteral node) => node.value ? true : false;
-
-  @override
-  Object visitDoubleLiteral(DoubleLiteral node) => node.value;
-
-  @override
-  Object visitIntegerLiteral(IntegerLiteral node) => node.value;
-
-  @override
-  Object visitInterpolationExpression(InterpolationExpression node) {
-    Object value = node.expression.accept(this);
-    if (value == null || value is bool || value is String || value is num) {
-      return value;
-    }
-    return NOT_A_CONSTANT;
-  }
-
-  @override
-  Object visitInterpolationString(InterpolationString node) => node.value;
-
-  @override
-  Object visitListLiteral(ListLiteral node) {
-    List<Object> list = new List<Object>();
-    for (Expression element in node.elements) {
-      Object value = element.accept(this);
-      if (identical(value, NOT_A_CONSTANT)) {
-        return value;
-      }
-      list.add(value);
-    }
-    return list;
-  }
-
-  @override
-  Object visitMapLiteral(MapLiteral node) {
-    HashMap<String, Object> map = new HashMap<String, Object>();
-    for (MapLiteralEntry entry in node.entries) {
-      Object key = entry.key.accept(this);
-      Object value = entry.value.accept(this);
-      if (key is! String || identical(value, NOT_A_CONSTANT)) {
-        return NOT_A_CONSTANT;
-      }
-      map[(key as String)] = value;
-    }
-    return map;
-  }
-
-  @override
-  Object visitMethodInvocation(MethodInvocation node) => visitNode(node);
-
-  @override
-  Object visitNode(AstNode node) => NOT_A_CONSTANT;
-
-  @override
-  Object visitNullLiteral(NullLiteral node) => null;
-
-  @override
-  Object visitParenthesizedExpression(ParenthesizedExpression node) =>
-      node.expression.accept(this);
-
-  @override
-  Object visitPrefixedIdentifier(PrefixedIdentifier node) =>
-      _getConstantValue(null);
-
-  @override
-  Object visitPrefixExpression(PrefixExpression node) {
-    Object operand = node.operand.accept(this);
-    if (identical(operand, NOT_A_CONSTANT)) {
-      return operand;
-    }
-    while (true) {
-      if (node.operator.type == TokenType.BANG) {
-        if (identical(operand, true)) {
-          return false;
-        } else if (identical(operand, false)) {
-          return true;
-        }
-      } else if (node.operator.type == TokenType.TILDE) {
-        if (operand is int) {
-          return ~operand;
-        }
-      } else if (node.operator.type == TokenType.MINUS) {
-        if (operand == null) {
-          return null;
-        } else if (operand is num) {
-          return -operand;
-        }
-      } else {}
-      break;
-    }
-    return NOT_A_CONSTANT;
-  }
-
-  @override
-  Object visitPropertyAccess(PropertyAccess node) => _getConstantValue(null);
-
-  @override
-  Object visitSimpleIdentifier(SimpleIdentifier node) =>
-      _getConstantValue(null);
-
-  @override
-  Object visitSimpleStringLiteral(SimpleStringLiteral node) => node.value;
-
-  @override
-  Object visitStringInterpolation(StringInterpolation node) {
-    StringBuffer buffer = new StringBuffer();
-    for (InterpolationElement element in node.elements) {
-      Object value = element.accept(this);
-      if (identical(value, NOT_A_CONSTANT)) {
-        return value;
-      }
-      buffer.write(value);
-    }
-    return buffer.toString();
-  }
-
-  @override
-  Object visitSymbolLiteral(SymbolLiteral node) {
-    // TODO(brianwilkerson) This isn't optimal because a Symbol is not a String.
-    StringBuffer buffer = new StringBuffer();
-    for (Token component in node.components) {
-      if (buffer.length > 0) {
-        buffer.writeCharCode(0x2E);
-      }
-      buffer.write(component.lexeme);
-    }
-    return buffer.toString();
-  }
-
-  /**
-   * Return the constant value of the static constant represented by the given
-   * [element].
-   */
-  Object _getConstantValue(Element element) {
-    // TODO(brianwilkerson) Implement this
-    if (element is FieldElement) {
-      FieldElement field = element;
-      if (field.isStatic && field.isConst) {
-        //field.getConstantValue();
-      }
-      //    } else if (element instanceof VariableElement) {
-      //      VariableElement variable = (VariableElement) element;
-      //      if (variable.isStatic() && variable.isConst()) {
-      //        //variable.getConstantValue();
-      //      }
-    }
-    return NOT_A_CONSTANT;
-  }
-}
-
 /**
  * A constructor declaration.
  *
@@ -6265,37 +3891,6 @@
 }
 
 /**
- * A recursive AST visitor that is used to run over [Expression]s to determine
- * whether the expression is composed by at least one deferred
- * [PrefixedIdentifier].
- *
- * See [PrefixedIdentifier.isDeferred].
- */
-class DeferredLibraryReferenceDetector extends RecursiveAstVisitor<Object> {
-  /**
-   * A flag indicating whether an identifier from a deferred library has been
-   * found.
-   */
-  bool _result = false;
-
-  /**
-   * Return `true` if the visitor found a [PrefixedIdentifier] that returned
-   * `true` to the [PrefixedIdentifier.isDeferred] query.
-   */
-  bool get result => _result;
-
-  @override
-  Object visitPrefixedIdentifier(PrefixedIdentifier node) {
-    if (!_result) {
-      if (node.isDeferred) {
-        _result = true;
-      }
-    }
-    return null;
-  }
-}
-
-/**
  * A node that represents a directive.
  *
  * > directive ::=
@@ -6523,134 +4118,6 @@
 }
 
 /**
- * An object used to locate the [Element] associated with a given [AstNode].
- */
-class ElementLocator {
-  /**
-   * Return the element associated with the given [node], or `null` if there is
-   * no element associated with the node.
-   */
-  static Element locate(AstNode node) {
-    if (node == null) {
-      return null;
-    }
-    ElementLocator_ElementMapper mapper = new ElementLocator_ElementMapper();
-    return node.accept(mapper);
-  }
-}
-
-/**
- * Visitor that maps nodes to elements.
- */
-class ElementLocator_ElementMapper extends GeneralizingAstVisitor<Element> {
-  @override
-  Element visitAnnotation(Annotation node) => node.element;
-
-  @override
-  Element visitAssignmentExpression(AssignmentExpression node) =>
-      node.bestElement;
-
-  @override
-  Element visitBinaryExpression(BinaryExpression node) => node.bestElement;
-
-  @override
-  Element visitClassDeclaration(ClassDeclaration node) => node.element;
-
-  @override
-  Element visitCompilationUnit(CompilationUnit node) => node.element;
-
-  @override
-  Element visitConstructorDeclaration(ConstructorDeclaration node) =>
-      node.element;
-
-  @override
-  Element visitFunctionDeclaration(FunctionDeclaration node) => node.element;
-
-  @override
-  Element visitIdentifier(Identifier node) {
-    AstNode parent = node.parent;
-    // Type name in Annotation
-    if (parent is Annotation) {
-      Annotation annotation = parent;
-      if (identical(annotation.name, node) &&
-          annotation.constructorName == null) {
-        return annotation.element;
-      }
-    }
-    // Extra work to map Constructor Declarations to their associated
-    // Constructor Elements
-    if (parent is ConstructorDeclaration) {
-      ConstructorDeclaration decl = parent;
-      Identifier returnType = decl.returnType;
-      if (identical(returnType, node)) {
-        SimpleIdentifier name = decl.name;
-        if (name != null) {
-          return name.bestElement;
-        }
-        Element element = node.bestElement;
-        if (element is ClassElement) {
-          return element.unnamedConstructor;
-        }
-      }
-    }
-    if (parent is LibraryIdentifier) {
-      AstNode grandParent = parent.parent;
-      if (grandParent is PartOfDirective) {
-        Element element = grandParent.element;
-        if (element is LibraryElement) {
-          return element.definingCompilationUnit;
-        }
-      }
-    }
-    return node.bestElement;
-  }
-
-  @override
-  Element visitImportDirective(ImportDirective node) => node.element;
-
-  @override
-  Element visitIndexExpression(IndexExpression node) => node.bestElement;
-
-  @override
-  Element visitInstanceCreationExpression(InstanceCreationExpression node) =>
-      node.staticElement;
-
-  @override
-  Element visitLibraryDirective(LibraryDirective node) => node.element;
-
-  @override
-  Element visitMethodDeclaration(MethodDeclaration node) => node.element;
-
-  @override
-  Element visitMethodInvocation(MethodInvocation node) =>
-      node.methodName.bestElement;
-
-  @override
-  Element visitPartOfDirective(PartOfDirective node) => node.element;
-
-  @override
-  Element visitPostfixExpression(PostfixExpression node) => node.bestElement;
-
-  @override
-  Element visitPrefixedIdentifier(PrefixedIdentifier node) => node.bestElement;
-
-  @override
-  Element visitPrefixExpression(PrefixExpression node) => node.bestElement;
-
-  @override
-  Element visitStringLiteral(StringLiteral node) {
-    AstNode parent = node.parent;
-    if (parent is UriBasedDirective) {
-      return parent.uriElement;
-    }
-    return null;
-  }
-
-  @override
-  Element visitVariableDeclaration(VariableDeclaration node) => node.element;
-}
-
-/**
  * An empty function body, which can only appear in constructors or abstract
  * methods.
  *
@@ -8380,7 +5847,7 @@
  * [MethodInvocation] nodes. Invocations of getters and setters are represented
  * by either [PrefixedIdentifier] or [PropertyAccess] nodes.
  *
- * > functionExpressionInvoction ::=
+ * > functionExpressionInvocation ::=
  * >     [Expression] [TypeArgumentList]? [ArgumentList]
  */
 class FunctionExpressionInvocation extends Expression {
@@ -8736,447 +6203,6 @@
 }
 
 /**
- * An AST visitor that will recursively visit all of the nodes in an AST
- * structure (like instances of the class [RecursiveAstVisitor]). In addition,
- * when a node of a specific type is visited not only will the visit method for
- * that specific type of node be invoked, but additional methods for the
- * superclasses of that node will also be invoked. For example, using an
- * instance of this class to visit a [Block] will cause the method [visitBlock]
- * to be invoked but will also cause the methods [visitStatement] and
- * [visitNode] to be subsequently invoked. This allows visitors to be written
- * that visit all statements without needing to override the visit method for
- * each of the specific subclasses of [Statement].
- *
- * Subclasses that override a visit method must either invoke the overridden
- * visit method or explicitly invoke the more general visit method. Failure to
- * do so will cause the visit methods for superclasses of the node to not be
- * invoked and will cause the children of the visited node to not be visited.
- */
-class GeneralizingAstVisitor<R> implements AstVisitor<R> {
-  @override
-  R visitAdjacentStrings(AdjacentStrings node) => visitStringLiteral(node);
-
-  R visitAnnotatedNode(AnnotatedNode node) => visitNode(node);
-
-  @override
-  R visitAnnotation(Annotation node) => visitNode(node);
-
-  @override
-  R visitArgumentList(ArgumentList node) => visitNode(node);
-
-  @override
-  R visitAsExpression(AsExpression node) => visitExpression(node);
-
-  @override
-  R visitAssertStatement(AssertStatement node) => visitStatement(node);
-
-  @override
-  R visitAssignmentExpression(AssignmentExpression node) =>
-      visitExpression(node);
-
-  @override
-  R visitAwaitExpression(AwaitExpression node) => visitExpression(node);
-
-  @override
-  R visitBinaryExpression(BinaryExpression node) => visitExpression(node);
-
-  @override
-  R visitBlock(Block node) => visitStatement(node);
-
-  @override
-  R visitBlockFunctionBody(BlockFunctionBody node) => visitFunctionBody(node);
-
-  @override
-  R visitBooleanLiteral(BooleanLiteral node) => visitLiteral(node);
-
-  @override
-  R visitBreakStatement(BreakStatement node) => visitStatement(node);
-
-  @override
-  R visitCascadeExpression(CascadeExpression node) => visitExpression(node);
-
-  @override
-  R visitCatchClause(CatchClause node) => visitNode(node);
-
-  @override
-  R visitClassDeclaration(ClassDeclaration node) =>
-      visitNamedCompilationUnitMember(node);
-
-  R visitClassMember(ClassMember node) => visitDeclaration(node);
-
-  @override
-  R visitClassTypeAlias(ClassTypeAlias node) => visitTypeAlias(node);
-
-  R visitCombinator(Combinator node) => visitNode(node);
-
-  @override
-  R visitComment(Comment node) => visitNode(node);
-
-  @override
-  R visitCommentReference(CommentReference node) => visitNode(node);
-
-  @override
-  R visitCompilationUnit(CompilationUnit node) => visitNode(node);
-
-  R visitCompilationUnitMember(CompilationUnitMember node) =>
-      visitDeclaration(node);
-
-  @override
-  R visitConditionalExpression(ConditionalExpression node) =>
-      visitExpression(node);
-
-  @override
-  R visitConfiguration(Configuration node) => visitNode(node);
-
-  @override
-  R visitConstructorDeclaration(ConstructorDeclaration node) =>
-      visitClassMember(node);
-
-  @override
-  R visitConstructorFieldInitializer(ConstructorFieldInitializer node) =>
-      visitConstructorInitializer(node);
-
-  R visitConstructorInitializer(ConstructorInitializer node) => visitNode(node);
-
-  @override
-  R visitConstructorName(ConstructorName node) => visitNode(node);
-
-  @override
-  R visitContinueStatement(ContinueStatement node) => visitStatement(node);
-
-  R visitDeclaration(Declaration node) => visitAnnotatedNode(node);
-
-  @override
-  R visitDeclaredIdentifier(DeclaredIdentifier node) => visitDeclaration(node);
-
-  @override
-  R visitDefaultFormalParameter(DefaultFormalParameter node) =>
-      visitFormalParameter(node);
-
-  R visitDirective(Directive node) => visitAnnotatedNode(node);
-
-  @override
-  R visitDoStatement(DoStatement node) => visitStatement(node);
-
-  @override
-  R visitDottedName(DottedName node) => visitNode(node);
-
-  @override
-  R visitDoubleLiteral(DoubleLiteral node) => visitLiteral(node);
-
-  @override
-  R visitEmptyFunctionBody(EmptyFunctionBody node) => visitFunctionBody(node);
-
-  @override
-  R visitEmptyStatement(EmptyStatement node) => visitStatement(node);
-
-  @override
-  R visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
-      visitDeclaration(node);
-
-  @override
-  R visitEnumDeclaration(EnumDeclaration node) =>
-      visitNamedCompilationUnitMember(node);
-
-  @override
-  R visitExportDirective(ExportDirective node) => visitNamespaceDirective(node);
-
-  R visitExpression(Expression node) => visitNode(node);
-
-  @override
-  R visitExpressionFunctionBody(ExpressionFunctionBody node) =>
-      visitFunctionBody(node);
-
-  @override
-  R visitExpressionStatement(ExpressionStatement node) => visitStatement(node);
-
-  @override
-  R visitExtendsClause(ExtendsClause node) => visitNode(node);
-
-  @override
-  R visitFieldDeclaration(FieldDeclaration node) => visitClassMember(node);
-
-  @override
-  R visitFieldFormalParameter(FieldFormalParameter node) =>
-      visitNormalFormalParameter(node);
-
-  @override
-  R visitForEachStatement(ForEachStatement node) => visitStatement(node);
-
-  R visitFormalParameter(FormalParameter node) => visitNode(node);
-
-  @override
-  R visitFormalParameterList(FormalParameterList node) => visitNode(node);
-
-  @override
-  R visitForStatement(ForStatement node) => visitStatement(node);
-
-  R visitFunctionBody(FunctionBody node) => visitNode(node);
-
-  @override
-  R visitFunctionDeclaration(FunctionDeclaration node) =>
-      visitNamedCompilationUnitMember(node);
-
-  @override
-  R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) =>
-      visitStatement(node);
-
-  @override
-  R visitFunctionExpression(FunctionExpression node) => visitExpression(node);
-
-  @override
-  R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) =>
-      visitExpression(node);
-
-  @override
-  R visitFunctionTypeAlias(FunctionTypeAlias node) => visitTypeAlias(node);
-
-  @override
-  R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) =>
-      visitNormalFormalParameter(node);
-
-  @override
-  R visitHideCombinator(HideCombinator node) => visitCombinator(node);
-
-  R visitIdentifier(Identifier node) => visitExpression(node);
-
-  @override
-  R visitIfStatement(IfStatement node) => visitStatement(node);
-
-  @override
-  R visitImplementsClause(ImplementsClause node) => visitNode(node);
-
-  @override
-  R visitImportDirective(ImportDirective node) => visitNamespaceDirective(node);
-
-  @override
-  R visitIndexExpression(IndexExpression node) => visitExpression(node);
-
-  @override
-  R visitInstanceCreationExpression(InstanceCreationExpression node) =>
-      visitExpression(node);
-
-  @override
-  R visitIntegerLiteral(IntegerLiteral node) => visitLiteral(node);
-
-  R visitInterpolationElement(InterpolationElement node) => visitNode(node);
-
-  @override
-  R visitInterpolationExpression(InterpolationExpression node) =>
-      visitInterpolationElement(node);
-
-  @override
-  R visitInterpolationString(InterpolationString node) =>
-      visitInterpolationElement(node);
-
-  @override
-  R visitIsExpression(IsExpression node) => visitExpression(node);
-
-  @override
-  R visitLabel(Label node) => visitNode(node);
-
-  @override
-  R visitLabeledStatement(LabeledStatement node) => visitStatement(node);
-
-  @override
-  R visitLibraryDirective(LibraryDirective node) => visitDirective(node);
-
-  @override
-  R visitLibraryIdentifier(LibraryIdentifier node) => visitIdentifier(node);
-
-  @override
-  R visitListLiteral(ListLiteral node) => visitTypedLiteral(node);
-
-  R visitLiteral(Literal node) => visitExpression(node);
-
-  @override
-  R visitMapLiteral(MapLiteral node) => visitTypedLiteral(node);
-
-  @override
-  R visitMapLiteralEntry(MapLiteralEntry node) => visitNode(node);
-
-  @override
-  R visitMethodDeclaration(MethodDeclaration node) => visitClassMember(node);
-
-  @override
-  R visitMethodInvocation(MethodInvocation node) => visitExpression(node);
-
-  R visitNamedCompilationUnitMember(NamedCompilationUnitMember node) =>
-      visitCompilationUnitMember(node);
-
-  @override
-  R visitNamedExpression(NamedExpression node) => visitExpression(node);
-
-  R visitNamespaceDirective(NamespaceDirective node) =>
-      visitUriBasedDirective(node);
-
-  @override
-  R visitNativeClause(NativeClause node) => visitNode(node);
-
-  @override
-  R visitNativeFunctionBody(NativeFunctionBody node) => visitFunctionBody(node);
-
-  R visitNode(AstNode node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  R visitNormalFormalParameter(NormalFormalParameter node) =>
-      visitFormalParameter(node);
-
-  @override
-  R visitNullLiteral(NullLiteral node) => visitLiteral(node);
-
-  @override
-  R visitParenthesizedExpression(ParenthesizedExpression node) =>
-      visitExpression(node);
-
-  @override
-  R visitPartDirective(PartDirective node) => visitUriBasedDirective(node);
-
-  @override
-  R visitPartOfDirective(PartOfDirective node) => visitDirective(node);
-
-  @override
-  R visitPostfixExpression(PostfixExpression node) => visitExpression(node);
-
-  @override
-  R visitPrefixedIdentifier(PrefixedIdentifier node) => visitIdentifier(node);
-
-  @override
-  R visitPrefixExpression(PrefixExpression node) => visitExpression(node);
-
-  @override
-  R visitPropertyAccess(PropertyAccess node) => visitExpression(node);
-
-  @override
-  R visitRedirectingConstructorInvocation(
-          RedirectingConstructorInvocation node) =>
-      visitConstructorInitializer(node);
-
-  @override
-  R visitRethrowExpression(RethrowExpression node) => visitExpression(node);
-
-  @override
-  R visitReturnStatement(ReturnStatement node) => visitStatement(node);
-
-  @override
-  R visitScriptTag(ScriptTag scriptTag) => visitNode(scriptTag);
-
-  @override
-  R visitShowCombinator(ShowCombinator node) => visitCombinator(node);
-
-  @override
-  R visitSimpleFormalParameter(SimpleFormalParameter node) =>
-      visitNormalFormalParameter(node);
-
-  @override
-  R visitSimpleIdentifier(SimpleIdentifier node) => visitIdentifier(node);
-
-  @override
-  R visitSimpleStringLiteral(SimpleStringLiteral node) =>
-      visitSingleStringLiteral(node);
-
-  R visitSingleStringLiteral(SingleStringLiteral node) =>
-      visitStringLiteral(node);
-
-  R visitStatement(Statement node) => visitNode(node);
-
-  @override
-  R visitStringInterpolation(StringInterpolation node) =>
-      visitSingleStringLiteral(node);
-
-  R visitStringLiteral(StringLiteral node) => visitLiteral(node);
-
-  @override
-  R visitSuperConstructorInvocation(SuperConstructorInvocation node) =>
-      visitConstructorInitializer(node);
-
-  @override
-  R visitSuperExpression(SuperExpression node) => visitExpression(node);
-
-  @override
-  R visitSwitchCase(SwitchCase node) => visitSwitchMember(node);
-
-  @override
-  R visitSwitchDefault(SwitchDefault node) => visitSwitchMember(node);
-
-  R visitSwitchMember(SwitchMember node) => visitNode(node);
-
-  @override
-  R visitSwitchStatement(SwitchStatement node) => visitStatement(node);
-
-  @override
-  R visitSymbolLiteral(SymbolLiteral node) => visitLiteral(node);
-
-  @override
-  R visitThisExpression(ThisExpression node) => visitExpression(node);
-
-  @override
-  R visitThrowExpression(ThrowExpression node) => visitExpression(node);
-
-  @override
-  R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) =>
-      visitCompilationUnitMember(node);
-
-  @override
-  R visitTryStatement(TryStatement node) => visitStatement(node);
-
-  R visitTypeAlias(TypeAlias node) => visitNamedCompilationUnitMember(node);
-
-  @override
-  R visitTypeArgumentList(TypeArgumentList node) => visitNode(node);
-
-  R visitTypedLiteral(TypedLiteral node) => visitLiteral(node);
-
-  @override
-  R visitTypeName(TypeName node) => visitNode(node);
-
-  @override
-  R visitTypeParameter(TypeParameter node) => visitNode(node);
-
-  @override
-  R visitTypeParameterList(TypeParameterList node) => visitNode(node);
-
-  R visitUriBasedDirective(UriBasedDirective node) => visitDirective(node);
-
-  @override
-  R visitVariableDeclaration(VariableDeclaration node) =>
-      visitDeclaration(node);
-
-  @override
-  R visitVariableDeclarationList(VariableDeclarationList node) =>
-      visitNode(node);
-
-  @override
-  R visitVariableDeclarationStatement(VariableDeclarationStatement node) =>
-      visitStatement(node);
-
-  @override
-  R visitWhileStatement(WhileStatement node) => visitStatement(node);
-
-  @override
-  R visitWithClause(WithClause node) => visitNode(node);
-
-  @override
-  R visitYieldStatement(YieldStatement node) => visitStatement(node);
-}
-
-class GeneralizingAstVisitor_BreadthFirstVisitor
-    extends GeneralizingAstVisitor<Object> {
-  final BreadthFirstVisitor BreadthFirstVisitor_this;
-
-  GeneralizingAstVisitor_BreadthFirstVisitor(this.BreadthFirstVisitor_this)
-      : super();
-
-  @override
-  Object visitNode(AstNode node) {
-    BreadthFirstVisitor_this._queue.add(node);
-    return null;
-  }
-}
-
-/**
  * A combinator that restricts the names being imported to those that are not in
  * a given list.
  *
@@ -9643,1065 +6669,6 @@
 }
 
 /**
- * An object that will clone any AST structure that it visits. The cloner will
- * clone the structure, replacing the specified ASTNode with a new ASTNode,
- * mapping the old token stream to a new token stream, and preserving resolution
- * results.
- */
-class IncrementalAstCloner implements AstVisitor<AstNode> {
-  /**
-   * The node to be replaced during the cloning process.
-   */
-  final AstNode _oldNode;
-
-  /**
-   * The replacement node used during the cloning process.
-   */
-  final AstNode _newNode;
-
-  /**
-   * A mapping of old tokens to new tokens used during the cloning process.
-   */
-  final TokenMap _tokenMap;
-
-  /**
-   * Construct a new instance that will replace the [oldNode] with the [newNode]
-   * in the process of cloning an existing AST structure. The [tokenMap] is a
-   * mapping of old tokens to new tokens.
-   */
-  IncrementalAstCloner(this._oldNode, this._newNode, this._tokenMap);
-
-  @override
-  AdjacentStrings visitAdjacentStrings(AdjacentStrings node) =>
-      new AdjacentStrings(_cloneNodeList(node.strings));
-
-  @override
-  Annotation visitAnnotation(Annotation node) {
-    Annotation copy = new Annotation(
-        _mapToken(node.atSign),
-        _cloneNode(node.name),
-        _mapToken(node.period),
-        _cloneNode(node.constructorName),
-        _cloneNode(node.arguments));
-    copy.element = node.element;
-    return copy;
-  }
-
-  @override
-  ArgumentList visitArgumentList(ArgumentList node) => new ArgumentList(
-      _mapToken(node.leftParenthesis),
-      _cloneNodeList(node.arguments),
-      _mapToken(node.rightParenthesis));
-
-  @override
-  AsExpression visitAsExpression(AsExpression node) {
-    AsExpression copy = new AsExpression(_cloneNode(node.expression),
-        _mapToken(node.asOperator), _cloneNode(node.type));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  AstNode visitAssertStatement(AssertStatement node) => new AssertStatement(
-      _mapToken(node.assertKeyword),
-      _mapToken(node.leftParenthesis),
-      _cloneNode(node.condition),
-      _mapToken(node.comma),
-      _cloneNode(node.message),
-      _mapToken(node.rightParenthesis),
-      _mapToken(node.semicolon));
-
-  @override
-  AssignmentExpression visitAssignmentExpression(AssignmentExpression node) {
-    AssignmentExpression copy = new AssignmentExpression(
-        _cloneNode(node.leftHandSide),
-        _mapToken(node.operator),
-        _cloneNode(node.rightHandSide));
-    copy.propagatedElement = node.propagatedElement;
-    copy.propagatedType = node.propagatedType;
-    copy.staticElement = node.staticElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  AwaitExpression visitAwaitExpression(AwaitExpression node) =>
-      new AwaitExpression(
-          _mapToken(node.awaitKeyword), _cloneNode(node.expression));
-
-  @override
-  BinaryExpression visitBinaryExpression(BinaryExpression node) {
-    BinaryExpression copy = new BinaryExpression(_cloneNode(node.leftOperand),
-        _mapToken(node.operator), _cloneNode(node.rightOperand));
-    copy.propagatedElement = node.propagatedElement;
-    copy.propagatedType = node.propagatedType;
-    copy.staticElement = node.staticElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  Block visitBlock(Block node) => new Block(_mapToken(node.leftBracket),
-      _cloneNodeList(node.statements), _mapToken(node.rightBracket));
-
-  @override
-  BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) =>
-      new BlockFunctionBody(_mapToken(node.keyword), _mapToken(node.star),
-          _cloneNode(node.block));
-
-  @override
-  BooleanLiteral visitBooleanLiteral(BooleanLiteral node) {
-    BooleanLiteral copy =
-        new BooleanLiteral(_mapToken(node.literal), node.value);
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  BreakStatement visitBreakStatement(BreakStatement node) => new BreakStatement(
-      _mapToken(node.breakKeyword),
-      _cloneNode(node.label),
-      _mapToken(node.semicolon));
-
-  @override
-  CascadeExpression visitCascadeExpression(CascadeExpression node) {
-    CascadeExpression copy = new CascadeExpression(
-        _cloneNode(node.target), _cloneNodeList(node.cascadeSections));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  CatchClause visitCatchClause(CatchClause node) => new CatchClause(
-      _mapToken(node.onKeyword),
-      _cloneNode(node.exceptionType),
-      _mapToken(node.catchKeyword),
-      _mapToken(node.leftParenthesis),
-      _cloneNode(node.exceptionParameter),
-      _mapToken(node.comma),
-      _cloneNode(node.stackTraceParameter),
-      _mapToken(node.rightParenthesis),
-      _cloneNode(node.body));
-
-  @override
-  ClassDeclaration visitClassDeclaration(ClassDeclaration node) {
-    ClassDeclaration copy = new ClassDeclaration(
-        _cloneNode(node.documentationComment),
-        _cloneNodeList(node.metadata),
-        _mapToken(node.abstractKeyword),
-        _mapToken(node.classKeyword),
-        _cloneNode(node.name),
-        _cloneNode(node.typeParameters),
-        _cloneNode(node.extendsClause),
-        _cloneNode(node.withClause),
-        _cloneNode(node.implementsClause),
-        _mapToken(node.leftBracket),
-        _cloneNodeList(node.members),
-        _mapToken(node.rightBracket));
-    copy.nativeClause = _cloneNode(node.nativeClause);
-    return copy;
-  }
-
-  @override
-  ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) => new ClassTypeAlias(
-      _cloneNode(node.documentationComment),
-      _cloneNodeList(node.metadata),
-      _mapToken(node.typedefKeyword),
-      _cloneNode(node.name),
-      _cloneNode(node.typeParameters),
-      _mapToken(node.equals),
-      _mapToken(node.abstractKeyword),
-      _cloneNode(node.superclass),
-      _cloneNode(node.withClause),
-      _cloneNode(node.implementsClause),
-      _mapToken(node.semicolon));
-
-  @override
-  Comment visitComment(Comment node) {
-    if (node.isDocumentation) {
-      return Comment.createDocumentationCommentWithReferences(
-          _mapTokens(node.tokens), _cloneNodeList(node.references));
-    } else if (node.isBlock) {
-      return Comment.createBlockComment(_mapTokens(node.tokens));
-    }
-    return Comment.createEndOfLineComment(_mapTokens(node.tokens));
-  }
-
-  @override
-  CommentReference visitCommentReference(CommentReference node) =>
-      new CommentReference(
-          _mapToken(node.newKeyword), _cloneNode(node.identifier));
-
-  @override
-  CompilationUnit visitCompilationUnit(CompilationUnit node) {
-    CompilationUnit copy = new CompilationUnit(
-        _mapToken(node.beginToken),
-        _cloneNode(node.scriptTag),
-        _cloneNodeList(node.directives),
-        _cloneNodeList(node.declarations),
-        _mapToken(node.endToken));
-    copy.lineInfo = node.lineInfo;
-    copy.element = node.element;
-    return copy;
-  }
-
-  @override
-  ConditionalExpression visitConditionalExpression(ConditionalExpression node) {
-    ConditionalExpression copy = new ConditionalExpression(
-        _cloneNode(node.condition),
-        _mapToken(node.question),
-        _cloneNode(node.thenExpression),
-        _mapToken(node.colon),
-        _cloneNode(node.elseExpression));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  Configuration visitConfiguration(Configuration node) => new Configuration(
-      _mapToken(node.ifKeyword),
-      _mapToken(node.leftParenthesis),
-      _cloneNode(node.name),
-      _mapToken(node.equalToken),
-      _cloneNode(node.value),
-      _mapToken(node.rightParenthesis),
-      _cloneNode(node.libraryUri));
-
-  @override
-  ConstructorDeclaration visitConstructorDeclaration(
-      ConstructorDeclaration node) {
-    ConstructorDeclaration copy = new ConstructorDeclaration(
-        _cloneNode(node.documentationComment),
-        _cloneNodeList(node.metadata),
-        _mapToken(node.externalKeyword),
-        _mapToken(node.constKeyword),
-        _mapToken(node.factoryKeyword),
-        _cloneNode(node.returnType),
-        _mapToken(node.period),
-        _cloneNode(node.name),
-        _cloneNode(node.parameters),
-        _mapToken(node.separator),
-        _cloneNodeList(node.initializers),
-        _cloneNode(node.redirectedConstructor),
-        _cloneNode(node.body));
-    copy.element = node.element;
-    return copy;
-  }
-
-  @override
-  ConstructorFieldInitializer visitConstructorFieldInitializer(
-          ConstructorFieldInitializer node) =>
-      new ConstructorFieldInitializer(
-          _mapToken(node.thisKeyword),
-          _mapToken(node.period),
-          _cloneNode(node.fieldName),
-          _mapToken(node.equals),
-          _cloneNode(node.expression));
-
-  @override
-  ConstructorName visitConstructorName(ConstructorName node) {
-    ConstructorName copy = new ConstructorName(
-        _cloneNode(node.type), _mapToken(node.period), _cloneNode(node.name));
-    copy.staticElement = node.staticElement;
-    return copy;
-  }
-
-  @override
-  ContinueStatement visitContinueStatement(ContinueStatement node) =>
-      new ContinueStatement(_mapToken(node.continueKeyword),
-          _cloneNode(node.label), _mapToken(node.semicolon));
-
-  @override
-  DeclaredIdentifier visitDeclaredIdentifier(DeclaredIdentifier node) =>
-      new DeclaredIdentifier(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.keyword),
-          _cloneNode(node.type),
-          _cloneNode(node.identifier));
-
-  @override
-  DefaultFormalParameter visitDefaultFormalParameter(
-          DefaultFormalParameter node) =>
-      new DefaultFormalParameter(_cloneNode(node.parameter), node.kind,
-          _mapToken(node.separator), _cloneNode(node.defaultValue));
-
-  @override
-  DoStatement visitDoStatement(DoStatement node) => new DoStatement(
-      _mapToken(node.doKeyword),
-      _cloneNode(node.body),
-      _mapToken(node.whileKeyword),
-      _mapToken(node.leftParenthesis),
-      _cloneNode(node.condition),
-      _mapToken(node.rightParenthesis),
-      _mapToken(node.semicolon));
-
-  @override
-  DottedName visitDottedName(DottedName node) =>
-      new DottedName(_cloneNodeList(node.components));
-
-  @override
-  DoubleLiteral visitDoubleLiteral(DoubleLiteral node) {
-    DoubleLiteral copy = new DoubleLiteral(_mapToken(node.literal), node.value);
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  EmptyFunctionBody visitEmptyFunctionBody(EmptyFunctionBody node) =>
-      new EmptyFunctionBody(_mapToken(node.semicolon));
-
-  @override
-  EmptyStatement visitEmptyStatement(EmptyStatement node) =>
-      new EmptyStatement(_mapToken(node.semicolon));
-
-  @override
-  AstNode visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
-      new EnumConstantDeclaration(_cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata), _cloneNode(node.name));
-
-  @override
-  AstNode visitEnumDeclaration(EnumDeclaration node) => new EnumDeclaration(
-      _cloneNode(node.documentationComment),
-      _cloneNodeList(node.metadata),
-      _mapToken(node.enumKeyword),
-      _cloneNode(node.name),
-      _mapToken(node.leftBracket),
-      _cloneNodeList(node.constants),
-      _mapToken(node.rightBracket));
-
-  @override
-  ExportDirective visitExportDirective(ExportDirective node) {
-    ExportDirective copy = new ExportDirective(
-        _cloneNode(node.documentationComment),
-        _cloneNodeList(node.metadata),
-        _mapToken(node.keyword),
-        _cloneNode(node.uri),
-        _cloneNodeList(node.configurations),
-        _cloneNodeList(node.combinators),
-        _mapToken(node.semicolon));
-    copy.element = node.element;
-    return copy;
-  }
-
-  @override
-  ExpressionFunctionBody visitExpressionFunctionBody(
-          ExpressionFunctionBody node) =>
-      new ExpressionFunctionBody(
-          _mapToken(node.keyword),
-          _mapToken(node.functionDefinition),
-          _cloneNode(node.expression),
-          _mapToken(node.semicolon));
-
-  @override
-  ExpressionStatement visitExpressionStatement(ExpressionStatement node) =>
-      new ExpressionStatement(
-          _cloneNode(node.expression), _mapToken(node.semicolon));
-
-  @override
-  ExtendsClause visitExtendsClause(ExtendsClause node) => new ExtendsClause(
-      _mapToken(node.extendsKeyword), _cloneNode(node.superclass));
-
-  @override
-  FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
-      new FieldDeclaration(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.staticKeyword),
-          _cloneNode(node.fields),
-          _mapToken(node.semicolon));
-
-  @override
-  FieldFormalParameter visitFieldFormalParameter(FieldFormalParameter node) =>
-      new FieldFormalParameter(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.keyword),
-          _cloneNode(node.type),
-          _mapToken(node.thisKeyword),
-          _mapToken(node.period),
-          _cloneNode(node.identifier),
-          _cloneNode(node.typeParameters),
-          _cloneNode(node.parameters));
-
-  @override
-  ForEachStatement visitForEachStatement(ForEachStatement node) {
-    DeclaredIdentifier loopVariable = node.loopVariable;
-    if (loopVariable == null) {
-      return new ForEachStatement.withReference(
-          _mapToken(node.awaitKeyword),
-          _mapToken(node.forKeyword),
-          _mapToken(node.leftParenthesis),
-          _cloneNode(node.identifier),
-          _mapToken(node.inKeyword),
-          _cloneNode(node.iterable),
-          _mapToken(node.rightParenthesis),
-          _cloneNode(node.body));
-    }
-    return new ForEachStatement.withDeclaration(
-        _mapToken(node.awaitKeyword),
-        _mapToken(node.forKeyword),
-        _mapToken(node.leftParenthesis),
-        _cloneNode(loopVariable),
-        _mapToken(node.inKeyword),
-        _cloneNode(node.iterable),
-        _mapToken(node.rightParenthesis),
-        _cloneNode(node.body));
-  }
-
-  @override
-  FormalParameterList visitFormalParameterList(FormalParameterList node) =>
-      new FormalParameterList(
-          _mapToken(node.leftParenthesis),
-          _cloneNodeList(node.parameters),
-          _mapToken(node.leftDelimiter),
-          _mapToken(node.rightDelimiter),
-          _mapToken(node.rightParenthesis));
-
-  @override
-  ForStatement visitForStatement(ForStatement node) => new ForStatement(
-      _mapToken(node.forKeyword),
-      _mapToken(node.leftParenthesis),
-      _cloneNode(node.variables),
-      _cloneNode(node.initialization),
-      _mapToken(node.leftSeparator),
-      _cloneNode(node.condition),
-      _mapToken(node.rightSeparator),
-      _cloneNodeList(node.updaters),
-      _mapToken(node.rightParenthesis),
-      _cloneNode(node.body));
-
-  @override
-  FunctionDeclaration visitFunctionDeclaration(FunctionDeclaration node) =>
-      new FunctionDeclaration(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.externalKeyword),
-          _cloneNode(node.returnType),
-          _mapToken(node.propertyKeyword),
-          _cloneNode(node.name),
-          _cloneNode(node.functionExpression));
-
-  @override
-  FunctionDeclarationStatement visitFunctionDeclarationStatement(
-          FunctionDeclarationStatement node) =>
-      new FunctionDeclarationStatement(_cloneNode(node.functionDeclaration));
-
-  @override
-  FunctionExpression visitFunctionExpression(FunctionExpression node) {
-    FunctionExpression copy = new FunctionExpression(
-        _cloneNode(node.typeParameters),
-        _cloneNode(node.parameters),
-        _cloneNode(node.body));
-    copy.element = node.element;
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  FunctionExpressionInvocation visitFunctionExpressionInvocation(
-      FunctionExpressionInvocation node) {
-    FunctionExpressionInvocation copy = new FunctionExpressionInvocation(
-        _cloneNode(node.function),
-        _cloneNode(node.typeArguments),
-        _cloneNode(node.argumentList));
-    copy.propagatedElement = node.propagatedElement;
-    copy.propagatedType = node.propagatedType;
-    copy.staticElement = node.staticElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  FunctionTypeAlias visitFunctionTypeAlias(FunctionTypeAlias node) =>
-      new FunctionTypeAlias(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.typedefKeyword),
-          _cloneNode(node.returnType),
-          _cloneNode(node.name),
-          _cloneNode(node.typeParameters),
-          _cloneNode(node.parameters),
-          _mapToken(node.semicolon));
-
-  @override
-  FunctionTypedFormalParameter visitFunctionTypedFormalParameter(
-          FunctionTypedFormalParameter node) =>
-      new FunctionTypedFormalParameter(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _cloneNode(node.returnType),
-          _cloneNode(node.identifier),
-          _cloneNode(node.typeParameters),
-          _cloneNode(node.parameters));
-
-  @override
-  HideCombinator visitHideCombinator(HideCombinator node) => new HideCombinator(
-      _mapToken(node.keyword), _cloneNodeList(node.hiddenNames));
-
-  @override
-  IfStatement visitIfStatement(IfStatement node) => new IfStatement(
-      _mapToken(node.ifKeyword),
-      _mapToken(node.leftParenthesis),
-      _cloneNode(node.condition),
-      _mapToken(node.rightParenthesis),
-      _cloneNode(node.thenStatement),
-      _mapToken(node.elseKeyword),
-      _cloneNode(node.elseStatement));
-
-  @override
-  ImplementsClause visitImplementsClause(ImplementsClause node) =>
-      new ImplementsClause(
-          _mapToken(node.implementsKeyword), _cloneNodeList(node.interfaces));
-
-  @override
-  ImportDirective visitImportDirective(ImportDirective node) =>
-      new ImportDirective(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.keyword),
-          _cloneNode(node.uri),
-          _cloneNodeList(node.configurations),
-          _mapToken(node.deferredKeyword),
-          _mapToken(node.asKeyword),
-          _cloneNode(node.prefix),
-          _cloneNodeList(node.combinators),
-          _mapToken(node.semicolon));
-
-  @override
-  IndexExpression visitIndexExpression(IndexExpression node) {
-    Token period = _mapToken(node.period);
-    IndexExpression copy;
-    if (period == null) {
-      copy = new IndexExpression.forTarget(
-          _cloneNode(node.target),
-          _mapToken(node.leftBracket),
-          _cloneNode(node.index),
-          _mapToken(node.rightBracket));
-    } else {
-      copy = new IndexExpression.forCascade(period, _mapToken(node.leftBracket),
-          _cloneNode(node.index), _mapToken(node.rightBracket));
-    }
-    copy.auxiliaryElements = node.auxiliaryElements;
-    copy.propagatedElement = node.propagatedElement;
-    copy.propagatedType = node.propagatedType;
-    copy.staticElement = node.staticElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  InstanceCreationExpression visitInstanceCreationExpression(
-      InstanceCreationExpression node) {
-    InstanceCreationExpression copy = new InstanceCreationExpression(
-        _mapToken(node.keyword),
-        _cloneNode(node.constructorName),
-        _cloneNode(node.argumentList));
-    copy.propagatedType = node.propagatedType;
-    copy.staticElement = node.staticElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  IntegerLiteral visitIntegerLiteral(IntegerLiteral node) {
-    IntegerLiteral copy =
-        new IntegerLiteral(_mapToken(node.literal), node.value);
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  InterpolationExpression visitInterpolationExpression(
-          InterpolationExpression node) =>
-      new InterpolationExpression(_mapToken(node.leftBracket),
-          _cloneNode(node.expression), _mapToken(node.rightBracket));
-
-  @override
-  InterpolationString visitInterpolationString(InterpolationString node) =>
-      new InterpolationString(_mapToken(node.contents), node.value);
-
-  @override
-  IsExpression visitIsExpression(IsExpression node) {
-    IsExpression copy = new IsExpression(
-        _cloneNode(node.expression),
-        _mapToken(node.isOperator),
-        _mapToken(node.notOperator),
-        _cloneNode(node.type));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  Label visitLabel(Label node) =>
-      new Label(_cloneNode(node.label), _mapToken(node.colon));
-
-  @override
-  LabeledStatement visitLabeledStatement(LabeledStatement node) =>
-      new LabeledStatement(
-          _cloneNodeList(node.labels), _cloneNode(node.statement));
-
-  @override
-  LibraryDirective visitLibraryDirective(LibraryDirective node) =>
-      new LibraryDirective(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.libraryKeyword),
-          _cloneNode(node.name),
-          _mapToken(node.semicolon));
-
-  @override
-  LibraryIdentifier visitLibraryIdentifier(LibraryIdentifier node) {
-    LibraryIdentifier copy =
-        new LibraryIdentifier(_cloneNodeList(node.components));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  ListLiteral visitListLiteral(ListLiteral node) {
-    ListLiteral copy = new ListLiteral(
-        _mapToken(node.constKeyword),
-        _cloneNode(node.typeArguments),
-        _mapToken(node.leftBracket),
-        _cloneNodeList(node.elements),
-        _mapToken(node.rightBracket));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  MapLiteral visitMapLiteral(MapLiteral node) {
-    MapLiteral copy = new MapLiteral(
-        _mapToken(node.constKeyword),
-        _cloneNode(node.typeArguments),
-        _mapToken(node.leftBracket),
-        _cloneNodeList(node.entries),
-        _mapToken(node.rightBracket));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  MapLiteralEntry visitMapLiteralEntry(MapLiteralEntry node) =>
-      new MapLiteralEntry(_cloneNode(node.key), _mapToken(node.separator),
-          _cloneNode(node.value));
-
-  @override
-  MethodDeclaration visitMethodDeclaration(MethodDeclaration node) =>
-      new MethodDeclaration(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.externalKeyword),
-          _mapToken(node.modifierKeyword),
-          _cloneNode(node.returnType),
-          _mapToken(node.propertyKeyword),
-          _mapToken(node.operatorKeyword),
-          _cloneNode(node.name),
-          _cloneNode(node._typeParameters),
-          _cloneNode(node.parameters),
-          _cloneNode(node.body));
-
-  @override
-  MethodInvocation visitMethodInvocation(MethodInvocation node) {
-    MethodInvocation copy = new MethodInvocation(
-        _cloneNode(node.target),
-        _mapToken(node.operator),
-        _cloneNode(node.methodName),
-        _cloneNode(node.typeArguments),
-        _cloneNode(node.argumentList));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  NamedExpression visitNamedExpression(NamedExpression node) {
-    NamedExpression copy =
-        new NamedExpression(_cloneNode(node.name), _cloneNode(node.expression));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  AstNode visitNativeClause(NativeClause node) =>
-      new NativeClause(_mapToken(node.nativeKeyword), _cloneNode(node.name));
-
-  @override
-  NativeFunctionBody visitNativeFunctionBody(NativeFunctionBody node) =>
-      new NativeFunctionBody(_mapToken(node.nativeKeyword),
-          _cloneNode(node.stringLiteral), _mapToken(node.semicolon));
-
-  @override
-  NullLiteral visitNullLiteral(NullLiteral node) {
-    NullLiteral copy = new NullLiteral(_mapToken(node.literal));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  ParenthesizedExpression visitParenthesizedExpression(
-      ParenthesizedExpression node) {
-    ParenthesizedExpression copy = new ParenthesizedExpression(
-        _mapToken(node.leftParenthesis),
-        _cloneNode(node.expression),
-        _mapToken(node.rightParenthesis));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  PartDirective visitPartDirective(PartDirective node) {
-    PartDirective copy = new PartDirective(
-        _cloneNode(node.documentationComment),
-        _cloneNodeList(node.metadata),
-        _mapToken(node.partKeyword),
-        _cloneNode(node.uri),
-        _mapToken(node.semicolon));
-    copy.element = node.element;
-    return copy;
-  }
-
-  @override
-  PartOfDirective visitPartOfDirective(PartOfDirective node) {
-    PartOfDirective copy = new PartOfDirective(
-        _cloneNode(node.documentationComment),
-        _cloneNodeList(node.metadata),
-        _mapToken(node.partKeyword),
-        _mapToken(node.ofKeyword),
-        _cloneNode(node.libraryName),
-        _mapToken(node.semicolon));
-    copy.element = node.element;
-    return copy;
-  }
-
-  @override
-  PostfixExpression visitPostfixExpression(PostfixExpression node) {
-    PostfixExpression copy = new PostfixExpression(
-        _cloneNode(node.operand), _mapToken(node.operator));
-    copy.propagatedElement = node.propagatedElement;
-    copy.propagatedType = node.propagatedType;
-    copy.staticElement = node.staticElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  PrefixedIdentifier visitPrefixedIdentifier(PrefixedIdentifier node) {
-    PrefixedIdentifier copy = new PrefixedIdentifier(_cloneNode(node.prefix),
-        _mapToken(node.period), _cloneNode(node.identifier));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  PrefixExpression visitPrefixExpression(PrefixExpression node) {
-    PrefixExpression copy = new PrefixExpression(
-        _mapToken(node.operator), _cloneNode(node.operand));
-    copy.propagatedElement = node.propagatedElement;
-    copy.propagatedType = node.propagatedType;
-    copy.staticElement = node.staticElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  PropertyAccess visitPropertyAccess(PropertyAccess node) {
-    PropertyAccess copy = new PropertyAccess(_cloneNode(node.target),
-        _mapToken(node.operator), _cloneNode(node.propertyName));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
-      RedirectingConstructorInvocation node) {
-    RedirectingConstructorInvocation copy =
-        new RedirectingConstructorInvocation(
-            _mapToken(node.thisKeyword),
-            _mapToken(node.period),
-            _cloneNode(node.constructorName),
-            _cloneNode(node.argumentList));
-    copy.staticElement = node.staticElement;
-    return copy;
-  }
-
-  @override
-  RethrowExpression visitRethrowExpression(RethrowExpression node) {
-    RethrowExpression copy =
-        new RethrowExpression(_mapToken(node.rethrowKeyword));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  ReturnStatement visitReturnStatement(ReturnStatement node) =>
-      new ReturnStatement(_mapToken(node.returnKeyword),
-          _cloneNode(node.expression), _mapToken(node.semicolon));
-
-  @override
-  ScriptTag visitScriptTag(ScriptTag node) =>
-      new ScriptTag(_mapToken(node.scriptTag));
-
-  @override
-  ShowCombinator visitShowCombinator(ShowCombinator node) => new ShowCombinator(
-      _mapToken(node.keyword), _cloneNodeList(node.shownNames));
-
-  @override
-  SimpleFormalParameter visitSimpleFormalParameter(
-          SimpleFormalParameter node) =>
-      new SimpleFormalParameter(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.keyword),
-          _cloneNode(node.type),
-          _cloneNode(node.identifier));
-
-  @override
-  SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
-    Token mappedToken = _mapToken(node.token);
-    if (mappedToken == null) {
-      // This only happens for SimpleIdentifiers created by the parser as part
-      // of scanning documentation comments (the tokens for those identifiers
-      // are not in the original token stream and hence do not get copied).
-      // This extra check can be removed if the scanner is changed to scan
-      // documentation comments for the parser.
-      mappedToken = node.token;
-    }
-    SimpleIdentifier copy = new SimpleIdentifier(mappedToken);
-    copy.auxiliaryElements = node.auxiliaryElements;
-    copy.propagatedElement = node.propagatedElement;
-    copy.propagatedType = node.propagatedType;
-    copy.staticElement = node.staticElement;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  SimpleStringLiteral visitSimpleStringLiteral(SimpleStringLiteral node) {
-    SimpleStringLiteral copy =
-        new SimpleStringLiteral(_mapToken(node.literal), node.value);
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  StringInterpolation visitStringInterpolation(StringInterpolation node) {
-    StringInterpolation copy =
-        new StringInterpolation(_cloneNodeList(node.elements));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  SuperConstructorInvocation visitSuperConstructorInvocation(
-      SuperConstructorInvocation node) {
-    SuperConstructorInvocation copy = new SuperConstructorInvocation(
-        _mapToken(node.superKeyword),
-        _mapToken(node.period),
-        _cloneNode(node.constructorName),
-        _cloneNode(node.argumentList));
-    copy.staticElement = node.staticElement;
-    return copy;
-  }
-
-  @override
-  SuperExpression visitSuperExpression(SuperExpression node) {
-    SuperExpression copy = new SuperExpression(_mapToken(node.superKeyword));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  SwitchCase visitSwitchCase(SwitchCase node) => new SwitchCase(
-      _cloneNodeList(node.labels),
-      _mapToken(node.keyword),
-      _cloneNode(node.expression),
-      _mapToken(node.colon),
-      _cloneNodeList(node.statements));
-
-  @override
-  SwitchDefault visitSwitchDefault(SwitchDefault node) => new SwitchDefault(
-      _cloneNodeList(node.labels),
-      _mapToken(node.keyword),
-      _mapToken(node.colon),
-      _cloneNodeList(node.statements));
-
-  @override
-  SwitchStatement visitSwitchStatement(SwitchStatement node) =>
-      new SwitchStatement(
-          _mapToken(node.switchKeyword),
-          _mapToken(node.leftParenthesis),
-          _cloneNode(node.expression),
-          _mapToken(node.rightParenthesis),
-          _mapToken(node.leftBracket),
-          _cloneNodeList(node.members),
-          _mapToken(node.rightBracket));
-
-  @override
-  AstNode visitSymbolLiteral(SymbolLiteral node) {
-    SymbolLiteral copy = new SymbolLiteral(
-        _mapToken(node.poundSign), _mapTokens(node.components));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  ThisExpression visitThisExpression(ThisExpression node) {
-    ThisExpression copy = new ThisExpression(_mapToken(node.thisKeyword));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  ThrowExpression visitThrowExpression(ThrowExpression node) {
-    ThrowExpression copy = new ThrowExpression(
-        _mapToken(node.throwKeyword), _cloneNode(node.expression));
-    copy.propagatedType = node.propagatedType;
-    copy.staticType = node.staticType;
-    return copy;
-  }
-
-  @override
-  TopLevelVariableDeclaration visitTopLevelVariableDeclaration(
-          TopLevelVariableDeclaration node) =>
-      new TopLevelVariableDeclaration(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _cloneNode(node.variables),
-          _mapToken(node.semicolon));
-
-  @override
-  TryStatement visitTryStatement(TryStatement node) => new TryStatement(
-      _mapToken(node.tryKeyword),
-      _cloneNode(node.body),
-      _cloneNodeList(node.catchClauses),
-      _mapToken(node.finallyKeyword),
-      _cloneNode(node.finallyBlock));
-
-  @override
-  TypeArgumentList visitTypeArgumentList(TypeArgumentList node) =>
-      new TypeArgumentList(_mapToken(node.leftBracket),
-          _cloneNodeList(node.arguments), _mapToken(node.rightBracket));
-
-  @override
-  TypeName visitTypeName(TypeName node) {
-    TypeName copy =
-        new TypeName(_cloneNode(node.name), _cloneNode(node.typeArguments));
-    copy.type = node.type;
-    return copy;
-  }
-
-  @override
-  TypeParameter visitTypeParameter(TypeParameter node) => new TypeParameter(
-      _cloneNode(node.documentationComment),
-      _cloneNodeList(node.metadata),
-      _cloneNode(node.name),
-      _mapToken(node.extendsKeyword),
-      _cloneNode(node.bound));
-
-  @override
-  TypeParameterList visitTypeParameterList(TypeParameterList node) =>
-      new TypeParameterList(_mapToken(node.leftBracket),
-          _cloneNodeList(node.typeParameters), _mapToken(node.rightBracket));
-
-  @override
-  VariableDeclaration visitVariableDeclaration(VariableDeclaration node) =>
-      new VariableDeclaration(_cloneNode(node.name), _mapToken(node.equals),
-          _cloneNode(node.initializer));
-
-  @override
-  VariableDeclarationList visitVariableDeclarationList(
-          VariableDeclarationList node) =>
-      new VariableDeclarationList(
-          null,
-          _cloneNodeList(node.metadata),
-          _mapToken(node.keyword),
-          _cloneNode(node.type),
-          _cloneNodeList(node.variables));
-
-  @override
-  VariableDeclarationStatement visitVariableDeclarationStatement(
-          VariableDeclarationStatement node) =>
-      new VariableDeclarationStatement(
-          _cloneNode(node.variables), _mapToken(node.semicolon));
-
-  @override
-  WhileStatement visitWhileStatement(WhileStatement node) => new WhileStatement(
-      _mapToken(node.whileKeyword),
-      _mapToken(node.leftParenthesis),
-      _cloneNode(node.condition),
-      _mapToken(node.rightParenthesis),
-      _cloneNode(node.body));
-
-  @override
-  WithClause visitWithClause(WithClause node) => new WithClause(
-      _mapToken(node.withKeyword), _cloneNodeList(node.mixinTypes));
-
-  @override
-  YieldStatement visitYieldStatement(YieldStatement node) => new YieldStatement(
-      _mapToken(node.yieldKeyword),
-      _mapToken(node.star),
-      _cloneNode(node.expression),
-      _mapToken(node.semicolon));
-
-  AstNode _cloneNode(AstNode node) {
-    if (node == null) {
-      return null;
-    }
-    if (identical(node, _oldNode)) {
-      return _newNode;
-    }
-    return node.accept(this) as AstNode;
-  }
-
-  List _cloneNodeList(NodeList nodes) {
-    List clonedNodes = new List();
-    for (AstNode node in nodes) {
-      clonedNodes.add(_cloneNode(node));
-    }
-    return clonedNodes;
-  }
-
-  Token _mapToken(Token oldToken) {
-    if (oldToken == null) {
-      return null;
-    }
-    return _tokenMap.get(oldToken);
-  }
-
-  List<Token> _mapTokens(List<Token> oldTokens) {
-    List<Token> newTokens = new List<Token>(oldTokens.length);
-    for (int index = 0; index < newTokens.length; index++) {
-      newTokens[index] = _mapToken(oldTokens[index]);
-    }
-    return newTokens;
-  }
-}
-
-/**
  * An index expression.
  *
  * > indexExpression ::=
@@ -11059,14 +7026,14 @@
  *
  * > integerLiteral ::=
  * >     decimalIntegerLiteral
- * >   | hexidecimalIntegerLiteral
+ * >   | hexadecimalIntegerLiteral
  * >
  * > decimalIntegerLiteral ::=
  * >     decimalDigit+
  * >
- * > hexidecimalIntegerLiteral ::=
- * >     '0x' hexidecimalDigit+
- * >   | '0X' hexidecimalDigit+
+ * > hexadecimalIntegerLiteral ::=
+ * >     '0x' hexadecimalDigit+
+ * >   | '0X' hexadecimalDigit+
  */
 class IntegerLiteral extends Literal {
   /**
@@ -12086,7 +8053,7 @@
  * [FunctionExpressionInvocation] nodes. Invocations of getters and setters are
  * represented by either [PrefixedIdentifier] or [PropertyAccess] nodes.
  *
- * > methodInvoction ::=
+ * > methodInvocation ::=
  * >     ([Expression] '.')? [SimpleIdentifier] [TypeArgumentList]? [ArgumentList]
  */
 class MethodInvocation extends Expression {
@@ -12694,1392 +8661,6 @@
 }
 
 /**
- * An object used to locate the [AstNode] associated with a source range, given
- * the AST structure built from the source. More specifically, they will return
- * the [AstNode] with the shortest length whose source range completely
- * encompasses the specified range.
- */
-class NodeLocator extends UnifyingAstVisitor<Object> {
-  /**
-   * The start offset of the range used to identify the node.
-   */
-  int _startOffset = 0;
-
-  /**
-   * The end offset of the range used to identify the node.
-   */
-  int _endOffset = 0;
-
-  /**
-   * The element that was found that corresponds to the given source range, or
-   * `null` if there is no such element.
-   */
-  AstNode _foundNode;
-
-  /**
-   * Initialize a newly created locator to locate an [AstNode] by locating the
-   * node within an AST structure that corresponds to the given range of
-   * characters (between the [startOffset] and [endOffset] in the source.
-   */
-  NodeLocator(int startOffset, [int endOffset])
-      : this._startOffset = startOffset,
-        this._endOffset = endOffset == null ? startOffset : endOffset;
-
-  /**
-   * Return the node that was found that corresponds to the given source range
-   * or `null` if there is no such node.
-   */
-  AstNode get foundNode => _foundNode;
-
-  /**
-   * Search within the given AST [node] for an identifier representing an
-   * element in the specified source range. Return the element that was found,
-   * or `null` if no element was found.
-   */
-  AstNode searchWithin(AstNode node) {
-    if (node == null) {
-      return null;
-    }
-    try {
-      node.accept(this);
-    } on NodeLocator_NodeFoundException {
-      // A node with the right source position was found.
-    } catch (exception, stackTrace) {
-      AnalysisEngine.instance.logger.logInformation(
-          "Unable to locate element at offset ($_startOffset - $_endOffset)",
-          new CaughtException(exception, stackTrace));
-      return null;
-    }
-    return _foundNode;
-  }
-
-  @override
-  Object visitNode(AstNode node) {
-    Token beginToken = node.beginToken;
-    Token endToken = node.endToken;
-    // Don't include synthetic tokens.
-    while (endToken != beginToken) {
-      if (endToken.type == TokenType.EOF || !endToken.isSynthetic) {
-        break;
-      }
-      endToken = endToken.previous;
-    }
-    int end = endToken.end;
-    int start = node.offset;
-    if (end < _startOffset) {
-      return null;
-    }
-    if (start > _endOffset) {
-      return null;
-    }
-    try {
-      node.visitChildren(this);
-    } on NodeLocator_NodeFoundException {
-      rethrow;
-    } catch (exception, stackTrace) {
-      // Ignore the exception and proceed in order to visit the rest of the
-      // structure.
-      AnalysisEngine.instance.logger.logInformation(
-          "Exception caught while traversing an AST structure.",
-          new CaughtException(exception, stackTrace));
-    }
-    if (start <= _startOffset && _endOffset <= end) {
-      _foundNode = node;
-      throw new NodeLocator_NodeFoundException();
-    }
-    return null;
-  }
-}
-
-/**
- * An object used to locate the [AstNode] associated with a source range.
- * More specifically, they will return the deepest [AstNode] which completely
- * encompasses the specified range.
- */
-class NodeLocator2 extends UnifyingAstVisitor<Object> {
-  /**
-   * The inclusive start offset of the range used to identify the node.
-   */
-  int _startOffset = 0;
-
-  /**
-   * The inclusive end offset of the range used to identify the node.
-   */
-  int _endOffset = 0;
-
-  /**
-   * The found node or `null` if there is no such node.
-   */
-  AstNode _foundNode;
-
-  /**
-   * Initialize a newly created locator to locate the deepest [AstNode] for
-   * which `node.offset <= [startOffset]` and `[endOffset] < node.end`.
-   *
-   * If [endOffset] is not provided, then it is considered the same as the
-   * given [startOffset].
-   */
-  NodeLocator2(int startOffset, [int endOffset])
-      : this._startOffset = startOffset,
-        this._endOffset = endOffset == null ? startOffset : endOffset;
-
-  /**
-   * Search within the given AST [node] and return the node that was found,
-   * or `null` if no node was found.
-   */
-  AstNode searchWithin(AstNode node) {
-    if (node == null) {
-      return null;
-    }
-    try {
-      node.accept(this);
-    } on NodeLocator_NodeFoundException {} catch (exception, stackTrace) {
-      AnalysisEngine.instance.logger.logInformation(
-          "Unable to locate element at offset ($_startOffset - $_endOffset)",
-          new CaughtException(exception, stackTrace));
-      return null;
-    }
-    return _foundNode;
-  }
-
-  @override
-  Object visitNode(AstNode node) {
-    Token beginToken = node.beginToken;
-    Token endToken = node.endToken;
-    // Don't include synthetic tokens.
-    while (endToken != beginToken) {
-      if (endToken.type == TokenType.EOF || !endToken.isSynthetic) {
-        break;
-      }
-      endToken = endToken.previous;
-    }
-    int end = endToken.end;
-    int start = node.offset;
-    if (end <= _startOffset) {
-      return null;
-    }
-    if (start > _endOffset) {
-      return null;
-    }
-    try {
-      node.visitChildren(this);
-    } on NodeLocator_NodeFoundException {
-      rethrow;
-    } catch (exception, stackTrace) {
-      // Ignore the exception and proceed in order to visit the rest of the
-      // structure.
-      AnalysisEngine.instance.logger.logInformation(
-          "Exception caught while traversing an AST structure.",
-          new CaughtException(exception, stackTrace));
-    }
-    if (start <= _startOffset && _endOffset < end) {
-      _foundNode = node;
-      throw new NodeLocator_NodeFoundException();
-    }
-    return null;
-  }
-}
-
-/**
- * An exception used by [NodeLocator] to cancel visiting after a node has been
- * found.
- */
-class NodeLocator_NodeFoundException extends RuntimeException {}
-
-/**
- * An object that will replace one child node in an AST node with another node.
- */
-class NodeReplacer implements AstVisitor<bool> {
-  /**
-   * The node being replaced.
-   */
-  final AstNode _oldNode;
-
-  /**
-   * The node that is replacing the old node.
-   */
-  final AstNode _newNode;
-
-  /**
-   * Initialize a newly created node locator to replace the [_oldNode] with the
-   * [_newNode].
-   */
-  NodeReplacer(this._oldNode, this._newNode);
-
-  @override
-  bool visitAdjacentStrings(AdjacentStrings node) {
-    if (_replaceInList(node.strings)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  bool visitAnnotatedNode(AnnotatedNode node) {
-    if (identical(node.documentationComment, _oldNode)) {
-      node.documentationComment = _newNode as Comment;
-      return true;
-    } else if (_replaceInList(node.metadata)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitAnnotation(Annotation node) {
-    if (identical(node.arguments, _oldNode)) {
-      node.arguments = _newNode as ArgumentList;
-      return true;
-    } else if (identical(node.constructorName, _oldNode)) {
-      node.constructorName = _newNode as SimpleIdentifier;
-      return true;
-    } else if (identical(node.name, _oldNode)) {
-      node.name = _newNode as Identifier;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitArgumentList(ArgumentList node) {
-    if (_replaceInList(node.arguments)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitAsExpression(AsExpression node) {
-    if (identical(node.expression, _oldNode)) {
-      node.expression = _newNode as Expression;
-      return true;
-    } else if (identical(node.type, _oldNode)) {
-      node.type = _newNode as TypeName;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitAssertStatement(AssertStatement node) {
-    if (identical(node.condition, _oldNode)) {
-      node.condition = _newNode as Expression;
-      return true;
-    }
-    if (identical(node._message, _oldNode)) {
-      node.message = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitAssignmentExpression(AssignmentExpression node) {
-    if (identical(node.leftHandSide, _oldNode)) {
-      node.leftHandSide = _newNode as Expression;
-      return true;
-    } else if (identical(node.rightHandSide, _oldNode)) {
-      node.rightHandSide = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitAwaitExpression(AwaitExpression node) {
-    if (identical(node.expression, _oldNode)) {
-      node.expression = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitBinaryExpression(BinaryExpression node) {
-    if (identical(node.leftOperand, _oldNode)) {
-      node.leftOperand = _newNode as Expression;
-      return true;
-    } else if (identical(node.rightOperand, _oldNode)) {
-      node.rightOperand = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitBlock(Block node) {
-    if (_replaceInList(node.statements)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitBlockFunctionBody(BlockFunctionBody node) {
-    if (identical(node.block, _oldNode)) {
-      node.block = _newNode as Block;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitBooleanLiteral(BooleanLiteral node) => visitNode(node);
-
-  @override
-  bool visitBreakStatement(BreakStatement node) {
-    if (identical(node.label, _oldNode)) {
-      node.label = _newNode as SimpleIdentifier;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitCascadeExpression(CascadeExpression node) {
-    if (identical(node.target, _oldNode)) {
-      node.target = _newNode as Expression;
-      return true;
-    } else if (_replaceInList(node.cascadeSections)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitCatchClause(CatchClause node) {
-    if (identical(node.exceptionType, _oldNode)) {
-      node.exceptionType = _newNode as TypeName;
-      return true;
-    } else if (identical(node.exceptionParameter, _oldNode)) {
-      node.exceptionParameter = _newNode as SimpleIdentifier;
-      return true;
-    } else if (identical(node.stackTraceParameter, _oldNode)) {
-      node.stackTraceParameter = _newNode as SimpleIdentifier;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitClassDeclaration(ClassDeclaration node) {
-    if (identical(node.name, _oldNode)) {
-      node.name = _newNode as SimpleIdentifier;
-      return true;
-    } else if (identical(node.typeParameters, _oldNode)) {
-      node.typeParameters = _newNode as TypeParameterList;
-      return true;
-    } else if (identical(node.extendsClause, _oldNode)) {
-      node.extendsClause = _newNode as ExtendsClause;
-      return true;
-    } else if (identical(node.withClause, _oldNode)) {
-      node.withClause = _newNode as WithClause;
-      return true;
-    } else if (identical(node.implementsClause, _oldNode)) {
-      node.implementsClause = _newNode as ImplementsClause;
-      return true;
-    } else if (identical(node.nativeClause, _oldNode)) {
-      node.nativeClause = _newNode as NativeClause;
-      return true;
-    } else if (_replaceInList(node.members)) {
-      return true;
-    }
-    return visitAnnotatedNode(node);
-  }
-
-  @override
-  bool visitClassTypeAlias(ClassTypeAlias node) {
-    if (identical(node.name, _oldNode)) {
-      node.name = _newNode as SimpleIdentifier;
-      return true;
-    } else if (identical(node.typeParameters, _oldNode)) {
-      node.typeParameters = _newNode as TypeParameterList;
-      return true;
-    } else if (identical(node.superclass, _oldNode)) {
-      node.superclass = _newNode as TypeName;
-      return true;
-    } else if (identical(node.withClause, _oldNode)) {
-      node.withClause = _newNode as WithClause;
-      return true;
-    } else if (identical(node.implementsClause, _oldNode)) {
-      node.implementsClause = _newNode as ImplementsClause;
-      return true;
-    }
-    return visitAnnotatedNode(node);
-  }
-
-  @override
-  bool visitComment(Comment node) {
-    if (_replaceInList(node.references)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitCommentReference(CommentReference node) {
-    if (identical(node.identifier, _oldNode)) {
-      node.identifier = _newNode as Identifier;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitCompilationUnit(CompilationUnit node) {
-    if (identical(node.scriptTag, _oldNode)) {
-      node.scriptTag = _newNode as ScriptTag;
-      return true;
-    } else if (_replaceInList(node.directives)) {
-      return true;
-    } else if (_replaceInList(node.declarations)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitConditionalExpression(ConditionalExpression node) {
-    if (identical(node.condition, _oldNode)) {
-      node.condition = _newNode as Expression;
-      return true;
-    } else if (identical(node.thenExpression, _oldNode)) {
-      node.thenExpression = _newNode as Expression;
-      return true;
-    } else if (identical(node.elseExpression, _oldNode)) {
-      node.elseExpression = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitConfiguration(Configuration node) {
-    if (identical(node.name, _oldNode)) {
-      node.name = _newNode as DottedName;
-      return true;
-    } else if (identical(node.value, _oldNode)) {
-      node.value = _newNode as StringLiteral;
-      return true;
-    } else if (identical(node.libraryUri, _oldNode)) {
-      node.libraryUri = _newNode as StringLiteral;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitConstructorDeclaration(ConstructorDeclaration node) {
-    if (identical(node.returnType, _oldNode)) {
-      node.returnType = _newNode as Identifier;
-      return true;
-    } else if (identical(node.name, _oldNode)) {
-      node.name = _newNode as SimpleIdentifier;
-      return true;
-    } else if (identical(node.parameters, _oldNode)) {
-      node.parameters = _newNode as FormalParameterList;
-      return true;
-    } else if (identical(node.redirectedConstructor, _oldNode)) {
-      node.redirectedConstructor = _newNode as ConstructorName;
-      return true;
-    } else if (identical(node.body, _oldNode)) {
-      node.body = _newNode as FunctionBody;
-      return true;
-    } else if (_replaceInList(node.initializers)) {
-      return true;
-    }
-    return visitAnnotatedNode(node);
-  }
-
-  @override
-  bool visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
-    if (identical(node.fieldName, _oldNode)) {
-      node.fieldName = _newNode as SimpleIdentifier;
-      return true;
-    } else if (identical(node.expression, _oldNode)) {
-      node.expression = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitConstructorName(ConstructorName node) {
-    if (identical(node.type, _oldNode)) {
-      node.type = _newNode as TypeName;
-      return true;
-    } else if (identical(node.name, _oldNode)) {
-      node.name = _newNode as SimpleIdentifier;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitContinueStatement(ContinueStatement node) {
-    if (identical(node.label, _oldNode)) {
-      node.label = _newNode as SimpleIdentifier;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitDeclaredIdentifier(DeclaredIdentifier node) {
-    if (identical(node.type, _oldNode)) {
-      node.type = _newNode as TypeName;
-      return true;
-    } else if (identical(node.identifier, _oldNode)) {
-      node.identifier = _newNode as SimpleIdentifier;
-      return true;
-    }
-    return visitAnnotatedNode(node);
-  }
-
-  @override
-  bool visitDefaultFormalParameter(DefaultFormalParameter node) {
-    if (identical(node.parameter, _oldNode)) {
-      node.parameter = _newNode as NormalFormalParameter;
-      return true;
-    } else if (identical(node.defaultValue, _oldNode)) {
-      node.defaultValue = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitDoStatement(DoStatement node) {
-    if (identical(node.body, _oldNode)) {
-      node.body = _newNode as Statement;
-      return true;
-    } else if (identical(node.condition, _oldNode)) {
-      node.condition = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitDottedName(DottedName node) {
-    if (_replaceInList(node.components)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitDoubleLiteral(DoubleLiteral node) => visitNode(node);
-
-  @override
-  bool visitEmptyFunctionBody(EmptyFunctionBody node) => visitNode(node);
-
-  @override
-  bool visitEmptyStatement(EmptyStatement node) => visitNode(node);
-
-  @override
-  bool visitEnumConstantDeclaration(EnumConstantDeclaration node) {
-    if (identical(node.name, _oldNode)) {
-      node.name = _newNode as SimpleIdentifier;
-      return true;
-    }
-    return visitAnnotatedNode(node);
-  }
-
-  @override
-  bool visitEnumDeclaration(EnumDeclaration node) {
-    if (identical(node.name, _oldNode)) {
-      node.name = _newNode as SimpleIdentifier;
-      return true;
-    } else if (_replaceInList(node.constants)) {
-      return true;
-    }
-    return visitAnnotatedNode(node);
-  }
-
-  @override
-  bool visitExportDirective(ExportDirective node) =>
-      visitNamespaceDirective(node);
-
-  @override
-  bool visitExpressionFunctionBody(ExpressionFunctionBody node) {
-    if (identical(node.expression, _oldNode)) {
-      node.expression = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitExpressionStatement(ExpressionStatement node) {
-    if (identical(node.expression, _oldNode)) {
-      node.expression = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitExtendsClause(ExtendsClause node) {
-    if (identical(node.superclass, _oldNode)) {
-      node.superclass = _newNode as TypeName;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitFieldDeclaration(FieldDeclaration node) {
-    if (identical(node.fields, _oldNode)) {
-      node.fields = _newNode as VariableDeclarationList;
-      return true;
-    }
-    return visitAnnotatedNode(node);
-  }
-
-  @override
-  bool visitFieldFormalParameter(FieldFormalParameter node) {
-    if (identical(node.type, _oldNode)) {
-      node.type = _newNode as TypeName;
-      return true;
-    } else if (identical(node.parameters, _oldNode)) {
-      node.parameters = _newNode as FormalParameterList;
-      return true;
-    }
-    return visitNormalFormalParameter(node);
-  }
-
-  @override
-  bool visitForEachStatement(ForEachStatement node) {
-    if (identical(node.loopVariable, _oldNode)) {
-      node.loopVariable = _newNode as DeclaredIdentifier;
-      return true;
-    } else if (identical(node.identifier, _oldNode)) {
-      node.identifier = _newNode as SimpleIdentifier;
-      return true;
-    } else if (identical(node.iterable, _oldNode)) {
-      node.iterable = _newNode as Expression;
-      return true;
-    } else if (identical(node.body, _oldNode)) {
-      node.body = _newNode as Statement;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitFormalParameterList(FormalParameterList node) {
-    if (_replaceInList(node.parameters)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitForStatement(ForStatement node) {
-    if (identical(node.variables, _oldNode)) {
-      node.variables = _newNode as VariableDeclarationList;
-      return true;
-    } else if (identical(node.initialization, _oldNode)) {
-      node.initialization = _newNode as Expression;
-      return true;
-    } else if (identical(node.condition, _oldNode)) {
-      node.condition = _newNode as Expression;
-      return true;
-    } else if (identical(node.body, _oldNode)) {
-      node.body = _newNode as Statement;
-      return true;
-    } else if (_replaceInList(node.updaters)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitFunctionDeclaration(FunctionDeclaration node) {
-    if (identical(node.returnType, _oldNode)) {
-      node.returnType = _newNode as TypeName;
-      return true;
-    } else if (identical(node.name, _oldNode)) {
-      node.name = _newNode as SimpleIdentifier;
-      return true;
-    } else if (identical(node.functionExpression, _oldNode)) {
-      node.functionExpression = _newNode as FunctionExpression;
-      return true;
-    }
-    return visitAnnotatedNode(node);
-  }
-
-  @override
-  bool visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
-    if (identical(node.functionDeclaration, _oldNode)) {
-      node.functionDeclaration = _newNode as FunctionDeclaration;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitFunctionExpression(FunctionExpression node) {
-    if (identical(node.parameters, _oldNode)) {
-      node.parameters = _newNode as FormalParameterList;
-      return true;
-    } else if (identical(node.body, _oldNode)) {
-      node.body = _newNode as FunctionBody;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
-    if (identical(node.function, _oldNode)) {
-      node.function = _newNode as Expression;
-      return true;
-    } else if (identical(node.argumentList, _oldNode)) {
-      node.argumentList = _newNode as ArgumentList;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitFunctionTypeAlias(FunctionTypeAlias node) {
-    if (identical(node.returnType, _oldNode)) {
-      node.returnType = _newNode as TypeName;
-      return true;
-    } else if (identical(node.name, _oldNode)) {
-      node.name = _newNode as SimpleIdentifier;
-      return true;
-    } else if (identical(node.typeParameters, _oldNode)) {
-      node.typeParameters = _newNode as TypeParameterList;
-      return true;
-    } else if (identical(node.parameters, _oldNode)) {
-      node.parameters = _newNode as FormalParameterList;
-      return true;
-    }
-    return visitAnnotatedNode(node);
-  }
-
-  @override
-  bool visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
-    if (identical(node.returnType, _oldNode)) {
-      node.returnType = _newNode as TypeName;
-      return true;
-    } else if (identical(node.parameters, _oldNode)) {
-      node.parameters = _newNode as FormalParameterList;
-      return true;
-    }
-    return visitNormalFormalParameter(node);
-  }
-
-  @override
-  bool visitHideCombinator(HideCombinator node) {
-    if (_replaceInList(node.hiddenNames)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitIfStatement(IfStatement node) {
-    if (identical(node.condition, _oldNode)) {
-      node.condition = _newNode as Expression;
-      return true;
-    } else if (identical(node.thenStatement, _oldNode)) {
-      node.thenStatement = _newNode as Statement;
-      return true;
-    } else if (identical(node.elseStatement, _oldNode)) {
-      node.elseStatement = _newNode as Statement;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitImplementsClause(ImplementsClause node) {
-    if (_replaceInList(node.interfaces)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitImportDirective(ImportDirective node) {
-    if (identical(node.prefix, _oldNode)) {
-      node.prefix = _newNode as SimpleIdentifier;
-      return true;
-    }
-    return visitNamespaceDirective(node);
-  }
-
-  @override
-  bool visitIndexExpression(IndexExpression node) {
-    if (identical(node.target, _oldNode)) {
-      node.target = _newNode as Expression;
-      return true;
-    } else if (identical(node.index, _oldNode)) {
-      node.index = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitInstanceCreationExpression(InstanceCreationExpression node) {
-    if (identical(node.constructorName, _oldNode)) {
-      node.constructorName = _newNode as ConstructorName;
-      return true;
-    } else if (identical(node.argumentList, _oldNode)) {
-      node.argumentList = _newNode as ArgumentList;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitIntegerLiteral(IntegerLiteral node) => visitNode(node);
-
-  @override
-  bool visitInterpolationExpression(InterpolationExpression node) {
-    if (identical(node.expression, _oldNode)) {
-      node.expression = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitInterpolationString(InterpolationString node) => visitNode(node);
-
-  @override
-  bool visitIsExpression(IsExpression node) {
-    if (identical(node.expression, _oldNode)) {
-      node.expression = _newNode as Expression;
-      return true;
-    } else if (identical(node.type, _oldNode)) {
-      node.type = _newNode as TypeName;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitLabel(Label node) {
-    if (identical(node.label, _oldNode)) {
-      node.label = _newNode as SimpleIdentifier;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitLabeledStatement(LabeledStatement node) {
-    if (identical(node.statement, _oldNode)) {
-      node.statement = _newNode as Statement;
-      return true;
-    } else if (_replaceInList(node.labels)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitLibraryDirective(LibraryDirective node) {
-    if (identical(node.name, _oldNode)) {
-      node.name = _newNode as LibraryIdentifier;
-      return true;
-    }
-    return visitAnnotatedNode(node);
-  }
-
-  @override
-  bool visitLibraryIdentifier(LibraryIdentifier node) {
-    if (_replaceInList(node.components)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitListLiteral(ListLiteral node) {
-    if (_replaceInList(node.elements)) {
-      return true;
-    }
-    return visitTypedLiteral(node);
-  }
-
-  @override
-  bool visitMapLiteral(MapLiteral node) {
-    if (_replaceInList(node.entries)) {
-      return true;
-    }
-    return visitTypedLiteral(node);
-  }
-
-  @override
-  bool visitMapLiteralEntry(MapLiteralEntry node) {
-    if (identical(node.key, _oldNode)) {
-      node.key = _newNode as Expression;
-      return true;
-    } else if (identical(node.value, _oldNode)) {
-      node.value = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitMethodDeclaration(MethodDeclaration node) {
-    if (identical(node.returnType, _oldNode)) {
-      node.returnType = _newNode as TypeName;
-      return true;
-    } else if (identical(node.name, _oldNode)) {
-      node.name = _newNode as SimpleIdentifier;
-      return true;
-    } else if (identical(node.parameters, _oldNode)) {
-      node.parameters = _newNode as FormalParameterList;
-      return true;
-    } else if (identical(node.body, _oldNode)) {
-      node.body = _newNode as FunctionBody;
-      return true;
-    }
-    return visitAnnotatedNode(node);
-  }
-
-  @override
-  bool visitMethodInvocation(MethodInvocation node) {
-    if (identical(node.target, _oldNode)) {
-      node.target = _newNode as Expression;
-      return true;
-    } else if (identical(node.methodName, _oldNode)) {
-      node.methodName = _newNode as SimpleIdentifier;
-      return true;
-    } else if (identical(node.argumentList, _oldNode)) {
-      node.argumentList = _newNode as ArgumentList;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitNamedExpression(NamedExpression node) {
-    if (identical(node.name, _oldNode)) {
-      node.name = _newNode as Label;
-      return true;
-    } else if (identical(node.expression, _oldNode)) {
-      node.expression = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  bool visitNamespaceDirective(NamespaceDirective node) {
-    if (_replaceInList(node.combinators)) {
-      return true;
-    }
-    return visitUriBasedDirective(node);
-  }
-
-  @override
-  bool visitNativeClause(NativeClause node) {
-    if (identical(node.name, _oldNode)) {
-      node.name = _newNode as StringLiteral;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitNativeFunctionBody(NativeFunctionBody node) {
-    if (identical(node.stringLiteral, _oldNode)) {
-      node.stringLiteral = _newNode as StringLiteral;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  bool visitNode(AstNode node) {
-    throw new IllegalArgumentException(
-        "The old node is not a child of it's parent");
-  }
-
-  bool visitNormalFormalParameter(NormalFormalParameter node) {
-    if (identical(node.documentationComment, _oldNode)) {
-      node.documentationComment = _newNode as Comment;
-      return true;
-    } else if (identical(node.identifier, _oldNode)) {
-      node.identifier = _newNode as SimpleIdentifier;
-      return true;
-    } else if (_replaceInList(node.metadata)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitNullLiteral(NullLiteral node) => visitNode(node);
-
-  @override
-  bool visitParenthesizedExpression(ParenthesizedExpression node) {
-    if (identical(node.expression, _oldNode)) {
-      node.expression = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitPartDirective(PartDirective node) => visitUriBasedDirective(node);
-
-  @override
-  bool visitPartOfDirective(PartOfDirective node) {
-    if (identical(node.libraryName, _oldNode)) {
-      node.libraryName = _newNode as LibraryIdentifier;
-      return true;
-    }
-    return visitAnnotatedNode(node);
-  }
-
-  @override
-  bool visitPostfixExpression(PostfixExpression node) {
-    if (identical(node.operand, _oldNode)) {
-      node.operand = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitPrefixedIdentifier(PrefixedIdentifier node) {
-    if (identical(node.prefix, _oldNode)) {
-      node.prefix = _newNode as SimpleIdentifier;
-      return true;
-    } else if (identical(node.identifier, _oldNode)) {
-      node.identifier = _newNode as SimpleIdentifier;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitPrefixExpression(PrefixExpression node) {
-    if (identical(node.operand, _oldNode)) {
-      node.operand = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitPropertyAccess(PropertyAccess node) {
-    if (identical(node.target, _oldNode)) {
-      node.target = _newNode as Expression;
-      return true;
-    } else if (identical(node.propertyName, _oldNode)) {
-      node.propertyName = _newNode as SimpleIdentifier;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitRedirectingConstructorInvocation(
-      RedirectingConstructorInvocation node) {
-    if (identical(node.constructorName, _oldNode)) {
-      node.constructorName = _newNode as SimpleIdentifier;
-      return true;
-    } else if (identical(node.argumentList, _oldNode)) {
-      node.argumentList = _newNode as ArgumentList;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitRethrowExpression(RethrowExpression node) => visitNode(node);
-
-  @override
-  bool visitReturnStatement(ReturnStatement node) {
-    if (identical(node.expression, _oldNode)) {
-      node.expression = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitScriptTag(ScriptTag scriptTag) => visitNode(scriptTag);
-
-  @override
-  bool visitShowCombinator(ShowCombinator node) {
-    if (_replaceInList(node.shownNames)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitSimpleFormalParameter(SimpleFormalParameter node) {
-    if (identical(node.type, _oldNode)) {
-      node.type = _newNode as TypeName;
-      return true;
-    }
-    return visitNormalFormalParameter(node);
-  }
-
-  @override
-  bool visitSimpleIdentifier(SimpleIdentifier node) => visitNode(node);
-
-  @override
-  bool visitSimpleStringLiteral(SimpleStringLiteral node) => visitNode(node);
-
-  @override
-  bool visitStringInterpolation(StringInterpolation node) {
-    if (_replaceInList(node.elements)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitSuperConstructorInvocation(SuperConstructorInvocation node) {
-    if (identical(node.constructorName, _oldNode)) {
-      node.constructorName = _newNode as SimpleIdentifier;
-      return true;
-    } else if (identical(node.argumentList, _oldNode)) {
-      node.argumentList = _newNode as ArgumentList;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitSuperExpression(SuperExpression node) => visitNode(node);
-
-  @override
-  bool visitSwitchCase(SwitchCase node) {
-    if (identical(node.expression, _oldNode)) {
-      node.expression = _newNode as Expression;
-      return true;
-    }
-    return visitSwitchMember(node);
-  }
-
-  @override
-  bool visitSwitchDefault(SwitchDefault node) => visitSwitchMember(node);
-
-  bool visitSwitchMember(SwitchMember node) {
-    if (_replaceInList(node.labels)) {
-      return true;
-    } else if (_replaceInList(node.statements)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitSwitchStatement(SwitchStatement node) {
-    if (identical(node.expression, _oldNode)) {
-      node.expression = _newNode as Expression;
-      return true;
-    } else if (_replaceInList(node.members)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitSymbolLiteral(SymbolLiteral node) => visitNode(node);
-
-  @override
-  bool visitThisExpression(ThisExpression node) => visitNode(node);
-
-  @override
-  bool visitThrowExpression(ThrowExpression node) {
-    if (identical(node.expression, _oldNode)) {
-      node.expression = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    if (identical(node.variables, _oldNode)) {
-      node.variables = _newNode as VariableDeclarationList;
-      return true;
-    }
-    return visitAnnotatedNode(node);
-  }
-
-  @override
-  bool visitTryStatement(TryStatement node) {
-    if (identical(node.body, _oldNode)) {
-      node.body = _newNode as Block;
-      return true;
-    } else if (identical(node.finallyBlock, _oldNode)) {
-      node.finallyBlock = _newNode as Block;
-      return true;
-    } else if (_replaceInList(node.catchClauses)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitTypeArgumentList(TypeArgumentList node) {
-    if (_replaceInList(node.arguments)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  bool visitTypedLiteral(TypedLiteral node) {
-    if (identical(node.typeArguments, _oldNode)) {
-      node.typeArguments = _newNode as TypeArgumentList;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitTypeName(TypeName node) {
-    if (identical(node.name, _oldNode)) {
-      node.name = _newNode as Identifier;
-      return true;
-    } else if (identical(node.typeArguments, _oldNode)) {
-      node.typeArguments = _newNode as TypeArgumentList;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitTypeParameter(TypeParameter node) {
-    if (identical(node.name, _oldNode)) {
-      node.name = _newNode as SimpleIdentifier;
-      return true;
-    } else if (identical(node.bound, _oldNode)) {
-      node.bound = _newNode as TypeName;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitTypeParameterList(TypeParameterList node) {
-    if (_replaceInList(node.typeParameters)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  bool visitUriBasedDirective(UriBasedDirective node) {
-    if (identical(node.uri, _oldNode)) {
-      node.uri = _newNode as StringLiteral;
-      return true;
-    }
-    return visitAnnotatedNode(node);
-  }
-
-  @override
-  bool visitVariableDeclaration(VariableDeclaration node) {
-    if (identical(node.name, _oldNode)) {
-      node.name = _newNode as SimpleIdentifier;
-      return true;
-    } else if (identical(node.initializer, _oldNode)) {
-      node.initializer = _newNode as Expression;
-      return true;
-    }
-    return visitAnnotatedNode(node);
-  }
-
-  @override
-  bool visitVariableDeclarationList(VariableDeclarationList node) {
-    if (identical(node.type, _oldNode)) {
-      node.type = _newNode as TypeName;
-      return true;
-    } else if (_replaceInList(node.variables)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitVariableDeclarationStatement(VariableDeclarationStatement node) {
-    if (identical(node.variables, _oldNode)) {
-      node.variables = _newNode as VariableDeclarationList;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitWhileStatement(WhileStatement node) {
-    if (identical(node.condition, _oldNode)) {
-      node.condition = _newNode as Expression;
-      return true;
-    } else if (identical(node.body, _oldNode)) {
-      node.body = _newNode as Statement;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitWithClause(WithClause node) {
-    if (_replaceInList(node.mixinTypes)) {
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitYieldStatement(YieldStatement node) {
-    if (identical(node.expression, _oldNode)) {
-      node.expression = _newNode as Expression;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  bool _replaceInList(NodeList list) {
-    int count = list.length;
-    for (int i = 0; i < count; i++) {
-      if (identical(_oldNode, list[i])) {
-        list[i] = _newNode;
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Replace the [oldNode] with the [newNode] in the AST structure containing
-   * the old node. Return `true` if the replacement was successful.
-   *
-   * Throws an [IllegalArgumentException] if either node is `null`, if the old
-   * node does not have a parent node, or if the AST structure has been
-   * corrupted.
-   */
-  static bool replace(AstNode oldNode, AstNode newNode) {
-    if (oldNode == null || newNode == null) {
-      throw new IllegalArgumentException(
-          "The old and new nodes must be non-null");
-    } else if (identical(oldNode, newNode)) {
-      return true;
-    }
-    AstNode parent = oldNode.parent;
-    if (parent == null) {
-      throw new IllegalArgumentException(
-          "The old node is not a child of another node");
-    }
-    NodeReplacer replacer = new NodeReplacer(oldNode, newNode);
-    return parent.accept(replacer);
-  }
-}
-
-/**
  * A formal parameter that is required (is not optional).
  *
  * > normalFormalParameter ::=
@@ -14934,667 +9515,6 @@
 }
 
 /**
- * An AST visitor that will recursively visit all of the nodes in an AST
- * structure. For example, using an instance of this class to visit a [Block]
- * will also cause all of the statements in the block to be visited.
- *
- * Subclasses that override a visit method must either invoke the overridden
- * visit method or must explicitly ask the visited node to visit its children.
- * Failure to do so will cause the children of the visited node to not be
- * visited.
- */
-class RecursiveAstVisitor<R> implements AstVisitor<R> {
-  @override
-  R visitAdjacentStrings(AdjacentStrings node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitAnnotation(Annotation node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitArgumentList(ArgumentList node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitAsExpression(AsExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitAssertStatement(AssertStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitAssignmentExpression(AssignmentExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitAwaitExpression(AwaitExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitBinaryExpression(BinaryExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitBlock(Block node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitBlockFunctionBody(BlockFunctionBody node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitBooleanLiteral(BooleanLiteral node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitBreakStatement(BreakStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitCascadeExpression(CascadeExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitCatchClause(CatchClause node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitClassDeclaration(ClassDeclaration node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitClassTypeAlias(ClassTypeAlias node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitComment(Comment node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitCommentReference(CommentReference node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitCompilationUnit(CompilationUnit node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitConditionalExpression(ConditionalExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitConfiguration(Configuration node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitConstructorDeclaration(ConstructorDeclaration node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitConstructorName(ConstructorName node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitContinueStatement(ContinueStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitDeclaredIdentifier(DeclaredIdentifier node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitDefaultFormalParameter(DefaultFormalParameter node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitDoStatement(DoStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitDottedName(DottedName node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitDoubleLiteral(DoubleLiteral node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitEmptyFunctionBody(EmptyFunctionBody node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitEmptyStatement(EmptyStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitEnumConstantDeclaration(EnumConstantDeclaration node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitEnumDeclaration(EnumDeclaration node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitExportDirective(ExportDirective node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitExpressionFunctionBody(ExpressionFunctionBody node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitExpressionStatement(ExpressionStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitExtendsClause(ExtendsClause node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitFieldDeclaration(FieldDeclaration node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitFieldFormalParameter(FieldFormalParameter node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitForEachStatement(ForEachStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitFormalParameterList(FormalParameterList node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitForStatement(ForStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitFunctionDeclaration(FunctionDeclaration node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitFunctionExpression(FunctionExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitFunctionTypeAlias(FunctionTypeAlias node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitHideCombinator(HideCombinator node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitIfStatement(IfStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitImplementsClause(ImplementsClause node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitImportDirective(ImportDirective node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitIndexExpression(IndexExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitInstanceCreationExpression(InstanceCreationExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitIntegerLiteral(IntegerLiteral node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitInterpolationExpression(InterpolationExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitInterpolationString(InterpolationString node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitIsExpression(IsExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitLabel(Label node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitLabeledStatement(LabeledStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitLibraryDirective(LibraryDirective node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitLibraryIdentifier(LibraryIdentifier node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitListLiteral(ListLiteral node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitMapLiteral(MapLiteral node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitMapLiteralEntry(MapLiteralEntry node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitMethodDeclaration(MethodDeclaration node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitMethodInvocation(MethodInvocation node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitNamedExpression(NamedExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitNativeClause(NativeClause node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitNativeFunctionBody(NativeFunctionBody node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitNullLiteral(NullLiteral node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitParenthesizedExpression(ParenthesizedExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitPartDirective(PartDirective node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitPartOfDirective(PartOfDirective node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitPostfixExpression(PostfixExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitPrefixedIdentifier(PrefixedIdentifier node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitPrefixExpression(PrefixExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitPropertyAccess(PropertyAccess node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitRedirectingConstructorInvocation(
-      RedirectingConstructorInvocation node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitRethrowExpression(RethrowExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitReturnStatement(ReturnStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitScriptTag(ScriptTag node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitShowCombinator(ShowCombinator node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitSimpleFormalParameter(SimpleFormalParameter node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitSimpleIdentifier(SimpleIdentifier node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitSimpleStringLiteral(SimpleStringLiteral node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitStringInterpolation(StringInterpolation node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitSuperConstructorInvocation(SuperConstructorInvocation node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitSuperExpression(SuperExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitSwitchCase(SwitchCase node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitSwitchDefault(SwitchDefault node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitSwitchStatement(SwitchStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitSymbolLiteral(SymbolLiteral node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitThisExpression(ThisExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitThrowExpression(ThrowExpression node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitTryStatement(TryStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitTypeArgumentList(TypeArgumentList node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitTypeName(TypeName node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitTypeParameter(TypeParameter node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitTypeParameterList(TypeParameterList node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitVariableDeclaration(VariableDeclaration node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitVariableDeclarationList(VariableDeclarationList node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitVariableDeclarationStatement(VariableDeclarationStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitWhileStatement(WhileStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitWithClause(WithClause node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitYieldStatement(YieldStatement node) {
-    node.visitChildren(this);
-    return null;
-  }
-}
-
-/**
  * The invocation of a constructor in the same class from within a constructor's
  * initialization list.
  *
@@ -15795,191 +9715,6 @@
 }
 
 /**
- * Traverse the AST from initial child node to successive parents, building a
- * collection of local variable and parameter names visible to the initial child
- * node. In case of name shadowing, the first name seen is the most specific one
- * so names are not redefined.
- *
- * Completion test code coverage is 95%. The two basic blocks that are not
- * executed cannot be executed. They are included for future reference.
- */
-class ScopedNameFinder extends GeneralizingAstVisitor<Object> {
-  Declaration _declarationNode;
-
-  AstNode _immediateChild;
-
-  Map<String, SimpleIdentifier> _locals =
-      new HashMap<String, SimpleIdentifier>();
-
-  final int _position;
-
-  bool _referenceIsWithinLocalFunction = false;
-
-  ScopedNameFinder(this._position);
-
-  Declaration get declaration => _declarationNode;
-
-  Map<String, SimpleIdentifier> get locals => _locals;
-
-  @override
-  Object visitBlock(Block node) {
-    _checkStatements(node.statements);
-    return super.visitBlock(node);
-  }
-
-  @override
-  Object visitCatchClause(CatchClause node) {
-    _addToScope(node.exceptionParameter);
-    _addToScope(node.stackTraceParameter);
-    return super.visitCatchClause(node);
-  }
-
-  @override
-  Object visitConstructorDeclaration(ConstructorDeclaration node) {
-    if (!identical(_immediateChild, node.parameters)) {
-      _addParameters(node.parameters.parameters);
-    }
-    _declarationNode = node;
-    return null;
-  }
-
-  @override
-  Object visitFieldDeclaration(FieldDeclaration node) {
-    _declarationNode = node;
-    return null;
-  }
-
-  @override
-  Object visitForEachStatement(ForEachStatement node) {
-    DeclaredIdentifier loopVariable = node.loopVariable;
-    if (loopVariable != null) {
-      _addToScope(loopVariable.identifier);
-    }
-    return super.visitForEachStatement(node);
-  }
-
-  @override
-  Object visitForStatement(ForStatement node) {
-    if (!identical(_immediateChild, node.variables) && node.variables != null) {
-      _addVariables(node.variables.variables);
-    }
-    return super.visitForStatement(node);
-  }
-
-  @override
-  Object visitFunctionDeclaration(FunctionDeclaration node) {
-    if (node.parent is! FunctionDeclarationStatement) {
-      _declarationNode = node;
-      return null;
-    }
-    return super.visitFunctionDeclaration(node);
-  }
-
-  @override
-  Object visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
-    _referenceIsWithinLocalFunction = true;
-    return super.visitFunctionDeclarationStatement(node);
-  }
-
-  @override
-  Object visitFunctionExpression(FunctionExpression node) {
-    if (node.parameters != null &&
-        !identical(_immediateChild, node.parameters)) {
-      _addParameters(node.parameters.parameters);
-    }
-    return super.visitFunctionExpression(node);
-  }
-
-  @override
-  Object visitMethodDeclaration(MethodDeclaration node) {
-    _declarationNode = node;
-    if (node.parameters == null) {
-      return null;
-    }
-    if (!identical(_immediateChild, node.parameters)) {
-      _addParameters(node.parameters.parameters);
-    }
-    return null;
-  }
-
-  @override
-  Object visitNode(AstNode node) {
-    _immediateChild = node;
-    AstNode parent = node.parent;
-    if (parent != null) {
-      parent.accept(this);
-    }
-    return null;
-  }
-
-  @override
-  Object visitSwitchMember(SwitchMember node) {
-    _checkStatements(node.statements);
-    return super.visitSwitchMember(node);
-  }
-
-  @override
-  Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    _declarationNode = node;
-    return null;
-  }
-
-  @override
-  Object visitTypeAlias(TypeAlias node) {
-    _declarationNode = node;
-    return null;
-  }
-
-  void _addParameters(NodeList<FormalParameter> vars) {
-    for (FormalParameter var2 in vars) {
-      _addToScope(var2.identifier);
-    }
-  }
-
-  void _addToScope(SimpleIdentifier identifier) {
-    if (identifier != null && _isInRange(identifier)) {
-      String name = identifier.name;
-      if (!_locals.containsKey(name)) {
-        _locals[name] = identifier;
-      }
-    }
-  }
-
-  void _addVariables(NodeList<VariableDeclaration> variables) {
-    for (VariableDeclaration variable in variables) {
-      _addToScope(variable.name);
-    }
-  }
-
-  /**
-   * Check the given list of [statements] for any that come before the immediate
-   * child and that define a name that would be visible to the immediate child.
-   */
-  void _checkStatements(List<Statement> statements) {
-    for (Statement statement in statements) {
-      if (identical(statement, _immediateChild)) {
-        return;
-      }
-      if (statement is VariableDeclarationStatement) {
-        _addVariables(statement.variables.variables);
-      } else if (statement is FunctionDeclarationStatement &&
-          !_referenceIsWithinLocalFunction) {
-        _addToScope(statement.functionDeclaration.name);
-      }
-    }
-  }
-
-  bool _isInRange(AstNode node) {
-    if (_position < 0) {
-      // if source position is not set then all nodes are in range
-      return true;
-      // not reached
-    }
-    return node.end < _position;
-  }
-}
-
-/**
  * A script tag that can optionally occur at the beginning of a compilation unit.
  *
  * > scriptTag ::=
@@ -16059,344 +9794,6 @@
 }
 
 /**
- * An AST visitor that will do nothing when visiting an AST node. It is intended
- * to be a superclass for classes that use the visitor pattern primarily as a
- * dispatch mechanism (and hence don't need to recursively visit a whole
- * structure) and that only need to visit a small number of node types.
- */
-class SimpleAstVisitor<R> implements AstVisitor<R> {
-  @override
-  R visitAdjacentStrings(AdjacentStrings node) => null;
-
-  @override
-  R visitAnnotation(Annotation node) => null;
-
-  @override
-  R visitArgumentList(ArgumentList node) => null;
-
-  @override
-  R visitAsExpression(AsExpression node) => null;
-
-  @override
-  R visitAssertStatement(AssertStatement node) => null;
-
-  @override
-  R visitAssignmentExpression(AssignmentExpression node) => null;
-
-  @override
-  R visitAwaitExpression(AwaitExpression node) => null;
-
-  @override
-  R visitBinaryExpression(BinaryExpression node) => null;
-
-  @override
-  R visitBlock(Block node) => null;
-
-  @override
-  R visitBlockFunctionBody(BlockFunctionBody node) => null;
-
-  @override
-  R visitBooleanLiteral(BooleanLiteral node) => null;
-
-  @override
-  R visitBreakStatement(BreakStatement node) => null;
-
-  @override
-  R visitCascadeExpression(CascadeExpression node) => null;
-
-  @override
-  R visitCatchClause(CatchClause node) => null;
-
-  @override
-  R visitClassDeclaration(ClassDeclaration node) => null;
-
-  @override
-  R visitClassTypeAlias(ClassTypeAlias node) => null;
-
-  @override
-  R visitComment(Comment node) => null;
-
-  @override
-  R visitCommentReference(CommentReference node) => null;
-
-  @override
-  R visitCompilationUnit(CompilationUnit node) => null;
-
-  @override
-  R visitConditionalExpression(ConditionalExpression node) => null;
-
-  @override
-  R visitConfiguration(Configuration node) => null;
-
-  @override
-  R visitConstructorDeclaration(ConstructorDeclaration node) => null;
-
-  @override
-  R visitConstructorFieldInitializer(ConstructorFieldInitializer node) => null;
-
-  @override
-  R visitConstructorName(ConstructorName node) => null;
-
-  @override
-  R visitContinueStatement(ContinueStatement node) => null;
-
-  @override
-  R visitDeclaredIdentifier(DeclaredIdentifier node) => null;
-
-  @override
-  R visitDefaultFormalParameter(DefaultFormalParameter node) => null;
-
-  @override
-  R visitDoStatement(DoStatement node) => null;
-
-  @override
-  R visitDottedName(DottedName node) => null;
-
-  @override
-  R visitDoubleLiteral(DoubleLiteral node) => null;
-
-  @override
-  R visitEmptyFunctionBody(EmptyFunctionBody node) => null;
-
-  @override
-  R visitEmptyStatement(EmptyStatement node) => null;
-
-  @override
-  R visitEnumConstantDeclaration(EnumConstantDeclaration node) => null;
-
-  @override
-  R visitEnumDeclaration(EnumDeclaration node) => null;
-
-  @override
-  R visitExportDirective(ExportDirective node) => null;
-
-  @override
-  R visitExpressionFunctionBody(ExpressionFunctionBody node) => null;
-
-  @override
-  R visitExpressionStatement(ExpressionStatement node) => null;
-
-  @override
-  R visitExtendsClause(ExtendsClause node) => null;
-
-  @override
-  R visitFieldDeclaration(FieldDeclaration node) => null;
-
-  @override
-  R visitFieldFormalParameter(FieldFormalParameter node) => null;
-
-  @override
-  R visitForEachStatement(ForEachStatement node) => null;
-
-  @override
-  R visitFormalParameterList(FormalParameterList node) => null;
-
-  @override
-  R visitForStatement(ForStatement node) => null;
-
-  @override
-  R visitFunctionDeclaration(FunctionDeclaration node) => null;
-
-  @override
-  R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) =>
-      null;
-
-  @override
-  R visitFunctionExpression(FunctionExpression node) => null;
-
-  @override
-  R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) =>
-      null;
-
-  @override
-  R visitFunctionTypeAlias(FunctionTypeAlias node) => null;
-
-  @override
-  R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) =>
-      null;
-
-  @override
-  R visitHideCombinator(HideCombinator node) => null;
-
-  @override
-  R visitIfStatement(IfStatement node) => null;
-
-  @override
-  R visitImplementsClause(ImplementsClause node) => null;
-
-  @override
-  R visitImportDirective(ImportDirective node) => null;
-
-  @override
-  R visitIndexExpression(IndexExpression node) => null;
-
-  @override
-  R visitInstanceCreationExpression(InstanceCreationExpression node) => null;
-
-  @override
-  R visitIntegerLiteral(IntegerLiteral node) => null;
-
-  @override
-  R visitInterpolationExpression(InterpolationExpression node) => null;
-
-  @override
-  R visitInterpolationString(InterpolationString node) => null;
-
-  @override
-  R visitIsExpression(IsExpression node) => null;
-
-  @override
-  R visitLabel(Label node) => null;
-
-  @override
-  R visitLabeledStatement(LabeledStatement node) => null;
-
-  @override
-  R visitLibraryDirective(LibraryDirective node) => null;
-
-  @override
-  R visitLibraryIdentifier(LibraryIdentifier node) => null;
-
-  @override
-  R visitListLiteral(ListLiteral node) => null;
-
-  @override
-  R visitMapLiteral(MapLiteral node) => null;
-
-  @override
-  R visitMapLiteralEntry(MapLiteralEntry node) => null;
-
-  @override
-  R visitMethodDeclaration(MethodDeclaration node) => null;
-
-  @override
-  R visitMethodInvocation(MethodInvocation node) => null;
-
-  @override
-  R visitNamedExpression(NamedExpression node) => null;
-
-  @override
-  R visitNativeClause(NativeClause node) => null;
-
-  @override
-  R visitNativeFunctionBody(NativeFunctionBody node) => null;
-
-  @override
-  R visitNullLiteral(NullLiteral node) => null;
-
-  @override
-  R visitParenthesizedExpression(ParenthesizedExpression node) => null;
-
-  @override
-  R visitPartDirective(PartDirective node) => null;
-
-  @override
-  R visitPartOfDirective(PartOfDirective node) => null;
-
-  @override
-  R visitPostfixExpression(PostfixExpression node) => null;
-
-  @override
-  R visitPrefixedIdentifier(PrefixedIdentifier node) => null;
-
-  @override
-  R visitPrefixExpression(PrefixExpression node) => null;
-
-  @override
-  R visitPropertyAccess(PropertyAccess node) => null;
-
-  @override
-  R visitRedirectingConstructorInvocation(
-          RedirectingConstructorInvocation node) =>
-      null;
-
-  @override
-  R visitRethrowExpression(RethrowExpression node) => null;
-
-  @override
-  R visitReturnStatement(ReturnStatement node) => null;
-
-  @override
-  R visitScriptTag(ScriptTag node) => null;
-
-  @override
-  R visitShowCombinator(ShowCombinator node) => null;
-
-  @override
-  R visitSimpleFormalParameter(SimpleFormalParameter node) => null;
-
-  @override
-  R visitSimpleIdentifier(SimpleIdentifier node) => null;
-
-  @override
-  R visitSimpleStringLiteral(SimpleStringLiteral node) => null;
-
-  @override
-  R visitStringInterpolation(StringInterpolation node) => null;
-
-  @override
-  R visitSuperConstructorInvocation(SuperConstructorInvocation node) => null;
-
-  @override
-  R visitSuperExpression(SuperExpression node) => null;
-
-  @override
-  R visitSwitchCase(SwitchCase node) => null;
-
-  @override
-  R visitSwitchDefault(SwitchDefault node) => null;
-
-  @override
-  R visitSwitchStatement(SwitchStatement node) => null;
-
-  @override
-  R visitSymbolLiteral(SymbolLiteral node) => null;
-
-  @override
-  R visitThisExpression(ThisExpression node) => null;
-
-  @override
-  R visitThrowExpression(ThrowExpression node) => null;
-
-  @override
-  R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) => null;
-
-  @override
-  R visitTryStatement(TryStatement node) => null;
-
-  @override
-  R visitTypeArgumentList(TypeArgumentList node) => null;
-
-  @override
-  R visitTypeName(TypeName node) => null;
-
-  @override
-  R visitTypeParameter(TypeParameter node) => null;
-
-  @override
-  R visitTypeParameterList(TypeParameterList node) => null;
-
-  @override
-  R visitVariableDeclaration(VariableDeclaration node) => null;
-
-  @override
-  R visitVariableDeclarationList(VariableDeclarationList node) => null;
-
-  @override
-  R visitVariableDeclarationStatement(VariableDeclarationStatement node) =>
-      null;
-
-  @override
-  R visitWhileStatement(WhileStatement node) => null;
-
-  @override
-  R visitWithClause(WithClause node) => null;
-
-  @override
-  R visitYieldStatement(YieldStatement node) => null;
-}
-
-/**
  * A simple formal parameter.
  *
  * > simpleFormalParameter ::=
@@ -16920,8 +10317,8 @@
   bool get isRaw;
 
   /**
-   * Return `true` if this string literal uses single qoutes (' or ''').
-   * Return `false` if this string literal uses double qoutes (" or """).
+   * Return `true` if this string literal uses single quotes (' or ''').
+   * Return `false` if this string literal uses double quotes (" or """).
    */
   bool get isSingleQuoted;
 }
@@ -17757,1149 +11154,6 @@
 }
 
 /**
- * A visitor used to write a source representation of a visited AST node (and
- * all of it's children) to a writer.
- */
-class ToSourceVisitor implements AstVisitor<Object> {
-  /**
-   * The writer to which the source is to be written.
-   */
-  final PrintWriter _writer;
-
-  /**
-   * Initialize a newly created visitor to write source code representing the
-   * visited nodes to the given [writer].
-   */
-  ToSourceVisitor(this._writer);
-
-  @override
-  Object visitAdjacentStrings(AdjacentStrings node) {
-    _visitNodeListWithSeparator(node.strings, " ");
-    return null;
-  }
-
-  @override
-  Object visitAnnotation(Annotation node) {
-    _writer.print('@');
-    _visitNode(node.name);
-    _visitNodeWithPrefix(".", node.constructorName);
-    _visitNode(node.arguments);
-    return null;
-  }
-
-  @override
-  Object visitArgumentList(ArgumentList node) {
-    _writer.print('(');
-    _visitNodeListWithSeparator(node.arguments, ", ");
-    _writer.print(')');
-    return null;
-  }
-
-  @override
-  Object visitAsExpression(AsExpression node) {
-    _visitNode(node.expression);
-    _writer.print(" as ");
-    _visitNode(node.type);
-    return null;
-  }
-
-  @override
-  Object visitAssertStatement(AssertStatement node) {
-    _writer.print("assert (");
-    _visitNode(node.condition);
-    if (node.message != null) {
-      _writer.print(', ');
-      _visitNode(node.message);
-    }
-    _writer.print(");");
-    return null;
-  }
-
-  @override
-  Object visitAssignmentExpression(AssignmentExpression node) {
-    _visitNode(node.leftHandSide);
-    _writer.print(' ');
-    _writer.print(node.operator.lexeme);
-    _writer.print(' ');
-    _visitNode(node.rightHandSide);
-    return null;
-  }
-
-  @override
-  Object visitAwaitExpression(AwaitExpression node) {
-    _writer.print("await ");
-    _visitNode(node.expression);
-    return null;
-  }
-
-  @override
-  Object visitBinaryExpression(BinaryExpression node) {
-    _visitNode(node.leftOperand);
-    _writer.print(' ');
-    _writer.print(node.operator.lexeme);
-    _writer.print(' ');
-    _visitNode(node.rightOperand);
-    return null;
-  }
-
-  @override
-  Object visitBlock(Block node) {
-    _writer.print('{');
-    _visitNodeListWithSeparator(node.statements, " ");
-    _writer.print('}');
-    return null;
-  }
-
-  @override
-  Object visitBlockFunctionBody(BlockFunctionBody node) {
-    Token keyword = node.keyword;
-    if (keyword != null) {
-      _writer.print(keyword.lexeme);
-      if (node.star != null) {
-        _writer.print('*');
-      }
-      _writer.print(' ');
-    }
-    _visitNode(node.block);
-    return null;
-  }
-
-  @override
-  Object visitBooleanLiteral(BooleanLiteral node) {
-    _writer.print(node.literal.lexeme);
-    return null;
-  }
-
-  @override
-  Object visitBreakStatement(BreakStatement node) {
-    _writer.print("break");
-    _visitNodeWithPrefix(" ", node.label);
-    _writer.print(";");
-    return null;
-  }
-
-  @override
-  Object visitCascadeExpression(CascadeExpression node) {
-    _visitNode(node.target);
-    _visitNodeList(node.cascadeSections);
-    return null;
-  }
-
-  @override
-  Object visitCatchClause(CatchClause node) {
-    _visitNodeWithPrefix("on ", node.exceptionType);
-    if (node.catchKeyword != null) {
-      if (node.exceptionType != null) {
-        _writer.print(' ');
-      }
-      _writer.print("catch (");
-      _visitNode(node.exceptionParameter);
-      _visitNodeWithPrefix(", ", node.stackTraceParameter);
-      _writer.print(") ");
-    } else {
-      _writer.print(" ");
-    }
-    _visitNode(node.body);
-    return null;
-  }
-
-  @override
-  Object visitClassDeclaration(ClassDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitTokenWithSuffix(node.abstractKeyword, " ");
-    _writer.print("class ");
-    _visitNode(node.name);
-    _visitNode(node.typeParameters);
-    _visitNodeWithPrefix(" ", node.extendsClause);
-    _visitNodeWithPrefix(" ", node.withClause);
-    _visitNodeWithPrefix(" ", node.implementsClause);
-    _writer.print(" {");
-    _visitNodeListWithSeparator(node.members, " ");
-    _writer.print("}");
-    return null;
-  }
-
-  @override
-  Object visitClassTypeAlias(ClassTypeAlias node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    if (node.abstractKeyword != null) {
-      _writer.print("abstract ");
-    }
-    _writer.print("class ");
-    _visitNode(node.name);
-    _visitNode(node.typeParameters);
-    _writer.print(" = ");
-    _visitNode(node.superclass);
-    _visitNodeWithPrefix(" ", node.withClause);
-    _visitNodeWithPrefix(" ", node.implementsClause);
-    _writer.print(";");
-    return null;
-  }
-
-  @override
-  Object visitComment(Comment node) => null;
-
-  @override
-  Object visitCommentReference(CommentReference node) => null;
-
-  @override
-  Object visitCompilationUnit(CompilationUnit node) {
-    ScriptTag scriptTag = node.scriptTag;
-    NodeList<Directive> directives = node.directives;
-    _visitNode(scriptTag);
-    String prefix = scriptTag == null ? "" : " ";
-    _visitNodeListWithSeparatorAndPrefix(prefix, directives, " ");
-    prefix = scriptTag == null && directives.isEmpty ? "" : " ";
-    _visitNodeListWithSeparatorAndPrefix(prefix, node.declarations, " ");
-    return null;
-  }
-
-  @override
-  Object visitConditionalExpression(ConditionalExpression node) {
-    _visitNode(node.condition);
-    _writer.print(" ? ");
-    _visitNode(node.thenExpression);
-    _writer.print(" : ");
-    _visitNode(node.elseExpression);
-    return null;
-  }
-
-  @override
-  Object visitConfiguration(Configuration node) {
-    _writer.print('if (');
-    _visitNode(node.name);
-    _visitNodeWithPrefix(" == ", node.value);
-    _writer.print(') ');
-    _visitNode(node.libraryUri);
-    return null;
-  }
-
-  @override
-  Object visitConstructorDeclaration(ConstructorDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitTokenWithSuffix(node.externalKeyword, " ");
-    _visitTokenWithSuffix(node.constKeyword, " ");
-    _visitTokenWithSuffix(node.factoryKeyword, " ");
-    _visitNode(node.returnType);
-    _visitNodeWithPrefix(".", node.name);
-    _visitNode(node.parameters);
-    _visitNodeListWithSeparatorAndPrefix(" : ", node.initializers, ", ");
-    _visitNodeWithPrefix(" = ", node.redirectedConstructor);
-    _visitFunctionWithPrefix(" ", node.body);
-    return null;
-  }
-
-  @override
-  Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
-    _visitTokenWithSuffix(node.thisKeyword, ".");
-    _visitNode(node.fieldName);
-    _writer.print(" = ");
-    _visitNode(node.expression);
-    return null;
-  }
-
-  @override
-  Object visitConstructorName(ConstructorName node) {
-    _visitNode(node.type);
-    _visitNodeWithPrefix(".", node.name);
-    return null;
-  }
-
-  @override
-  Object visitContinueStatement(ContinueStatement node) {
-    _writer.print("continue");
-    _visitNodeWithPrefix(" ", node.label);
-    _writer.print(";");
-    return null;
-  }
-
-  @override
-  Object visitDeclaredIdentifier(DeclaredIdentifier node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitTokenWithSuffix(node.keyword, " ");
-    _visitNodeWithSuffix(node.type, " ");
-    _visitNode(node.identifier);
-    return null;
-  }
-
-  @override
-  Object visitDefaultFormalParameter(DefaultFormalParameter node) {
-    _visitNode(node.parameter);
-    if (node.separator != null) {
-      _writer.print(" ");
-      _writer.print(node.separator.lexeme);
-      _visitNodeWithPrefix(" ", node.defaultValue);
-    }
-    return null;
-  }
-
-  @override
-  Object visitDoStatement(DoStatement node) {
-    _writer.print("do ");
-    _visitNode(node.body);
-    _writer.print(" while (");
-    _visitNode(node.condition);
-    _writer.print(");");
-    return null;
-  }
-
-  @override
-  Object visitDottedName(DottedName node) {
-    _visitNodeListWithSeparator(node.components, ".");
-    return null;
-  }
-
-  @override
-  Object visitDoubleLiteral(DoubleLiteral node) {
-    _writer.print(node.literal.lexeme);
-    return null;
-  }
-
-  @override
-  Object visitEmptyFunctionBody(EmptyFunctionBody node) {
-    _writer.print(';');
-    return null;
-  }
-
-  @override
-  Object visitEmptyStatement(EmptyStatement node) {
-    _writer.print(';');
-    return null;
-  }
-
-  @override
-  Object visitEnumConstantDeclaration(EnumConstantDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitNode(node.name);
-    return null;
-  }
-
-  @override
-  Object visitEnumDeclaration(EnumDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _writer.print("enum ");
-    _visitNode(node.name);
-    _writer.print(" {");
-    _visitNodeListWithSeparator(node.constants, ", ");
-    _writer.print("}");
-    return null;
-  }
-
-  @override
-  Object visitExportDirective(ExportDirective node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _writer.print("export ");
-    _visitNode(node.uri);
-    _visitNodeListWithSeparatorAndPrefix(" ", node.combinators, " ");
-    _writer.print(';');
-    return null;
-  }
-
-  @override
-  Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
-    Token keyword = node.keyword;
-    if (keyword != null) {
-      _writer.print(keyword.lexeme);
-      _writer.print(' ');
-    }
-    _writer.print("=> ");
-    _visitNode(node.expression);
-    if (node.semicolon != null) {
-      _writer.print(';');
-    }
-    return null;
-  }
-
-  @override
-  Object visitExpressionStatement(ExpressionStatement node) {
-    _visitNode(node.expression);
-    _writer.print(';');
-    return null;
-  }
-
-  @override
-  Object visitExtendsClause(ExtendsClause node) {
-    _writer.print("extends ");
-    _visitNode(node.superclass);
-    return null;
-  }
-
-  @override
-  Object visitFieldDeclaration(FieldDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitTokenWithSuffix(node.staticKeyword, " ");
-    _visitNode(node.fields);
-    _writer.print(";");
-    return null;
-  }
-
-  @override
-  Object visitFieldFormalParameter(FieldFormalParameter node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
-    _visitTokenWithSuffix(node.keyword, " ");
-    _visitNodeWithSuffix(node.type, " ");
-    _writer.print("this.");
-    _visitNode(node.identifier);
-    _visitNode(node.typeParameters);
-    _visitNode(node.parameters);
-    return null;
-  }
-
-  @override
-  Object visitForEachStatement(ForEachStatement node) {
-    DeclaredIdentifier loopVariable = node.loopVariable;
-    if (node.awaitKeyword != null) {
-      _writer.print("await ");
-    }
-    _writer.print("for (");
-    if (loopVariable == null) {
-      _visitNode(node.identifier);
-    } else {
-      _visitNode(loopVariable);
-    }
-    _writer.print(" in ");
-    _visitNode(node.iterable);
-    _writer.print(") ");
-    _visitNode(node.body);
-    return null;
-  }
-
-  @override
-  Object visitFormalParameterList(FormalParameterList node) {
-    String groupEnd = null;
-    _writer.print('(');
-    NodeList<FormalParameter> parameters = node.parameters;
-    int size = parameters.length;
-    for (int i = 0; i < size; i++) {
-      FormalParameter parameter = parameters[i];
-      if (i > 0) {
-        _writer.print(", ");
-      }
-      if (groupEnd == null && parameter is DefaultFormalParameter) {
-        if (parameter.kind == ParameterKind.NAMED) {
-          groupEnd = "}";
-          _writer.print('{');
-        } else {
-          groupEnd = "]";
-          _writer.print('[');
-        }
-      }
-      parameter.accept(this);
-    }
-    if (groupEnd != null) {
-      _writer.print(groupEnd);
-    }
-    _writer.print(')');
-    return null;
-  }
-
-  @override
-  Object visitForStatement(ForStatement node) {
-    Expression initialization = node.initialization;
-    _writer.print("for (");
-    if (initialization != null) {
-      _visitNode(initialization);
-    } else {
-      _visitNode(node.variables);
-    }
-    _writer.print(";");
-    _visitNodeWithPrefix(" ", node.condition);
-    _writer.print(";");
-    _visitNodeListWithSeparatorAndPrefix(" ", node.updaters, ", ");
-    _writer.print(") ");
-    _visitNode(node.body);
-    return null;
-  }
-
-  @override
-  Object visitFunctionDeclaration(FunctionDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitTokenWithSuffix(node.externalKeyword, " ");
-    _visitNodeWithSuffix(node.returnType, " ");
-    _visitTokenWithSuffix(node.propertyKeyword, " ");
-    _visitNode(node.name);
-    _visitNode(node.functionExpression);
-    return null;
-  }
-
-  @override
-  Object visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
-    _visitNode(node.functionDeclaration);
-    return null;
-  }
-
-  @override
-  Object visitFunctionExpression(FunctionExpression node) {
-    _visitNode(node.typeParameters);
-    _visitNode(node.parameters);
-    if (node.body is! EmptyFunctionBody) {
-      _writer.print(' ');
-    }
-    _visitNode(node.body);
-    return null;
-  }
-
-  @override
-  Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
-    _visitNode(node.function);
-    _visitNode(node.typeArguments);
-    _visitNode(node.argumentList);
-    return null;
-  }
-
-  @override
-  Object visitFunctionTypeAlias(FunctionTypeAlias node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _writer.print("typedef ");
-    _visitNodeWithSuffix(node.returnType, " ");
-    _visitNode(node.name);
-    _visitNode(node.typeParameters);
-    _visitNode(node.parameters);
-    _writer.print(";");
-    return null;
-  }
-
-  @override
-  Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
-    _visitNodeWithSuffix(node.returnType, " ");
-    _visitNode(node.identifier);
-    _visitNode(node.typeParameters);
-    _visitNode(node.parameters);
-    return null;
-  }
-
-  @override
-  Object visitHideCombinator(HideCombinator node) {
-    _writer.print("hide ");
-    _visitNodeListWithSeparator(node.hiddenNames, ", ");
-    return null;
-  }
-
-  @override
-  Object visitIfStatement(IfStatement node) {
-    _writer.print("if (");
-    _visitNode(node.condition);
-    _writer.print(") ");
-    _visitNode(node.thenStatement);
-    _visitNodeWithPrefix(" else ", node.elseStatement);
-    return null;
-  }
-
-  @override
-  Object visitImplementsClause(ImplementsClause node) {
-    _writer.print("implements ");
-    _visitNodeListWithSeparator(node.interfaces, ", ");
-    return null;
-  }
-
-  @override
-  Object visitImportDirective(ImportDirective node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _writer.print("import ");
-    _visitNode(node.uri);
-    if (node.deferredKeyword != null) {
-      _writer.print(" deferred");
-    }
-    _visitNodeWithPrefix(" as ", node.prefix);
-    _visitNodeListWithSeparatorAndPrefix(" ", node.combinators, " ");
-    _writer.print(';');
-    return null;
-  }
-
-  @override
-  Object visitIndexExpression(IndexExpression node) {
-    if (node.isCascaded) {
-      _writer.print("..");
-    } else {
-      _visitNode(node.target);
-    }
-    _writer.print('[');
-    _visitNode(node.index);
-    _writer.print(']');
-    return null;
-  }
-
-  @override
-  Object visitInstanceCreationExpression(InstanceCreationExpression node) {
-    _visitTokenWithSuffix(node.keyword, " ");
-    _visitNode(node.constructorName);
-    _visitNode(node.argumentList);
-    return null;
-  }
-
-  @override
-  Object visitIntegerLiteral(IntegerLiteral node) {
-    _writer.print(node.literal.lexeme);
-    return null;
-  }
-
-  @override
-  Object visitInterpolationExpression(InterpolationExpression node) {
-    if (node.rightBracket != null) {
-      _writer.print("\${");
-      _visitNode(node.expression);
-      _writer.print("}");
-    } else {
-      _writer.print("\$");
-      _visitNode(node.expression);
-    }
-    return null;
-  }
-
-  @override
-  Object visitInterpolationString(InterpolationString node) {
-    _writer.print(node.contents.lexeme);
-    return null;
-  }
-
-  @override
-  Object visitIsExpression(IsExpression node) {
-    _visitNode(node.expression);
-    if (node.notOperator == null) {
-      _writer.print(" is ");
-    } else {
-      _writer.print(" is! ");
-    }
-    _visitNode(node.type);
-    return null;
-  }
-
-  @override
-  Object visitLabel(Label node) {
-    _visitNode(node.label);
-    _writer.print(":");
-    return null;
-  }
-
-  @override
-  Object visitLabeledStatement(LabeledStatement node) {
-    _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
-    _visitNode(node.statement);
-    return null;
-  }
-
-  @override
-  Object visitLibraryDirective(LibraryDirective node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _writer.print("library ");
-    _visitNode(node.name);
-    _writer.print(';');
-    return null;
-  }
-
-  @override
-  Object visitLibraryIdentifier(LibraryIdentifier node) {
-    _writer.print(node.name);
-    return null;
-  }
-
-  @override
-  Object visitListLiteral(ListLiteral node) {
-    if (node.constKeyword != null) {
-      _writer.print(node.constKeyword.lexeme);
-      _writer.print(' ');
-    }
-    _visitNodeWithSuffix(node.typeArguments, " ");
-    _writer.print("[");
-    _visitNodeListWithSeparator(node.elements, ", ");
-    _writer.print("]");
-    return null;
-  }
-
-  @override
-  Object visitMapLiteral(MapLiteral node) {
-    if (node.constKeyword != null) {
-      _writer.print(node.constKeyword.lexeme);
-      _writer.print(' ');
-    }
-    _visitNodeWithSuffix(node.typeArguments, " ");
-    _writer.print("{");
-    _visitNodeListWithSeparator(node.entries, ", ");
-    _writer.print("}");
-    return null;
-  }
-
-  @override
-  Object visitMapLiteralEntry(MapLiteralEntry node) {
-    _visitNode(node.key);
-    _writer.print(" : ");
-    _visitNode(node.value);
-    return null;
-  }
-
-  @override
-  Object visitMethodDeclaration(MethodDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitTokenWithSuffix(node.externalKeyword, " ");
-    _visitTokenWithSuffix(node.modifierKeyword, " ");
-    _visitNodeWithSuffix(node.returnType, " ");
-    _visitTokenWithSuffix(node.propertyKeyword, " ");
-    _visitTokenWithSuffix(node.operatorKeyword, " ");
-    _visitNode(node.name);
-    if (!node.isGetter) {
-      _visitNode(node.typeParameters);
-      _visitNode(node.parameters);
-    }
-    _visitFunctionWithPrefix(" ", node.body);
-    return null;
-  }
-
-  @override
-  Object visitMethodInvocation(MethodInvocation node) {
-    if (node.isCascaded) {
-      _writer.print("..");
-    } else {
-      if (node.target != null) {
-        node.target.accept(this);
-        _writer.print(node.operator.lexeme);
-      }
-    }
-    _visitNode(node.methodName);
-    _visitNode(node.typeArguments);
-    _visitNode(node.argumentList);
-    return null;
-  }
-
-  @override
-  Object visitNamedExpression(NamedExpression node) {
-    _visitNode(node.name);
-    _visitNodeWithPrefix(" ", node.expression);
-    return null;
-  }
-
-  @override
-  Object visitNativeClause(NativeClause node) {
-    _writer.print("native ");
-    _visitNode(node.name);
-    return null;
-  }
-
-  @override
-  Object visitNativeFunctionBody(NativeFunctionBody node) {
-    _writer.print("native ");
-    _visitNode(node.stringLiteral);
-    _writer.print(';');
-    return null;
-  }
-
-  @override
-  Object visitNullLiteral(NullLiteral node) {
-    _writer.print("null");
-    return null;
-  }
-
-  @override
-  Object visitParenthesizedExpression(ParenthesizedExpression node) {
-    _writer.print('(');
-    _visitNode(node.expression);
-    _writer.print(')');
-    return null;
-  }
-
-  @override
-  Object visitPartDirective(PartDirective node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _writer.print("part ");
-    _visitNode(node.uri);
-    _writer.print(';');
-    return null;
-  }
-
-  @override
-  Object visitPartOfDirective(PartOfDirective node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _writer.print("part of ");
-    _visitNode(node.libraryName);
-    _writer.print(';');
-    return null;
-  }
-
-  @override
-  Object visitPostfixExpression(PostfixExpression node) {
-    _visitNode(node.operand);
-    _writer.print(node.operator.lexeme);
-    return null;
-  }
-
-  @override
-  Object visitPrefixedIdentifier(PrefixedIdentifier node) {
-    _visitNode(node.prefix);
-    _writer.print('.');
-    _visitNode(node.identifier);
-    return null;
-  }
-
-  @override
-  Object visitPrefixExpression(PrefixExpression node) {
-    _writer.print(node.operator.lexeme);
-    _visitNode(node.operand);
-    return null;
-  }
-
-  @override
-  Object visitPropertyAccess(PropertyAccess node) {
-    if (node.isCascaded) {
-      _writer.print("..");
-    } else {
-      _visitNode(node.target);
-      _writer.print(node.operator.lexeme);
-    }
-    _visitNode(node.propertyName);
-    return null;
-  }
-
-  @override
-  Object visitRedirectingConstructorInvocation(
-      RedirectingConstructorInvocation node) {
-    _writer.print("this");
-    _visitNodeWithPrefix(".", node.constructorName);
-    _visitNode(node.argumentList);
-    return null;
-  }
-
-  @override
-  Object visitRethrowExpression(RethrowExpression node) {
-    _writer.print("rethrow");
-    return null;
-  }
-
-  @override
-  Object visitReturnStatement(ReturnStatement node) {
-    Expression expression = node.expression;
-    if (expression == null) {
-      _writer.print("return;");
-    } else {
-      _writer.print("return ");
-      expression.accept(this);
-      _writer.print(";");
-    }
-    return null;
-  }
-
-  @override
-  Object visitScriptTag(ScriptTag node) {
-    _writer.print(node.scriptTag.lexeme);
-    return null;
-  }
-
-  @override
-  Object visitShowCombinator(ShowCombinator node) {
-    _writer.print("show ");
-    _visitNodeListWithSeparator(node.shownNames, ", ");
-    return null;
-  }
-
-  @override
-  Object visitSimpleFormalParameter(SimpleFormalParameter node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
-    _visitTokenWithSuffix(node.keyword, " ");
-    _visitNodeWithSuffix(node.type, " ");
-    _visitNode(node.identifier);
-    return null;
-  }
-
-  @override
-  Object visitSimpleIdentifier(SimpleIdentifier node) {
-    _writer.print(node.token.lexeme);
-    return null;
-  }
-
-  @override
-  Object visitSimpleStringLiteral(SimpleStringLiteral node) {
-    _writer.print(node.literal.lexeme);
-    return null;
-  }
-
-  @override
-  Object visitStringInterpolation(StringInterpolation node) {
-    _visitNodeList(node.elements);
-    return null;
-  }
-
-  @override
-  Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
-    _writer.print("super");
-    _visitNodeWithPrefix(".", node.constructorName);
-    _visitNode(node.argumentList);
-    return null;
-  }
-
-  @override
-  Object visitSuperExpression(SuperExpression node) {
-    _writer.print("super");
-    return null;
-  }
-
-  @override
-  Object visitSwitchCase(SwitchCase node) {
-    _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
-    _writer.print("case ");
-    _visitNode(node.expression);
-    _writer.print(": ");
-    _visitNodeListWithSeparator(node.statements, " ");
-    return null;
-  }
-
-  @override
-  Object visitSwitchDefault(SwitchDefault node) {
-    _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
-    _writer.print("default: ");
-    _visitNodeListWithSeparator(node.statements, " ");
-    return null;
-  }
-
-  @override
-  Object visitSwitchStatement(SwitchStatement node) {
-    _writer.print("switch (");
-    _visitNode(node.expression);
-    _writer.print(") {");
-    _visitNodeListWithSeparator(node.members, " ");
-    _writer.print("}");
-    return null;
-  }
-
-  @override
-  Object visitSymbolLiteral(SymbolLiteral node) {
-    _writer.print("#");
-    List<Token> components = node.components;
-    for (int i = 0; i < components.length; i++) {
-      if (i > 0) {
-        _writer.print(".");
-      }
-      _writer.print(components[i].lexeme);
-    }
-    return null;
-  }
-
-  @override
-  Object visitThisExpression(ThisExpression node) {
-    _writer.print("this");
-    return null;
-  }
-
-  @override
-  Object visitThrowExpression(ThrowExpression node) {
-    _writer.print("throw ");
-    _visitNode(node.expression);
-    return null;
-  }
-
-  @override
-  Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    _visitNodeWithSuffix(node.variables, ";");
-    return null;
-  }
-
-  @override
-  Object visitTryStatement(TryStatement node) {
-    _writer.print("try ");
-    _visitNode(node.body);
-    _visitNodeListWithSeparatorAndPrefix(" ", node.catchClauses, " ");
-    _visitNodeWithPrefix(" finally ", node.finallyBlock);
-    return null;
-  }
-
-  @override
-  Object visitTypeArgumentList(TypeArgumentList node) {
-    _writer.print('<');
-    _visitNodeListWithSeparator(node.arguments, ", ");
-    _writer.print('>');
-    return null;
-  }
-
-  @override
-  Object visitTypeName(TypeName node) {
-    _visitNode(node.name);
-    _visitNode(node.typeArguments);
-    return null;
-  }
-
-  @override
-  Object visitTypeParameter(TypeParameter node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitNode(node.name);
-    _visitNodeWithPrefix(" extends ", node.bound);
-    return null;
-  }
-
-  @override
-  Object visitTypeParameterList(TypeParameterList node) {
-    _writer.print('<');
-    _visitNodeListWithSeparator(node.typeParameters, ", ");
-    _writer.print('>');
-    return null;
-  }
-
-  @override
-  Object visitVariableDeclaration(VariableDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitNode(node.name);
-    _visitNodeWithPrefix(" = ", node.initializer);
-    return null;
-  }
-
-  @override
-  Object visitVariableDeclarationList(VariableDeclarationList node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitTokenWithSuffix(node.keyword, " ");
-    _visitNodeWithSuffix(node.type, " ");
-    _visitNodeListWithSeparator(node.variables, ", ");
-    return null;
-  }
-
-  @override
-  Object visitVariableDeclarationStatement(VariableDeclarationStatement node) {
-    _visitNode(node.variables);
-    _writer.print(";");
-    return null;
-  }
-
-  @override
-  Object visitWhileStatement(WhileStatement node) {
-    _writer.print("while (");
-    _visitNode(node.condition);
-    _writer.print(") ");
-    _visitNode(node.body);
-    return null;
-  }
-
-  @override
-  Object visitWithClause(WithClause node) {
-    _writer.print("with ");
-    _visitNodeListWithSeparator(node.mixinTypes, ", ");
-    return null;
-  }
-
-  @override
-  Object visitYieldStatement(YieldStatement node) {
-    if (node.star != null) {
-      _writer.print("yield* ");
-    } else {
-      _writer.print("yield ");
-    }
-    _visitNode(node.expression);
-    _writer.print(";");
-    return null;
-  }
-
-  /**
-   * Visit the given function [body], printing the [prefix] before if the body
-   * is not empty.
-   */
-  void _visitFunctionWithPrefix(String prefix, FunctionBody body) {
-    if (body is! EmptyFunctionBody) {
-      _writer.print(prefix);
-    }
-    _visitNode(body);
-  }
-
-  /**
-   * Safely visit the given [node].
-   */
-  void _visitNode(AstNode node) {
-    if (node != null) {
-      node.accept(this);
-    }
-  }
-
-  /**
-   * Print a list of [nodes] without any separation.
-   */
-  void _visitNodeList(NodeList<AstNode> nodes) {
-    _visitNodeListWithSeparator(nodes, "");
-  }
-
-  /**
-   * Print a list of [nodes], separated by the given [separator].
-   */
-  void _visitNodeListWithSeparator(NodeList<AstNode> nodes, String separator) {
-    if (nodes != null) {
-      int size = nodes.length;
-      for (int i = 0; i < size; i++) {
-        if (i > 0) {
-          _writer.print(separator);
-        }
-        nodes[i].accept(this);
-      }
-    }
-  }
-
-  /**
-   * Print a list of [nodes], prefixed by the given [prefix] if the list is not
-   * empty, and separated by the given [separator].
-   */
-  void _visitNodeListWithSeparatorAndPrefix(
-      String prefix, NodeList<AstNode> nodes, String separator) {
-    if (nodes != null) {
-      int size = nodes.length;
-      if (size > 0) {
-        _writer.print(prefix);
-        for (int i = 0; i < size; i++) {
-          if (i > 0) {
-            _writer.print(separator);
-          }
-          nodes[i].accept(this);
-        }
-      }
-    }
-  }
-
-  /**
-   * Print a list of [nodes], separated by the given [separator], followed by
-   * the given [suffix] if the list is not empty.
-   */
-  void _visitNodeListWithSeparatorAndSuffix(
-      NodeList<AstNode> nodes, String separator, String suffix) {
-    if (nodes != null) {
-      int size = nodes.length;
-      if (size > 0) {
-        for (int i = 0; i < size; i++) {
-          if (i > 0) {
-            _writer.print(separator);
-          }
-          nodes[i].accept(this);
-        }
-        _writer.print(suffix);
-      }
-    }
-  }
-
-  /**
-   * Safely visit the given [node], printing the [prefix] before the node if it
-   * is non-`null`.
-   */
-  void _visitNodeWithPrefix(String prefix, AstNode node) {
-    if (node != null) {
-      _writer.print(prefix);
-      node.accept(this);
-    }
-  }
-
-  /**
-   * Safely visit the given [node], printing the [suffix] after the node if it
-   * is non-`null`.
-   */
-  void _visitNodeWithSuffix(AstNode node, String suffix) {
-    if (node != null) {
-      node.accept(this);
-      _writer.print(suffix);
-    }
-  }
-
-  /**
-   * Safely visit the given [token], printing the [suffix] after the token if it
-   * is non-`null`.
-   */
-  void _visitTokenWithSuffix(Token token, String suffix) {
-    if (token != null) {
-      _writer.print(token.lexeme);
-      _writer.print(suffix);
-    }
-  }
-}
-
-/**
  * A try statement.
  *
  * > tryStatement ::=
@@ -19408,361 +11662,6 @@
 }
 
 /**
- * An AST visitor that will recursively visit all of the nodes in an AST
- * structure (like instances of the class [RecursiveAstVisitor]). In addition,
- * every node will also be visited by using a single unified [visitNode] method.
- *
- * Subclasses that override a visit method must either invoke the overridden
- * visit method or explicitly invoke the more general [visitNode] method.
- * Failure to do so will cause the children of the visited node to not be
- * visited.
- */
-class UnifyingAstVisitor<R> implements AstVisitor<R> {
-  @override
-  R visitAdjacentStrings(AdjacentStrings node) => visitNode(node);
-
-  @override
-  R visitAnnotation(Annotation node) => visitNode(node);
-
-  @override
-  R visitArgumentList(ArgumentList node) => visitNode(node);
-
-  @override
-  R visitAsExpression(AsExpression node) => visitNode(node);
-
-  @override
-  R visitAssertStatement(AssertStatement node) => visitNode(node);
-
-  @override
-  R visitAssignmentExpression(AssignmentExpression node) => visitNode(node);
-
-  @override
-  R visitAwaitExpression(AwaitExpression node) => visitNode(node);
-
-  @override
-  R visitBinaryExpression(BinaryExpression node) => visitNode(node);
-
-  @override
-  R visitBlock(Block node) => visitNode(node);
-
-  @override
-  R visitBlockFunctionBody(BlockFunctionBody node) => visitNode(node);
-
-  @override
-  R visitBooleanLiteral(BooleanLiteral node) => visitNode(node);
-
-  @override
-  R visitBreakStatement(BreakStatement node) => visitNode(node);
-
-  @override
-  R visitCascadeExpression(CascadeExpression node) => visitNode(node);
-
-  @override
-  R visitCatchClause(CatchClause node) => visitNode(node);
-
-  @override
-  R visitClassDeclaration(ClassDeclaration node) => visitNode(node);
-
-  @override
-  R visitClassTypeAlias(ClassTypeAlias node) => visitNode(node);
-
-  @override
-  R visitComment(Comment node) => visitNode(node);
-
-  @override
-  R visitCommentReference(CommentReference node) => visitNode(node);
-
-  @override
-  R visitCompilationUnit(CompilationUnit node) => visitNode(node);
-
-  @override
-  R visitConditionalExpression(ConditionalExpression node) => visitNode(node);
-
-  @override
-  R visitConfiguration(Configuration node) => visitNode(node);
-
-  @override
-  R visitConstructorDeclaration(ConstructorDeclaration node) => visitNode(node);
-
-  @override
-  R visitConstructorFieldInitializer(ConstructorFieldInitializer node) =>
-      visitNode(node);
-
-  @override
-  R visitConstructorName(ConstructorName node) => visitNode(node);
-
-  @override
-  R visitContinueStatement(ContinueStatement node) => visitNode(node);
-
-  @override
-  R visitDeclaredIdentifier(DeclaredIdentifier node) => visitNode(node);
-
-  @override
-  R visitDefaultFormalParameter(DefaultFormalParameter node) => visitNode(node);
-
-  @override
-  R visitDoStatement(DoStatement node) => visitNode(node);
-
-  @override
-  R visitDottedName(DottedName node) => visitNode(node);
-
-  @override
-  R visitDoubleLiteral(DoubleLiteral node) => visitNode(node);
-
-  @override
-  R visitEmptyFunctionBody(EmptyFunctionBody node) => visitNode(node);
-
-  @override
-  R visitEmptyStatement(EmptyStatement node) => visitNode(node);
-
-  @override
-  R visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
-      visitNode(node);
-
-  @override
-  R visitEnumDeclaration(EnumDeclaration node) => visitNode(node);
-
-  @override
-  R visitExportDirective(ExportDirective node) => visitNode(node);
-
-  @override
-  R visitExpressionFunctionBody(ExpressionFunctionBody node) => visitNode(node);
-
-  @override
-  R visitExpressionStatement(ExpressionStatement node) => visitNode(node);
-
-  @override
-  R visitExtendsClause(ExtendsClause node) => visitNode(node);
-
-  @override
-  R visitFieldDeclaration(FieldDeclaration node) => visitNode(node);
-
-  @override
-  R visitFieldFormalParameter(FieldFormalParameter node) => visitNode(node);
-
-  @override
-  R visitForEachStatement(ForEachStatement node) => visitNode(node);
-
-  @override
-  R visitFormalParameterList(FormalParameterList node) => visitNode(node);
-
-  @override
-  R visitForStatement(ForStatement node) => visitNode(node);
-
-  @override
-  R visitFunctionDeclaration(FunctionDeclaration node) => visitNode(node);
-
-  @override
-  R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) =>
-      visitNode(node);
-
-  @override
-  R visitFunctionExpression(FunctionExpression node) => visitNode(node);
-
-  @override
-  R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) =>
-      visitNode(node);
-
-  @override
-  R visitFunctionTypeAlias(FunctionTypeAlias node) => visitNode(node);
-
-  @override
-  R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) =>
-      visitNode(node);
-
-  @override
-  R visitHideCombinator(HideCombinator node) => visitNode(node);
-
-  @override
-  R visitIfStatement(IfStatement node) => visitNode(node);
-
-  @override
-  R visitImplementsClause(ImplementsClause node) => visitNode(node);
-
-  @override
-  R visitImportDirective(ImportDirective node) => visitNode(node);
-
-  @override
-  R visitIndexExpression(IndexExpression node) => visitNode(node);
-
-  @override
-  R visitInstanceCreationExpression(InstanceCreationExpression node) =>
-      visitNode(node);
-
-  @override
-  R visitIntegerLiteral(IntegerLiteral node) => visitNode(node);
-
-  @override
-  R visitInterpolationExpression(InterpolationExpression node) =>
-      visitNode(node);
-
-  @override
-  R visitInterpolationString(InterpolationString node) => visitNode(node);
-
-  @override
-  R visitIsExpression(IsExpression node) => visitNode(node);
-
-  @override
-  R visitLabel(Label node) => visitNode(node);
-
-  @override
-  R visitLabeledStatement(LabeledStatement node) => visitNode(node);
-
-  @override
-  R visitLibraryDirective(LibraryDirective node) => visitNode(node);
-
-  @override
-  R visitLibraryIdentifier(LibraryIdentifier node) => visitNode(node);
-
-  @override
-  R visitListLiteral(ListLiteral node) => visitNode(node);
-
-  @override
-  R visitMapLiteral(MapLiteral node) => visitNode(node);
-
-  @override
-  R visitMapLiteralEntry(MapLiteralEntry node) => visitNode(node);
-
-  @override
-  R visitMethodDeclaration(MethodDeclaration node) => visitNode(node);
-
-  @override
-  R visitMethodInvocation(MethodInvocation node) => visitNode(node);
-
-  @override
-  R visitNamedExpression(NamedExpression node) => visitNode(node);
-
-  @override
-  R visitNativeClause(NativeClause node) => visitNode(node);
-
-  @override
-  R visitNativeFunctionBody(NativeFunctionBody node) => visitNode(node);
-
-  R visitNode(AstNode node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitNullLiteral(NullLiteral node) => visitNode(node);
-
-  @override
-  R visitParenthesizedExpression(ParenthesizedExpression node) =>
-      visitNode(node);
-
-  @override
-  R visitPartDirective(PartDirective node) => visitNode(node);
-
-  @override
-  R visitPartOfDirective(PartOfDirective node) => visitNode(node);
-
-  @override
-  R visitPostfixExpression(PostfixExpression node) => visitNode(node);
-
-  @override
-  R visitPrefixedIdentifier(PrefixedIdentifier node) => visitNode(node);
-
-  @override
-  R visitPrefixExpression(PrefixExpression node) => visitNode(node);
-
-  @override
-  R visitPropertyAccess(PropertyAccess node) => visitNode(node);
-
-  @override
-  R visitRedirectingConstructorInvocation(
-          RedirectingConstructorInvocation node) =>
-      visitNode(node);
-
-  @override
-  R visitRethrowExpression(RethrowExpression node) => visitNode(node);
-
-  @override
-  R visitReturnStatement(ReturnStatement node) => visitNode(node);
-
-  @override
-  R visitScriptTag(ScriptTag scriptTag) => visitNode(scriptTag);
-
-  @override
-  R visitShowCombinator(ShowCombinator node) => visitNode(node);
-
-  @override
-  R visitSimpleFormalParameter(SimpleFormalParameter node) => visitNode(node);
-
-  @override
-  R visitSimpleIdentifier(SimpleIdentifier node) => visitNode(node);
-
-  @override
-  R visitSimpleStringLiteral(SimpleStringLiteral node) => visitNode(node);
-
-  @override
-  R visitStringInterpolation(StringInterpolation node) => visitNode(node);
-
-  @override
-  R visitSuperConstructorInvocation(SuperConstructorInvocation node) =>
-      visitNode(node);
-
-  @override
-  R visitSuperExpression(SuperExpression node) => visitNode(node);
-
-  @override
-  R visitSwitchCase(SwitchCase node) => visitNode(node);
-
-  @override
-  R visitSwitchDefault(SwitchDefault node) => visitNode(node);
-
-  @override
-  R visitSwitchStatement(SwitchStatement node) => visitNode(node);
-
-  @override
-  R visitSymbolLiteral(SymbolLiteral node) => visitNode(node);
-
-  @override
-  R visitThisExpression(ThisExpression node) => visitNode(node);
-
-  @override
-  R visitThrowExpression(ThrowExpression node) => visitNode(node);
-
-  @override
-  R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) =>
-      visitNode(node);
-
-  @override
-  R visitTryStatement(TryStatement node) => visitNode(node);
-
-  @override
-  R visitTypeArgumentList(TypeArgumentList node) => visitNode(node);
-
-  @override
-  R visitTypeName(TypeName node) => visitNode(node);
-
-  @override
-  R visitTypeParameter(TypeParameter node) => visitNode(node);
-
-  @override
-  R visitTypeParameterList(TypeParameterList node) => visitNode(node);
-
-  @override
-  R visitVariableDeclaration(VariableDeclaration node) => visitNode(node);
-
-  @override
-  R visitVariableDeclarationList(VariableDeclarationList node) =>
-      visitNode(node);
-
-  @override
-  R visitVariableDeclarationStatement(VariableDeclarationStatement node) =>
-      visitNode(node);
-
-  @override
-  R visitWhileStatement(WhileStatement node) => visitNode(node);
-
-  @override
-  R visitWithClause(WithClause node) => visitNode(node);
-
-  @override
-  R visitYieldStatement(YieldStatement node) => visitNode(node);
-}
-
-/**
  * A directive that references a URI.
  *
  * > uriBasedDirective ::=
@@ -19928,7 +11827,7 @@
 
   /**
    * This overridden implementation of getDocumentationComment() looks in the
-   * grandparent node for dartdoc comments if no documentation is specifically
+   * grandparent node for Dartdoc comments if no documentation is specifically
    * available on the node.
    */
   @override
diff --git a/pkg/analyzer/lib/src/generated/element_handle.dart b/pkg/analyzer/lib/src/generated/element_handle.dart
index f36d436..0a29cfb 100644
--- a/pkg/analyzer/lib/src/generated/element_handle.dart
+++ b/pkg/analyzer/lib/src/generated/element_handle.dart
@@ -335,6 +335,7 @@
   @override
   String get displayName => actualElement.displayName;
 
+  @deprecated
   @override
   SourceRange get docRange => actualElement.docRange;
 
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 06d0c56..9f0cda0 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -2129,7 +2129,7 @@
    * given [propertyName], return the element that represents the property.
    */
   Element _resolveElement(
-      ClassElementImpl classElement, SimpleIdentifier propertyName) {
+      ClassElement classElement, SimpleIdentifier propertyName) {
     String name = propertyName.name;
     Element element = null;
     if (propertyName.inSetterContext()) {
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 1861ffe..0e762ee 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -1887,6 +1887,18 @@
   List<WorkManager> get workManagers;
 
   /**
+   * This method is invoked when the state of the [result] of the [entry] is
+   * [CacheState.INVALID], so it is about to be computed.
+   *
+   * If the context knows how to provide the value, it sets the value into
+   * the [entry] with all required dependencies, and returns `true`.
+   *
+   * Otherwise, it returns `false` to indicate that the result should be
+   * computed as usually.
+   */
+  bool aboutToComputeResult(CacheEntry entry, ResultDescriptor result);
+
+  /**
    * Return a list containing the sources of the libraries that are exported by
    * the library with the given [source]. The list will be empty if the given
    * source is invalid, if the given source does not represent a library, or if
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index f8cba0c..b67b905 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -48,7 +48,7 @@
  */
 class DeclarationMatcher extends RecursiveAstVisitor {
   /**
-   * The libary containing the AST nodes being visited.
+   * The library containing the AST nodes being visited.
    */
   LibraryElement _enclosingLibrary;
 
@@ -165,6 +165,8 @@
         _assertEquals(constructor.parameters.length, 0);
       }
     }
+    // matches, set the element
+    node.name.staticElement = element;
   }
 
   @override
@@ -355,11 +357,12 @@
       if (newElement != null) {
         _addedElements.add(newElement);
         if (newElement is MethodElement) {
-          List<MethodElement> methods = _enclosingClass.methods;
+          List<MethodElement> methods = _enclosingClass.methods.toList();
           methods.add(newElement);
           _enclosingClass.methods = methods;
         } else {
-          List<PropertyAccessorElement> accessors = _enclosingClass.accessors;
+          List<PropertyAccessorElement> accessors =
+              _enclosingClass.accessors.toList();
           accessors.add(newElement);
           _enclosingClass.accessors = accessors;
         }
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index bd13357..33510ed 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -4219,6 +4219,14 @@
     return _tokenMatches(token, TokenType.OPEN_PAREN);
   }
 
+  bool _isPeekGenericTypeParametersAndOpenParen() {
+    if (!parseGenericMethods) {
+      return false;
+    }
+    Token token = _skipTypeArgumentList(_peek());
+    return token != null && _tokenMatches(token, TokenType.OPEN_PAREN);
+  }
+
   /**
    * Return `true` if the current token appears to be the beginning of a switch
    * member.
@@ -5216,6 +5224,9 @@
       }
       _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
       return null;
+    } else if (_isPeekGenericTypeParametersAndOpenParen()) {
+      return _parseFunctionDeclaration(
+          commentAndMetadata, modifiers.externalKeyword, null);
     } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
       TypeName returnType = _parseOptionalTypeNameComment();
       _validateModifiersForTopLevelFunction(modifiers);
@@ -5275,7 +5286,8 @@
     if (_peek().matchesAny([
       TokenType.OPEN_PAREN,
       TokenType.FUNCTION,
-      TokenType.OPEN_CURLY_BRACKET
+      TokenType.OPEN_CURLY_BRACKET,
+      TokenType.LT
     ])) {
       _validateModifiersForTopLevelFunction(modifiers);
       return _parseFunctionDeclaration(
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index a52736d..35616c6 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -2377,10 +2377,18 @@
   @override
   Object visitTypeParameter(TypeParameter node) {
     SimpleIdentifier parameterName = node.name;
-    if (_enclosingClass != null) {
-      _findIdentifier(_enclosingClass.typeParameters, parameterName);
-    } else if (_enclosingAlias != null) {
-      _findIdentifier(_enclosingAlias.typeParameters, parameterName);
+
+    Element element;
+    if (_enclosingExecutable != null) {
+      element =
+          _findIdentifier(_enclosingExecutable.typeParameters, parameterName);
+    }
+    if (element == null) {
+      if (_enclosingClass != null) {
+        _findIdentifier(_enclosingClass.typeParameters, parameterName);
+      } else if (_enclosingAlias != null) {
+        _findIdentifier(_enclosingAlias.typeParameters, parameterName);
+      }
     }
     return super.visitTypeParameter(node);
   }
@@ -5415,6 +5423,8 @@
    * A stack of return types for all of the enclosing
    * functions and methods.
    */
+  // TODO(leafp) Handle the implicit union type for Futures
+  // https://github.com/dart-lang/sdk/issues/25322
   List<DartType> _returnStack = <DartType>[];
 
   InferenceContext._(this._errorListener, TypeProvider typeProvider,
@@ -5423,9 +5433,15 @@
 
   /**
    * Get the return type of the current enclosing function, if any.
+   *
+   * The type returned for a function is the type that is expected
+   * to be used in a return or yield context.  For ordinary functions
+   * this is the same as the return type of the function.  For async
+   * functions returning Future<T> and for generator functions
+   * returning Stream<T> or Iterable<T>, this is T.
    */
   DartType get returnContext =>
-      (_returnStack.isNotEmpty) ? _returnStack.last : null;
+      _returnStack.isNotEmpty ? _returnStack.last : null;
 
   /**
    * Match type [t1] against type [t2] as follows.
@@ -8359,8 +8375,10 @@
 
   @override
   Object visitAwaitExpression(AwaitExpression node) {
-    //TODO(leafp): Handle the implicit union type here
-    DartType contextType = InferenceContext.getType(node);
+    // TODO(leafp): Handle the implicit union type here
+    // https://github.com/dart-lang/sdk/issues/25322
+    DartType contextType = StaticTypeAnalyzer.flattenFutures(
+        typeProvider, InferenceContext.getType(node));
     if (contextType != null) {
       InterfaceType futureT =
           typeProvider.futureType.substitute4([contextType]);
@@ -8894,7 +8912,11 @@
         DartType functionType = InferenceContext.getType(node);
         if (functionType is FunctionType) {
           _inferFormalParameterList(node.parameters, functionType);
-          InferenceContext.setType(node.body, functionType.returnType);
+          DartType returnType = _computeReturnOrYieldType(
+              functionType.returnType,
+              _enclosingFunction.isGenerator,
+              _enclosingFunction.isAsynchronous);
+          InferenceContext.setType(node.body, returnType);
         }
         super.visitFunctionExpression(node);
       } finally {
@@ -9099,7 +9121,11 @@
     ExecutableElement outerFunction = _enclosingFunction;
     try {
       _enclosingFunction = node.element;
-      InferenceContext.setType(node.body, node.element.type?.returnType);
+      DartType returnType = _computeReturnOrYieldType(
+          _enclosingFunction.type?.returnType,
+          _enclosingFunction.isGenerator,
+          _enclosingFunction.isAsynchronous);
+      InferenceContext.setType(node.body, returnType);
       super.visitMethodDeclaration(node);
     } finally {
       _enclosingFunction = outerFunction;
@@ -9328,18 +9354,15 @@
       // If we're not in a generator ([a]sync*, then we shouldn't have a yield.
       // so don't infer
       if (_enclosingFunction.isGenerator) {
-        // If this is a yield*, then we just propagate the return type downwards
+        // If this just a yield, then we just pass on the element type
         DartType type = returnType;
-        // If this just a yield, then we need to get the element type
-        if (node.star == null) {
+        if (node.star != null) {
+          // If this is a yield*, then we wrap the element return type
           // If it's synchronous, we expect Iterable<T>, otherwise Stream<T>
-          InterfaceType wrapperD = _enclosingFunction.isSynchronous
-              ? typeProvider.iterableDynamicType
-              : typeProvider.streamDynamicType;
-          // Match the types to instantiate the type arguments if possible
-          List<DartType> targs =
-              inferenceContext.matchTypes(wrapperD, returnType);
-          type = (targs?.length == 1) ? targs[0] : null;
+          InterfaceType wrapperType = _enclosingFunction.isSynchronous
+              ? typeProvider.iterableType
+              : typeProvider.streamType;
+          type = wrapperType.substitute4(<DartType>[type]);
         }
         InferenceContext.setType(node.expression, type);
       }
@@ -9380,6 +9403,34 @@
   }
 
   /**
+   * Given the declared return type of a function, compute the type of the
+   * values which should be returned or yielded as appropriate.  If a type
+   * cannot be computed from the declared return type, return null.
+   */
+  DartType _computeReturnOrYieldType(
+      DartType declaredType, bool isGenerator, bool isAsynchronous) {
+    // Ordinary functions just return their declared types.
+    if (!isGenerator && !isAsynchronous) {
+      return declaredType;
+    }
+    if (isGenerator) {
+      if (declaredType is! InterfaceType) {
+        return null;
+      }
+      // If it's synchronous, we expect Iterable<T>, otherwise Stream<T>
+      InterfaceType rawType = isAsynchronous
+          ? typeProvider.streamDynamicType
+          : typeProvider.iterableDynamicType;
+      // Match the types to instantiate the type arguments if possible
+      List<DartType> typeArgs =
+          inferenceContext.matchTypes(rawType, declaredType);
+      return (typeArgs?.length == 1) ? typeArgs[0] : null;
+    }
+    // Must be asynchronous to reach here, so strip off any layers of Future
+    return StaticTypeAnalyzer.flattenFutures(typeProvider, declaredType);
+  }
+
+  /**
    * The given expression is the expression used to compute the iterator for a
    * for-each statement. Attempt to compute the type of objects that will be
    * assigned to the loop variable and return that type. Return `null` if the
diff --git a/pkg/analyzer/lib/src/generated/sdk_io.dart b/pkg/analyzer/lib/src/generated/sdk_io.dart
index 1f98ba3..1fc4b33 100644
--- a/pkg/analyzer/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer/lib/src/generated/sdk_io.dart
@@ -18,6 +18,9 @@
 import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/summary/format.dart' show SdkBundle;
+import 'package:analyzer/src/summary/summary_sdk.dart';
+import 'package:path/path.dart' as pathos;
 
 /**
  * A Dart SDK installed in a specified directory. Typical Dart SDK layout is
@@ -241,7 +244,12 @@
   @override
   AnalysisContext get context {
     if (_analysisContext == null) {
-      _analysisContext = new SdkAnalysisContext();
+      SdkBundle sdkBundle = _getSummarySdkBundle();
+      if (sdkBundle != null) {
+        _analysisContext = new SummarySdkAnalysisContext(sdkBundle);
+      } else {
+        _analysisContext = new SdkAnalysisContext();
+      }
       SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
       _analysisContext.sourceFactory = factory;
       List<String> uris = this.uris;
@@ -533,6 +541,26 @@
   }
 
   /**
+   * Return the [SdkBundle] for this SDK, if it exists, or `null` otherwise.
+   */
+  SdkBundle _getSummarySdkBundle() {
+    String rootPath = directory.getAbsolutePath();
+    String path = pathos.join(rootPath, 'lib', '_internal', 'analysis_summary');
+    try {
+      File file = new File(path);
+      if (file.existsSync()) {
+        List<int> bytes = file.readAsBytesSync();
+        return new SdkBundle.fromBuffer(bytes);
+      }
+    } catch (exception, stackTrace) {
+      AnalysisEngine.instance.logger.logError(
+          'Failed to load SDK analysis summary from $path',
+          new CaughtException(exception, stackTrace));
+    }
+    return null;
+  }
+
+  /**
    * Return the given [file] if it exists and is executable, or `null` if it
    * does not exist or is not executable.
    */
diff --git a/pkg/analyzer/lib/src/summary/builder.dart b/pkg/analyzer/lib/src/summary/base.dart
similarity index 61%
rename from pkg/analyzer/lib/src/summary/builder.dart
rename to pkg/analyzer/lib/src/summary/base.dart
index c1bedfb..0002dc9 100644
--- a/pkg/analyzer/lib/src/summary/builder.dart
+++ b/pkg/analyzer/lib/src/summary/base.dart
@@ -3,9 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /**
- * Format-agnostic infrastructure for building summary objects.
+ * Base functionality which code generated summary classes are built upon.
  */
-library analyzer.src.summary.builder;
+library analyzer.src.summary.base;
 
 /**
  * Instances of this class encapsulate the necessary state to keep track of a
@@ -20,3 +20,16 @@
   // we switch to a serialization format that requires state tracking, the
   // state will be stored here.
 }
+
+/**
+ * Instances of this class represent data that has been read from a summary.
+ */
+abstract class SummaryClass {
+  /**
+   * Translate the data in this class into a map whose keys are the names of
+   * fields and whose values are the data stored in those fields.
+   *
+   * Intended for testing and debugging only.
+   */
+  Map<String, Object> toMap();
+}
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index d050d81..c4fb417 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -8,8 +8,12 @@
 library analyzer.src.summary.format;
 
 import 'dart:convert';
-import 'builder.dart' as builder;
+import 'base.dart' as base;
 
+/**
+ * Enum used to indicate the kind of entity referred to by a
+ * [PrelinkedReference].
+ */
 enum PrelinkedReferenceKind {
   classOrEnum,
   typedef,
@@ -18,6 +22,9 @@
   unresolved,
 }
 
+/**
+ * Enum used to indicate the kind of an executable.
+ */
 enum UnlinkedExecutableKind {
   functionOrMethod,
   getter,
@@ -25,18 +32,33 @@
   constructor,
 }
 
+/**
+ * Enum used to indicate the kind of a parameter.
+ */
 enum UnlinkedParamKind {
   required,
   positional,
   named,
 }
 
-class PrelinkedDependency {
+/**
+ * Information about a dependency that exists between one library and another
+ * due to an "import" declaration.
+ */
+class PrelinkedDependency extends base.SummaryClass {
   String _uri;
 
   PrelinkedDependency.fromJson(Map json)
     : _uri = json["uri"];
 
+  @override
+  Map<String, Object> toMap() => {
+    "uri": uri,
+  };
+
+  /**
+   * The relative URI used to import one library from the other.
+   */
   String get uri => _uri ?? '';
 }
 
@@ -45,8 +67,11 @@
 
   bool _finished = false;
 
-  PrelinkedDependencyBuilder(builder.BuilderContext context);
+  PrelinkedDependencyBuilder(base.BuilderContext context);
 
+  /**
+   * The relative URI used to import one library from the other.
+   */
   void set uri(String _value) {
     assert(!_finished);
     assert(!_json.containsKey("uri"));
@@ -62,13 +87,16 @@
   }
 }
 
-PrelinkedDependencyBuilder encodePrelinkedDependency(builder.BuilderContext builderContext, {String uri}) {
+PrelinkedDependencyBuilder encodePrelinkedDependency(base.BuilderContext builderContext, {String uri}) {
   PrelinkedDependencyBuilder builder = new PrelinkedDependencyBuilder(builderContext);
   builder.uri = uri;
   return builder;
 }
 
-class PrelinkedLibrary {
+/**
+ * Pre-linked summary of a library.
+ */
+class PrelinkedLibrary extends base.SummaryClass {
   List<PrelinkedUnit> _units;
   List<PrelinkedDependency> _dependencies;
   List<int> _importDependencies;
@@ -78,10 +106,41 @@
       _dependencies = json["dependencies"]?.map((x) => new PrelinkedDependency.fromJson(x))?.toList(),
       _importDependencies = json["importDependencies"];
 
+  @override
+  Map<String, Object> toMap() => {
+    "units": units,
+    "dependencies": dependencies,
+    "importDependencies": importDependencies,
+  };
+
   PrelinkedLibrary.fromBuffer(List<int> buffer) : this.fromJson(JSON.decode(UTF8.decode(buffer)));
 
+  /**
+   * The pre-linked summary of all the compilation units constituting the
+   * library.  The summary of the defining compilation unit is listed first,
+   * followed by the summary of each part, in the order of the `part`
+   * declarations in the defining compilation unit.
+   */
   List<PrelinkedUnit> get units => _units ?? const <PrelinkedUnit>[];
+
+  /**
+   * The libraries that this library depends on (either via an explicit import
+   * statement or via the implicit dependencies on `dart:core` and
+   * `dart:async`).  The first element of this array is a pseudo-dependency
+   * representing the library itself (it is also used for "dynamic").
+   *
+   * TODO(paulberry): consider removing this entirely and just using
+   * [UnlinkedLibrary.imports].
+   */
   List<PrelinkedDependency> get dependencies => _dependencies ?? const <PrelinkedDependency>[];
+
+  /**
+   * For each import in [UnlinkedUnit.imports], an index into [dependencies]
+   * of the library being imported.
+   *
+   * TODO(paulberry): if [dependencies] is removed, this can be removed as
+   * well, since there will effectively be a one-to-one mapping.
+   */
   List<int> get importDependencies => _importDependencies ?? const <int>[];
 }
 
@@ -90,28 +149,50 @@
 
   bool _finished = false;
 
-  PrelinkedLibraryBuilder(builder.BuilderContext context);
+  PrelinkedLibraryBuilder(base.BuilderContext context);
 
+  /**
+   * The pre-linked summary of all the compilation units constituting the
+   * library.  The summary of the defining compilation unit is listed first,
+   * followed by the summary of each part, in the order of the `part`
+   * declarations in the defining compilation unit.
+   */
   void set units(List<PrelinkedUnitBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("units"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["units"] = _value.map((b) => b.finish()).toList();
     }
   }
 
+  /**
+   * The libraries that this library depends on (either via an explicit import
+   * statement or via the implicit dependencies on `dart:core` and
+   * `dart:async`).  The first element of this array is a pseudo-dependency
+   * representing the library itself (it is also used for "dynamic").
+   *
+   * TODO(paulberry): consider removing this entirely and just using
+   * [UnlinkedLibrary.imports].
+   */
   void set dependencies(List<PrelinkedDependencyBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("dependencies"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["dependencies"] = _value.map((b) => b.finish()).toList();
     }
   }
 
+  /**
+   * For each import in [UnlinkedUnit.imports], an index into [dependencies]
+   * of the library being imported.
+   *
+   * TODO(paulberry): if [dependencies] is removed, this can be removed as
+   * well, since there will effectively be a one-to-one mapping.
+   */
   void set importDependencies(List<int> _value) {
     assert(!_finished);
     assert(!_json.containsKey("importDependencies"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["importDependencies"] = _value.toList();
     }
   }
@@ -125,7 +206,7 @@
   }
 }
 
-PrelinkedLibraryBuilder encodePrelinkedLibrary(builder.BuilderContext builderContext, {List<PrelinkedUnitBuilder> units, List<PrelinkedDependencyBuilder> dependencies, List<int> importDependencies}) {
+PrelinkedLibraryBuilder encodePrelinkedLibrary(base.BuilderContext builderContext, {List<PrelinkedUnitBuilder> units, List<PrelinkedDependencyBuilder> dependencies, List<int> importDependencies}) {
   PrelinkedLibraryBuilder builder = new PrelinkedLibraryBuilder(builderContext);
   builder.units = units;
   builder.dependencies = dependencies;
@@ -133,19 +214,54 @@
   return builder;
 }
 
-class PrelinkedReference {
+/**
+ * Information about the resolution of an [UnlinkedReference].
+ */
+class PrelinkedReference extends base.SummaryClass {
   int _dependency;
   PrelinkedReferenceKind _kind;
   int _unit;
+  int _numTypeParameters;
 
   PrelinkedReference.fromJson(Map json)
     : _dependency = json["dependency"],
       _kind = json["kind"] == null ? null : PrelinkedReferenceKind.values[json["kind"]],
-      _unit = json["unit"];
+      _unit = json["unit"],
+      _numTypeParameters = json["numTypeParameters"];
 
+  @override
+  Map<String, Object> toMap() => {
+    "dependency": dependency,
+    "kind": kind,
+    "unit": unit,
+    "numTypeParameters": numTypeParameters,
+  };
+
+  /**
+   * Index into [PrelinkedLibrary.dependencies] indicating which imported library
+   * declares the entity being referred to.
+   */
   int get dependency => _dependency ?? 0;
+
+  /**
+   * The kind of the entity being referred to.  For the pseudo-type `dynamic`,
+   * the kind is [PrelinkedReferenceKind.classOrEnum].
+   */
   PrelinkedReferenceKind get kind => _kind ?? PrelinkedReferenceKind.classOrEnum;
+
+  /**
+   * Integer index indicating which unit in the imported library contains the
+   * definition of the entity.  As with indices into [PrelinkedLibrary.units],
+   * zero represents the defining compilation unit, and nonzero values
+   * represent parts in the order of the corresponding `part` declarations.
+   */
   int get unit => _unit ?? 0;
+
+  /**
+   * If the entity being referred to is generic, the number of type parameters
+   * it accepts.  Otherwise zero.
+   */
+  int get numTypeParameters => _numTypeParameters ?? 0;
 }
 
 class PrelinkedReferenceBuilder {
@@ -153,8 +269,12 @@
 
   bool _finished = false;
 
-  PrelinkedReferenceBuilder(builder.BuilderContext context);
+  PrelinkedReferenceBuilder(base.BuilderContext context);
 
+  /**
+   * Index into [PrelinkedLibrary.dependencies] indicating which imported library
+   * declares the entity being referred to.
+   */
   void set dependency(int _value) {
     assert(!_finished);
     assert(!_json.containsKey("dependency"));
@@ -163,14 +283,24 @@
     }
   }
 
+  /**
+   * The kind of the entity being referred to.  For the pseudo-type `dynamic`,
+   * the kind is [PrelinkedReferenceKind.classOrEnum].
+   */
   void set kind(PrelinkedReferenceKind _value) {
     assert(!_finished);
     assert(!_json.containsKey("kind"));
-    if (_value != null || _value == PrelinkedReferenceKind.classOrEnum) {
+    if (!(_value == null || _value == PrelinkedReferenceKind.classOrEnum)) {
       _json["kind"] = _value.index;
     }
   }
 
+  /**
+   * Integer index indicating which unit in the imported library contains the
+   * definition of the entity.  As with indices into [PrelinkedLibrary.units],
+   * zero represents the defining compilation unit, and nonzero values
+   * represent parts in the order of the corresponding `part` declarations.
+   */
   void set unit(int _value) {
     assert(!_finished);
     assert(!_json.containsKey("unit"));
@@ -179,6 +309,18 @@
     }
   }
 
+  /**
+   * If the entity being referred to is generic, the number of type parameters
+   * it accepts.  Otherwise zero.
+   */
+  void set numTypeParameters(int _value) {
+    assert(!_finished);
+    assert(!_json.containsKey("numTypeParameters"));
+    if (_value != null) {
+      _json["numTypeParameters"] = _value;
+    }
+  }
+
   Map finish() {
     assert(!_finished);
     _finished = true;
@@ -186,20 +328,33 @@
   }
 }
 
-PrelinkedReferenceBuilder encodePrelinkedReference(builder.BuilderContext builderContext, {int dependency, PrelinkedReferenceKind kind, int unit}) {
+PrelinkedReferenceBuilder encodePrelinkedReference(base.BuilderContext builderContext, {int dependency, PrelinkedReferenceKind kind, int unit, int numTypeParameters}) {
   PrelinkedReferenceBuilder builder = new PrelinkedReferenceBuilder(builderContext);
   builder.dependency = dependency;
   builder.kind = kind;
   builder.unit = unit;
+  builder.numTypeParameters = numTypeParameters;
   return builder;
 }
 
-class PrelinkedUnit {
+/**
+ * Pre-linked summary of a compilation unit.
+ */
+class PrelinkedUnit extends base.SummaryClass {
   List<PrelinkedReference> _references;
 
   PrelinkedUnit.fromJson(Map json)
     : _references = json["references"]?.map((x) => new PrelinkedReference.fromJson(x))?.toList();
 
+  @override
+  Map<String, Object> toMap() => {
+    "references": references,
+  };
+
+  /**
+   * For each reference in [UnlinkedUnit.references], information about how
+   * that reference is resolved.
+   */
   List<PrelinkedReference> get references => _references ?? const <PrelinkedReference>[];
 }
 
@@ -208,12 +363,16 @@
 
   bool _finished = false;
 
-  PrelinkedUnitBuilder(builder.BuilderContext context);
+  PrelinkedUnitBuilder(base.BuilderContext context);
 
+  /**
+   * For each reference in [UnlinkedUnit.references], information about how
+   * that reference is resolved.
+   */
   void set references(List<PrelinkedReferenceBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("references"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["references"] = _value.map((b) => b.finish()).toList();
     }
   }
@@ -225,13 +384,131 @@
   }
 }
 
-PrelinkedUnitBuilder encodePrelinkedUnit(builder.BuilderContext builderContext, {List<PrelinkedReferenceBuilder> references}) {
+PrelinkedUnitBuilder encodePrelinkedUnit(base.BuilderContext builderContext, {List<PrelinkedReferenceBuilder> references}) {
   PrelinkedUnitBuilder builder = new PrelinkedUnitBuilder(builderContext);
   builder.references = references;
   return builder;
 }
 
-class UnlinkedClass {
+/**
+ * Information about SDK.
+ */
+class SdkBundle extends base.SummaryClass {
+  List<String> _prelinkedLibraryUris;
+  List<PrelinkedLibrary> _prelinkedLibraries;
+  List<String> _unlinkedUnitUris;
+  List<UnlinkedUnit> _unlinkedUnits;
+
+  SdkBundle.fromJson(Map json)
+    : _prelinkedLibraryUris = json["prelinkedLibraryUris"],
+      _prelinkedLibraries = json["prelinkedLibraries"]?.map((x) => new PrelinkedLibrary.fromJson(x))?.toList(),
+      _unlinkedUnitUris = json["unlinkedUnitUris"],
+      _unlinkedUnits = json["unlinkedUnits"]?.map((x) => new UnlinkedUnit.fromJson(x))?.toList();
+
+  @override
+  Map<String, Object> toMap() => {
+    "prelinkedLibraryUris": prelinkedLibraryUris,
+    "prelinkedLibraries": prelinkedLibraries,
+    "unlinkedUnitUris": unlinkedUnitUris,
+    "unlinkedUnits": unlinkedUnits,
+  };
+
+  SdkBundle.fromBuffer(List<int> buffer) : this.fromJson(JSON.decode(UTF8.decode(buffer)));
+
+  /**
+   * The list of URIs of items in [prelinkedLibraries], e.g. `dart:core`.
+   */
+  List<String> get prelinkedLibraryUris => _prelinkedLibraryUris ?? const <String>[];
+
+  /**
+   * Pre-linked libraries.
+   */
+  List<PrelinkedLibrary> get prelinkedLibraries => _prelinkedLibraries ?? const <PrelinkedLibrary>[];
+
+  /**
+   * The list of URIs of items in [unlinkedUnits], e.g. `dart:core/bool.dart`.
+   */
+  List<String> get unlinkedUnitUris => _unlinkedUnitUris ?? const <String>[];
+
+  /**
+   * Unlinked information for the compilation units constituting the SDK.
+   */
+  List<UnlinkedUnit> get unlinkedUnits => _unlinkedUnits ?? const <UnlinkedUnit>[];
+}
+
+class SdkBundleBuilder {
+  final Map _json = {};
+
+  bool _finished = false;
+
+  SdkBundleBuilder(base.BuilderContext context);
+
+  /**
+   * The list of URIs of items in [prelinkedLibraries], e.g. `dart:core`.
+   */
+  void set prelinkedLibraryUris(List<String> _value) {
+    assert(!_finished);
+    assert(!_json.containsKey("prelinkedLibraryUris"));
+    if (!(_value == null || _value.isEmpty)) {
+      _json["prelinkedLibraryUris"] = _value.toList();
+    }
+  }
+
+  /**
+   * Pre-linked libraries.
+   */
+  void set prelinkedLibraries(List<PrelinkedLibraryBuilder> _value) {
+    assert(!_finished);
+    assert(!_json.containsKey("prelinkedLibraries"));
+    if (!(_value == null || _value.isEmpty)) {
+      _json["prelinkedLibraries"] = _value.map((b) => b.finish()).toList();
+    }
+  }
+
+  /**
+   * The list of URIs of items in [unlinkedUnits], e.g. `dart:core/bool.dart`.
+   */
+  void set unlinkedUnitUris(List<String> _value) {
+    assert(!_finished);
+    assert(!_json.containsKey("unlinkedUnitUris"));
+    if (!(_value == null || _value.isEmpty)) {
+      _json["unlinkedUnitUris"] = _value.toList();
+    }
+  }
+
+  /**
+   * Unlinked information for the compilation units constituting the SDK.
+   */
+  void set unlinkedUnits(List<UnlinkedUnitBuilder> _value) {
+    assert(!_finished);
+    assert(!_json.containsKey("unlinkedUnits"));
+    if (!(_value == null || _value.isEmpty)) {
+      _json["unlinkedUnits"] = _value.map((b) => b.finish()).toList();
+    }
+  }
+
+  List<int> toBuffer() => UTF8.encode(JSON.encode(finish()));
+
+  Map finish() {
+    assert(!_finished);
+    _finished = true;
+    return _json;
+  }
+}
+
+SdkBundleBuilder encodeSdkBundle(base.BuilderContext builderContext, {List<String> prelinkedLibraryUris, List<PrelinkedLibraryBuilder> prelinkedLibraries, List<String> unlinkedUnitUris, List<UnlinkedUnitBuilder> unlinkedUnits}) {
+  SdkBundleBuilder builder = new SdkBundleBuilder(builderContext);
+  builder.prelinkedLibraryUris = prelinkedLibraryUris;
+  builder.prelinkedLibraries = prelinkedLibraries;
+  builder.unlinkedUnitUris = unlinkedUnitUris;
+  builder.unlinkedUnits = unlinkedUnits;
+  return builder;
+}
+
+/**
+ * Unlinked summary information about a class declaration.
+ */
+class UnlinkedClass extends base.SummaryClass {
   String _name;
   List<UnlinkedTypeParam> _typeParameters;
   UnlinkedTypeRef _supertype;
@@ -255,15 +532,71 @@
       _isMixinApplication = json["isMixinApplication"],
       _hasNoSupertype = json["hasNoSupertype"];
 
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "typeParameters": typeParameters,
+    "supertype": supertype,
+    "mixins": mixins,
+    "interfaces": interfaces,
+    "fields": fields,
+    "executables": executables,
+    "isAbstract": isAbstract,
+    "isMixinApplication": isMixinApplication,
+    "hasNoSupertype": hasNoSupertype,
+  };
+
+  /**
+   * Name of the class.
+   */
   String get name => _name ?? '';
+
+  /**
+   * Type parameters of the class, if any.
+   */
   List<UnlinkedTypeParam> get typeParameters => _typeParameters ?? const <UnlinkedTypeParam>[];
+
+  /**
+   * Supertype of the class, or `null` if either (a) the class doesn't
+   * explicitly declare a supertype (and hence has supertype `Object`), or (b)
+   * the class *is* `Object` (and hence has no supertype).
+   */
   UnlinkedTypeRef get supertype => _supertype;
+
+  /**
+   * Mixins appearing in a `with` clause, if any.
+   */
   List<UnlinkedTypeRef> get mixins => _mixins ?? const <UnlinkedTypeRef>[];
+
+  /**
+   * Interfaces appearing in an `implements` clause, if any.
+   */
   List<UnlinkedTypeRef> get interfaces => _interfaces ?? const <UnlinkedTypeRef>[];
+
+  /**
+   * Field declarations contained in the class.
+   */
   List<UnlinkedVariable> get fields => _fields ?? const <UnlinkedVariable>[];
+
+  /**
+   * Executable objects (methods, getters, and setters) contained in the class.
+   */
   List<UnlinkedExecutable> get executables => _executables ?? const <UnlinkedExecutable>[];
+
+  /**
+   * Indicates whether the class is declared with the `abstract` keyword.
+   */
   bool get isAbstract => _isAbstract ?? false;
+
+  /**
+   * Indicates whether the class is declared using mixin application syntax.
+   */
   bool get isMixinApplication => _isMixinApplication ?? false;
+
+  /**
+   * Indicates whether this class is the core "Object" class (and hence has no
+   * supertype)
+   */
   bool get hasNoSupertype => _hasNoSupertype ?? false;
 }
 
@@ -272,8 +605,11 @@
 
   bool _finished = false;
 
-  UnlinkedClassBuilder(builder.BuilderContext context);
+  UnlinkedClassBuilder(base.BuilderContext context);
 
+  /**
+   * Name of the class.
+   */
   void set name(String _value) {
     assert(!_finished);
     assert(!_json.containsKey("name"));
@@ -282,14 +618,22 @@
     }
   }
 
+  /**
+   * Type parameters of the class, if any.
+   */
   void set typeParameters(List<UnlinkedTypeParamBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("typeParameters"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["typeParameters"] = _value.map((b) => b.finish()).toList();
     }
   }
 
+  /**
+   * Supertype of the class, or `null` if either (a) the class doesn't
+   * explicitly declare a supertype (and hence has supertype `Object`), or (b)
+   * the class *is* `Object` (and hence has no supertype).
+   */
   void set supertype(UnlinkedTypeRefBuilder _value) {
     assert(!_finished);
     assert(!_json.containsKey("supertype"));
@@ -298,38 +642,53 @@
     }
   }
 
+  /**
+   * Mixins appearing in a `with` clause, if any.
+   */
   void set mixins(List<UnlinkedTypeRefBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("mixins"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["mixins"] = _value.map((b) => b.finish()).toList();
     }
   }
 
+  /**
+   * Interfaces appearing in an `implements` clause, if any.
+   */
   void set interfaces(List<UnlinkedTypeRefBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("interfaces"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["interfaces"] = _value.map((b) => b.finish()).toList();
     }
   }
 
+  /**
+   * Field declarations contained in the class.
+   */
   void set fields(List<UnlinkedVariableBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("fields"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["fields"] = _value.map((b) => b.finish()).toList();
     }
   }
 
+  /**
+   * Executable objects (methods, getters, and setters) contained in the class.
+   */
   void set executables(List<UnlinkedExecutableBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("executables"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["executables"] = _value.map((b) => b.finish()).toList();
     }
   }
 
+  /**
+   * Indicates whether the class is declared with the `abstract` keyword.
+   */
   void set isAbstract(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("isAbstract"));
@@ -338,6 +697,9 @@
     }
   }
 
+  /**
+   * Indicates whether the class is declared using mixin application syntax.
+   */
   void set isMixinApplication(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("isMixinApplication"));
@@ -346,6 +708,10 @@
     }
   }
 
+  /**
+   * Indicates whether this class is the core "Object" class (and hence has no
+   * supertype)
+   */
   void set hasNoSupertype(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("hasNoSupertype"));
@@ -361,7 +727,7 @@
   }
 }
 
-UnlinkedClassBuilder encodeUnlinkedClass(builder.BuilderContext builderContext, {String name, List<UnlinkedTypeParamBuilder> typeParameters, UnlinkedTypeRefBuilder supertype, List<UnlinkedTypeRefBuilder> mixins, List<UnlinkedTypeRefBuilder> interfaces, List<UnlinkedVariableBuilder> fields, List<UnlinkedExecutableBuilder> executables, bool isAbstract, bool isMixinApplication, bool hasNoSupertype}) {
+UnlinkedClassBuilder encodeUnlinkedClass(base.BuilderContext builderContext, {String name, List<UnlinkedTypeParamBuilder> typeParameters, UnlinkedTypeRefBuilder supertype, List<UnlinkedTypeRefBuilder> mixins, List<UnlinkedTypeRefBuilder> interfaces, List<UnlinkedVariableBuilder> fields, List<UnlinkedExecutableBuilder> executables, bool isAbstract, bool isMixinApplication, bool hasNoSupertype}) {
   UnlinkedClassBuilder builder = new UnlinkedClassBuilder(builderContext);
   builder.name = name;
   builder.typeParameters = typeParameters;
@@ -376,16 +742,33 @@
   return builder;
 }
 
-class UnlinkedCombinator {
-  List<UnlinkedCombinatorName> _shows;
-  List<UnlinkedCombinatorName> _hides;
+/**
+ * Unlinked summary information about a `show` or `hide` combinator in an
+ * import or export declaration.
+ */
+class UnlinkedCombinator extends base.SummaryClass {
+  List<String> _shows;
+  List<String> _hides;
 
   UnlinkedCombinator.fromJson(Map json)
-    : _shows = json["shows"]?.map((x) => new UnlinkedCombinatorName.fromJson(x))?.toList(),
-      _hides = json["hides"]?.map((x) => new UnlinkedCombinatorName.fromJson(x))?.toList();
+    : _shows = json["shows"],
+      _hides = json["hides"];
 
-  List<UnlinkedCombinatorName> get shows => _shows ?? const <UnlinkedCombinatorName>[];
-  List<UnlinkedCombinatorName> get hides => _hides ?? const <UnlinkedCombinatorName>[];
+  @override
+  Map<String, Object> toMap() => {
+    "shows": shows,
+    "hides": hides,
+  };
+
+  /**
+   * List of names which are shown.  Empty if this is a `hide` combinator.
+   */
+  List<String> get shows => _shows ?? const <String>[];
+
+  /**
+   * List of names which are hidden.  Empty if this is a `show` combinator.
+   */
+  List<String> get hides => _hides ?? const <String>[];
 }
 
 class UnlinkedCombinatorBuilder {
@@ -393,21 +776,27 @@
 
   bool _finished = false;
 
-  UnlinkedCombinatorBuilder(builder.BuilderContext context);
+  UnlinkedCombinatorBuilder(base.BuilderContext context);
 
-  void set shows(List<UnlinkedCombinatorNameBuilder> _value) {
+  /**
+   * List of names which are shown.  Empty if this is a `hide` combinator.
+   */
+  void set shows(List<String> _value) {
     assert(!_finished);
     assert(!_json.containsKey("shows"));
-    if (_value != null || _value.isEmpty) {
-      _json["shows"] = _value.map((b) => b.finish()).toList();
+    if (!(_value == null || _value.isEmpty)) {
+      _json["shows"] = _value.toList();
     }
   }
 
-  void set hides(List<UnlinkedCombinatorNameBuilder> _value) {
+  /**
+   * List of names which are hidden.  Empty if this is a `show` combinator.
+   */
+  void set hides(List<String> _value) {
     assert(!_finished);
     assert(!_json.containsKey("hides"));
-    if (_value != null || _value.isEmpty) {
-      _json["hides"] = _value.map((b) => b.finish()).toList();
+    if (!(_value == null || _value.isEmpty)) {
+      _json["hides"] = _value.toList();
     }
   }
 
@@ -418,51 +807,17 @@
   }
 }
 
-UnlinkedCombinatorBuilder encodeUnlinkedCombinator(builder.BuilderContext builderContext, {List<UnlinkedCombinatorNameBuilder> shows, List<UnlinkedCombinatorNameBuilder> hides}) {
+UnlinkedCombinatorBuilder encodeUnlinkedCombinator(base.BuilderContext builderContext, {List<String> shows, List<String> hides}) {
   UnlinkedCombinatorBuilder builder = new UnlinkedCombinatorBuilder(builderContext);
   builder.shows = shows;
   builder.hides = hides;
   return builder;
 }
 
-class UnlinkedCombinatorName {
-  String _name;
-
-  UnlinkedCombinatorName.fromJson(Map json)
-    : _name = json["name"];
-
-  String get name => _name ?? '';
-}
-
-class UnlinkedCombinatorNameBuilder {
-  final Map _json = {};
-
-  bool _finished = false;
-
-  UnlinkedCombinatorNameBuilder(builder.BuilderContext context);
-
-  void set name(String _value) {
-    assert(!_finished);
-    assert(!_json.containsKey("name"));
-    if (_value != null) {
-      _json["name"] = _value;
-    }
-  }
-
-  Map finish() {
-    assert(!_finished);
-    _finished = true;
-    return _json;
-  }
-}
-
-UnlinkedCombinatorNameBuilder encodeUnlinkedCombinatorName(builder.BuilderContext builderContext, {String name}) {
-  UnlinkedCombinatorNameBuilder builder = new UnlinkedCombinatorNameBuilder(builderContext);
-  builder.name = name;
-  return builder;
-}
-
-class UnlinkedEnum {
+/**
+ * Unlinked summary information about an enum declaration.
+ */
+class UnlinkedEnum extends base.SummaryClass {
   String _name;
   List<UnlinkedEnumValue> _values;
 
@@ -470,7 +825,20 @@
     : _name = json["name"],
       _values = json["values"]?.map((x) => new UnlinkedEnumValue.fromJson(x))?.toList();
 
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "values": values,
+  };
+
+  /**
+   * Name of the enum type.
+   */
   String get name => _name ?? '';
+
+  /**
+   * Values listed in the enum declaration, in declaration order.
+   */
   List<UnlinkedEnumValue> get values => _values ?? const <UnlinkedEnumValue>[];
 }
 
@@ -479,8 +847,11 @@
 
   bool _finished = false;
 
-  UnlinkedEnumBuilder(builder.BuilderContext context);
+  UnlinkedEnumBuilder(base.BuilderContext context);
 
+  /**
+   * Name of the enum type.
+   */
   void set name(String _value) {
     assert(!_finished);
     assert(!_json.containsKey("name"));
@@ -489,10 +860,13 @@
     }
   }
 
+  /**
+   * Values listed in the enum declaration, in declaration order.
+   */
   void set values(List<UnlinkedEnumValueBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("values"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["values"] = _value.map((b) => b.finish()).toList();
     }
   }
@@ -504,19 +878,31 @@
   }
 }
 
-UnlinkedEnumBuilder encodeUnlinkedEnum(builder.BuilderContext builderContext, {String name, List<UnlinkedEnumValueBuilder> values}) {
+UnlinkedEnumBuilder encodeUnlinkedEnum(base.BuilderContext builderContext, {String name, List<UnlinkedEnumValueBuilder> values}) {
   UnlinkedEnumBuilder builder = new UnlinkedEnumBuilder(builderContext);
   builder.name = name;
   builder.values = values;
   return builder;
 }
 
-class UnlinkedEnumValue {
+/**
+ * Unlinked summary information about a single enumerated value in an enum
+ * declaration.
+ */
+class UnlinkedEnumValue extends base.SummaryClass {
   String _name;
 
   UnlinkedEnumValue.fromJson(Map json)
     : _name = json["name"];
 
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+  };
+
+  /**
+   * Name of the enumerated value.
+   */
   String get name => _name ?? '';
 }
 
@@ -525,8 +911,11 @@
 
   bool _finished = false;
 
-  UnlinkedEnumValueBuilder(builder.BuilderContext context);
+  UnlinkedEnumValueBuilder(base.BuilderContext context);
 
+  /**
+   * Name of the enumerated value.
+   */
   void set name(String _value) {
     assert(!_finished);
     assert(!_json.containsKey("name"));
@@ -542,13 +931,17 @@
   }
 }
 
-UnlinkedEnumValueBuilder encodeUnlinkedEnumValue(builder.BuilderContext builderContext, {String name}) {
+UnlinkedEnumValueBuilder encodeUnlinkedEnumValue(base.BuilderContext builderContext, {String name}) {
   UnlinkedEnumValueBuilder builder = new UnlinkedEnumValueBuilder(builderContext);
   builder.name = name;
   return builder;
 }
 
-class UnlinkedExecutable {
+/**
+ * Unlinked summary information about a function, method, getter, or setter
+ * declaration.
+ */
+class UnlinkedExecutable extends base.SummaryClass {
   String _name;
   List<UnlinkedTypeParam> _typeParameters;
   UnlinkedTypeRef _returnType;
@@ -574,16 +967,87 @@
       _hasImplicitReturnType = json["hasImplicitReturnType"],
       _isExternal = json["isExternal"];
 
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "typeParameters": typeParameters,
+    "returnType": returnType,
+    "parameters": parameters,
+    "kind": kind,
+    "isAbstract": isAbstract,
+    "isStatic": isStatic,
+    "isConst": isConst,
+    "isFactory": isFactory,
+    "hasImplicitReturnType": hasImplicitReturnType,
+    "isExternal": isExternal,
+  };
+
+  /**
+   * Name of the executable.  For setters, this includes the trailing "=".  For
+   * named constructors, this excludes the class name and excludes the ".".
+   * For unnamed constructors, this is the empty string.
+   */
   String get name => _name ?? '';
+
+  /**
+   * Type parameters of the executable, if any.  Empty if support for generic
+   * method syntax is disabled.
+   */
   List<UnlinkedTypeParam> get typeParameters => _typeParameters ?? const <UnlinkedTypeParam>[];
+
+  /**
+   * Declared return type of the executable.  Absent if the return type is
+   * `void`.  Note that when strong mode is enabled, the actual return type may
+   * be different due to type inference.
+   */
   UnlinkedTypeRef get returnType => _returnType;
+
+  /**
+   * Parameters of the executable, if any.  Note that getters have no
+   * parameters (hence this will be the empty list), and setters have a single
+   * parameter.
+   */
   List<UnlinkedParam> get parameters => _parameters ?? const <UnlinkedParam>[];
+
+  /**
+   * The kind of the executable (function/method, getter, setter, or
+   * constructor).
+   */
   UnlinkedExecutableKind get kind => _kind ?? UnlinkedExecutableKind.functionOrMethod;
+
+  /**
+   * Indicates whether the executable is declared using the `abstract` keyword.
+   */
   bool get isAbstract => _isAbstract ?? false;
+
+  /**
+   * Indicates whether the executable is declared using the `static` keyword.
+   *
+   * Note that for top level executables, this flag is false, since they are
+   * not declared using the `static` keyword (even though they are considered
+   * static for semantic purposes).
+   */
   bool get isStatic => _isStatic ?? false;
+
+  /**
+   * Indicates whether the executable is declared using the `const` keyword.
+   */
   bool get isConst => _isConst ?? false;
+
+  /**
+   * Indicates whether the executable is declared using the `factory` keyword.
+   */
   bool get isFactory => _isFactory ?? false;
+
+  /**
+   * Indicates whether the executable lacks an explicit return type
+   * declaration.  False for constructors and setters.
+   */
   bool get hasImplicitReturnType => _hasImplicitReturnType ?? false;
+
+  /**
+   * Indicates whether the executable is declared using the `external` keyword.
+   */
   bool get isExternal => _isExternal ?? false;
 }
 
@@ -592,8 +1056,13 @@
 
   bool _finished = false;
 
-  UnlinkedExecutableBuilder(builder.BuilderContext context);
+  UnlinkedExecutableBuilder(base.BuilderContext context);
 
+  /**
+   * Name of the executable.  For setters, this includes the trailing "=".  For
+   * named constructors, this excludes the class name and excludes the ".".
+   * For unnamed constructors, this is the empty string.
+   */
   void set name(String _value) {
     assert(!_finished);
     assert(!_json.containsKey("name"));
@@ -602,14 +1071,23 @@
     }
   }
 
+  /**
+   * Type parameters of the executable, if any.  Empty if support for generic
+   * method syntax is disabled.
+   */
   void set typeParameters(List<UnlinkedTypeParamBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("typeParameters"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["typeParameters"] = _value.map((b) => b.finish()).toList();
     }
   }
 
+  /**
+   * Declared return type of the executable.  Absent if the return type is
+   * `void`.  Note that when strong mode is enabled, the actual return type may
+   * be different due to type inference.
+   */
   void set returnType(UnlinkedTypeRefBuilder _value) {
     assert(!_finished);
     assert(!_json.containsKey("returnType"));
@@ -618,22 +1096,34 @@
     }
   }
 
+  /**
+   * Parameters of the executable, if any.  Note that getters have no
+   * parameters (hence this will be the empty list), and setters have a single
+   * parameter.
+   */
   void set parameters(List<UnlinkedParamBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("parameters"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["parameters"] = _value.map((b) => b.finish()).toList();
     }
   }
 
+  /**
+   * The kind of the executable (function/method, getter, setter, or
+   * constructor).
+   */
   void set kind(UnlinkedExecutableKind _value) {
     assert(!_finished);
     assert(!_json.containsKey("kind"));
-    if (_value != null || _value == UnlinkedExecutableKind.functionOrMethod) {
+    if (!(_value == null || _value == UnlinkedExecutableKind.functionOrMethod)) {
       _json["kind"] = _value.index;
     }
   }
 
+  /**
+   * Indicates whether the executable is declared using the `abstract` keyword.
+   */
   void set isAbstract(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("isAbstract"));
@@ -642,6 +1132,13 @@
     }
   }
 
+  /**
+   * Indicates whether the executable is declared using the `static` keyword.
+   *
+   * Note that for top level executables, this flag is false, since they are
+   * not declared using the `static` keyword (even though they are considered
+   * static for semantic purposes).
+   */
   void set isStatic(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("isStatic"));
@@ -650,6 +1147,9 @@
     }
   }
 
+  /**
+   * Indicates whether the executable is declared using the `const` keyword.
+   */
   void set isConst(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("isConst"));
@@ -658,6 +1158,9 @@
     }
   }
 
+  /**
+   * Indicates whether the executable is declared using the `factory` keyword.
+   */
   void set isFactory(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("isFactory"));
@@ -666,6 +1169,10 @@
     }
   }
 
+  /**
+   * Indicates whether the executable lacks an explicit return type
+   * declaration.  False for constructors and setters.
+   */
   void set hasImplicitReturnType(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("hasImplicitReturnType"));
@@ -674,6 +1181,9 @@
     }
   }
 
+  /**
+   * Indicates whether the executable is declared using the `external` keyword.
+   */
   void set isExternal(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("isExternal"));
@@ -689,7 +1199,7 @@
   }
 }
 
-UnlinkedExecutableBuilder encodeUnlinkedExecutable(builder.BuilderContext builderContext, {String name, List<UnlinkedTypeParamBuilder> typeParameters, UnlinkedTypeRefBuilder returnType, List<UnlinkedParamBuilder> parameters, UnlinkedExecutableKind kind, bool isAbstract, bool isStatic, bool isConst, bool isFactory, bool hasImplicitReturnType, bool isExternal}) {
+UnlinkedExecutableBuilder encodeUnlinkedExecutable(base.BuilderContext builderContext, {String name, List<UnlinkedTypeParamBuilder> typeParameters, UnlinkedTypeRefBuilder returnType, List<UnlinkedParamBuilder> parameters, UnlinkedExecutableKind kind, bool isAbstract, bool isStatic, bool isConst, bool isFactory, bool hasImplicitReturnType, bool isExternal}) {
   UnlinkedExecutableBuilder builder = new UnlinkedExecutableBuilder(builderContext);
   builder.name = name;
   builder.typeParameters = typeParameters;
@@ -705,7 +1215,10 @@
   return builder;
 }
 
-class UnlinkedExport {
+/**
+ * Unlinked summary information about an export declaration.
+ */
+class UnlinkedExport extends base.SummaryClass {
   String _uri;
   List<UnlinkedCombinator> _combinators;
 
@@ -713,7 +1226,20 @@
     : _uri = json["uri"],
       _combinators = json["combinators"]?.map((x) => new UnlinkedCombinator.fromJson(x))?.toList();
 
+  @override
+  Map<String, Object> toMap() => {
+    "uri": uri,
+    "combinators": combinators,
+  };
+
+  /**
+   * URI used in the source code to reference the exported library.
+   */
   String get uri => _uri ?? '';
+
+  /**
+   * Combinators contained in this import declaration.
+   */
   List<UnlinkedCombinator> get combinators => _combinators ?? const <UnlinkedCombinator>[];
 }
 
@@ -722,8 +1248,11 @@
 
   bool _finished = false;
 
-  UnlinkedExportBuilder(builder.BuilderContext context);
+  UnlinkedExportBuilder(base.BuilderContext context);
 
+  /**
+   * URI used in the source code to reference the exported library.
+   */
   void set uri(String _value) {
     assert(!_finished);
     assert(!_json.containsKey("uri"));
@@ -732,10 +1261,13 @@
     }
   }
 
+  /**
+   * Combinators contained in this import declaration.
+   */
   void set combinators(List<UnlinkedCombinatorBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("combinators"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["combinators"] = _value.map((b) => b.finish()).toList();
     }
   }
@@ -747,14 +1279,17 @@
   }
 }
 
-UnlinkedExportBuilder encodeUnlinkedExport(builder.BuilderContext builderContext, {String uri, List<UnlinkedCombinatorBuilder> combinators}) {
+UnlinkedExportBuilder encodeUnlinkedExport(base.BuilderContext builderContext, {String uri, List<UnlinkedCombinatorBuilder> combinators}) {
   UnlinkedExportBuilder builder = new UnlinkedExportBuilder(builderContext);
   builder.uri = uri;
   builder.combinators = combinators;
   return builder;
 }
 
-class UnlinkedImport {
+/**
+ * Unlinked summary information about an import declaration.
+ */
+class UnlinkedImport extends base.SummaryClass {
   String _uri;
   int _offset;
   int _prefixReference;
@@ -770,11 +1305,48 @@
       _isDeferred = json["isDeferred"],
       _isImplicit = json["isImplicit"];
 
+  @override
+  Map<String, Object> toMap() => {
+    "uri": uri,
+    "offset": offset,
+    "prefixReference": prefixReference,
+    "combinators": combinators,
+    "isDeferred": isDeferred,
+    "isImplicit": isImplicit,
+  };
+
+  /**
+   * URI used in the source code to reference the imported library.
+   */
   String get uri => _uri ?? '';
+
+  /**
+   * If [isImplicit] is false, offset of the "import" keyword.  If [isImplicit]
+   * is true, zero.
+   */
   int get offset => _offset ?? 0;
+
+  /**
+   * Index into [UnlinkedUnit.references] of the prefix declared by this
+   * import declaration, or zero if this import declaration declares no prefix.
+   *
+   * Note that multiple imports can declare the same prefix.
+   */
   int get prefixReference => _prefixReference ?? 0;
+
+  /**
+   * Combinators contained in this import declaration.
+   */
   List<UnlinkedCombinator> get combinators => _combinators ?? const <UnlinkedCombinator>[];
+
+  /**
+   * Indicates whether the import declaration uses the `deferred` keyword.
+   */
   bool get isDeferred => _isDeferred ?? false;
+
+  /**
+   * Indicates whether the import declaration is implicit.
+   */
   bool get isImplicit => _isImplicit ?? false;
 }
 
@@ -783,8 +1355,11 @@
 
   bool _finished = false;
 
-  UnlinkedImportBuilder(builder.BuilderContext context);
+  UnlinkedImportBuilder(base.BuilderContext context);
 
+  /**
+   * URI used in the source code to reference the imported library.
+   */
   void set uri(String _value) {
     assert(!_finished);
     assert(!_json.containsKey("uri"));
@@ -793,6 +1368,10 @@
     }
   }
 
+  /**
+   * If [isImplicit] is false, offset of the "import" keyword.  If [isImplicit]
+   * is true, zero.
+   */
   void set offset(int _value) {
     assert(!_finished);
     assert(!_json.containsKey("offset"));
@@ -801,6 +1380,12 @@
     }
   }
 
+  /**
+   * Index into [UnlinkedUnit.references] of the prefix declared by this
+   * import declaration, or zero if this import declaration declares no prefix.
+   *
+   * Note that multiple imports can declare the same prefix.
+   */
   void set prefixReference(int _value) {
     assert(!_finished);
     assert(!_json.containsKey("prefixReference"));
@@ -809,14 +1394,20 @@
     }
   }
 
+  /**
+   * Combinators contained in this import declaration.
+   */
   void set combinators(List<UnlinkedCombinatorBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("combinators"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["combinators"] = _value.map((b) => b.finish()).toList();
     }
   }
 
+  /**
+   * Indicates whether the import declaration uses the `deferred` keyword.
+   */
   void set isDeferred(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("isDeferred"));
@@ -825,6 +1416,9 @@
     }
   }
 
+  /**
+   * Indicates whether the import declaration is implicit.
+   */
   void set isImplicit(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("isImplicit"));
@@ -840,7 +1434,7 @@
   }
 }
 
-UnlinkedImportBuilder encodeUnlinkedImport(builder.BuilderContext builderContext, {String uri, int offset, int prefixReference, List<UnlinkedCombinatorBuilder> combinators, bool isDeferred, bool isImplicit}) {
+UnlinkedImportBuilder encodeUnlinkedImport(base.BuilderContext builderContext, {String uri, int offset, int prefixReference, List<UnlinkedCombinatorBuilder> combinators, bool isDeferred, bool isImplicit}) {
   UnlinkedImportBuilder builder = new UnlinkedImportBuilder(builderContext);
   builder.uri = uri;
   builder.offset = offset;
@@ -851,7 +1445,10 @@
   return builder;
 }
 
-class UnlinkedParam {
+/**
+ * Unlinked summary information about a function parameter.
+ */
+class UnlinkedParam extends base.SummaryClass {
   String _name;
   UnlinkedTypeRef _type;
   List<UnlinkedParam> _parameters;
@@ -869,12 +1466,56 @@
       _isInitializingFormal = json["isInitializingFormal"],
       _hasImplicitType = json["hasImplicitType"];
 
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "type": type,
+    "parameters": parameters,
+    "kind": kind,
+    "isFunctionTyped": isFunctionTyped,
+    "isInitializingFormal": isInitializingFormal,
+    "hasImplicitType": hasImplicitType,
+  };
+
+  /**
+   * Name of the parameter.
+   */
   String get name => _name ?? '';
+
+  /**
+   * If [isFunctionTyped] is `true`, the declared return type.  If
+   * [isFunctionTyped] is `false`, the declared type.  Absent if
+   * [isFunctionTyped] is `true` and the declared return type is `void`.  Note
+   * that when strong mode is enabled, the actual type may be different due to
+   * type inference.
+   */
   UnlinkedTypeRef get type => _type;
+
+  /**
+   * If [isFunctionTyped] is `true`, the parameters of the function type.
+   */
   List<UnlinkedParam> get parameters => _parameters ?? const <UnlinkedParam>[];
+
+  /**
+   * Kind of the parameter.
+   */
   UnlinkedParamKind get kind => _kind ?? UnlinkedParamKind.required;
+
+  /**
+   * Indicates whether this is a function-typed parameter.
+   */
   bool get isFunctionTyped => _isFunctionTyped ?? false;
+
+  /**
+   * Indicates whether this is an initializing formal parameter (i.e. it is
+   * declared using `this.` syntax).
+   */
   bool get isInitializingFormal => _isInitializingFormal ?? false;
+
+  /**
+   * Indicates whether this parameter lacks an explicit type declaration.
+   * Always false for a function-typed parameter.
+   */
   bool get hasImplicitType => _hasImplicitType ?? false;
 }
 
@@ -883,8 +1524,11 @@
 
   bool _finished = false;
 
-  UnlinkedParamBuilder(builder.BuilderContext context);
+  UnlinkedParamBuilder(base.BuilderContext context);
 
+  /**
+   * Name of the parameter.
+   */
   void set name(String _value) {
     assert(!_finished);
     assert(!_json.containsKey("name"));
@@ -893,6 +1537,13 @@
     }
   }
 
+  /**
+   * If [isFunctionTyped] is `true`, the declared return type.  If
+   * [isFunctionTyped] is `false`, the declared type.  Absent if
+   * [isFunctionTyped] is `true` and the declared return type is `void`.  Note
+   * that when strong mode is enabled, the actual type may be different due to
+   * type inference.
+   */
   void set type(UnlinkedTypeRefBuilder _value) {
     assert(!_finished);
     assert(!_json.containsKey("type"));
@@ -901,22 +1552,31 @@
     }
   }
 
+  /**
+   * If [isFunctionTyped] is `true`, the parameters of the function type.
+   */
   void set parameters(List<UnlinkedParamBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("parameters"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["parameters"] = _value.map((b) => b.finish()).toList();
     }
   }
 
+  /**
+   * Kind of the parameter.
+   */
   void set kind(UnlinkedParamKind _value) {
     assert(!_finished);
     assert(!_json.containsKey("kind"));
-    if (_value != null || _value == UnlinkedParamKind.required) {
+    if (!(_value == null || _value == UnlinkedParamKind.required)) {
       _json["kind"] = _value.index;
     }
   }
 
+  /**
+   * Indicates whether this is a function-typed parameter.
+   */
   void set isFunctionTyped(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("isFunctionTyped"));
@@ -925,6 +1585,10 @@
     }
   }
 
+  /**
+   * Indicates whether this is an initializing formal parameter (i.e. it is
+   * declared using `this.` syntax).
+   */
   void set isInitializingFormal(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("isInitializingFormal"));
@@ -933,6 +1597,10 @@
     }
   }
 
+  /**
+   * Indicates whether this parameter lacks an explicit type declaration.
+   * Always false for a function-typed parameter.
+   */
   void set hasImplicitType(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("hasImplicitType"));
@@ -948,7 +1616,7 @@
   }
 }
 
-UnlinkedParamBuilder encodeUnlinkedParam(builder.BuilderContext builderContext, {String name, UnlinkedTypeRefBuilder type, List<UnlinkedParamBuilder> parameters, UnlinkedParamKind kind, bool isFunctionTyped, bool isInitializingFormal, bool hasImplicitType}) {
+UnlinkedParamBuilder encodeUnlinkedParam(base.BuilderContext builderContext, {String name, UnlinkedTypeRefBuilder type, List<UnlinkedParamBuilder> parameters, UnlinkedParamKind kind, bool isFunctionTyped, bool isInitializingFormal, bool hasImplicitType}) {
   UnlinkedParamBuilder builder = new UnlinkedParamBuilder(builderContext);
   builder.name = name;
   builder.type = type;
@@ -960,12 +1628,23 @@
   return builder;
 }
 
-class UnlinkedPart {
+/**
+ * Unlinked summary information about a part declaration.
+ */
+class UnlinkedPart extends base.SummaryClass {
   String _uri;
 
   UnlinkedPart.fromJson(Map json)
     : _uri = json["uri"];
 
+  @override
+  Map<String, Object> toMap() => {
+    "uri": uri,
+  };
+
+  /**
+   * String used in the compilation unit to refer to the part file.
+   */
   String get uri => _uri ?? '';
 }
 
@@ -974,8 +1653,11 @@
 
   bool _finished = false;
 
-  UnlinkedPartBuilder(builder.BuilderContext context);
+  UnlinkedPartBuilder(base.BuilderContext context);
 
+  /**
+   * String used in the compilation unit to refer to the part file.
+   */
   void set uri(String _value) {
     assert(!_finished);
     assert(!_json.containsKey("uri"));
@@ -991,31 +1673,61 @@
   }
 }
 
-UnlinkedPartBuilder encodeUnlinkedPart(builder.BuilderContext builderContext, {String uri}) {
+UnlinkedPartBuilder encodeUnlinkedPart(base.BuilderContext builderContext, {String uri}) {
   UnlinkedPartBuilder builder = new UnlinkedPartBuilder(builderContext);
   builder.uri = uri;
   return builder;
 }
 
-class UnlinkedReference {
+/**
+ * Unlinked summary information about a specific name contributed by a
+ * compilation unit to a library's public namespace.
+ *
+ * TODO(paulberry): add a count of generic parameters, so that resynthesis
+ * doesn't have to peek into the library to obtain this info.
+ *
+ * TODO(paulberry): for classes, add info about static members and
+ * constructors, since this will be needed to prelink info about constants.
+ *
+ * TODO(paulberry): some of this information is redundant with information
+ * elsewhere in the summary.  Consider reducing the redundancy to reduce
+ * summary size.
+ */
+class UnlinkedPublicName extends base.SummaryClass {
   String _name;
-  int _prefixReference;
+  PrelinkedReferenceKind _kind;
 
-  UnlinkedReference.fromJson(Map json)
+  UnlinkedPublicName.fromJson(Map json)
     : _name = json["name"],
-      _prefixReference = json["prefixReference"];
+      _kind = json["kind"] == null ? null : PrelinkedReferenceKind.values[json["kind"]];
 
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "kind": kind,
+  };
+
+  /**
+   * The name itself.
+   */
   String get name => _name ?? '';
-  int get prefixReference => _prefixReference ?? 0;
+
+  /**
+   * The kind of object referred to by the name.
+   */
+  PrelinkedReferenceKind get kind => _kind ?? PrelinkedReferenceKind.classOrEnum;
 }
 
-class UnlinkedReferenceBuilder {
+class UnlinkedPublicNameBuilder {
   final Map _json = {};
 
   bool _finished = false;
 
-  UnlinkedReferenceBuilder(builder.BuilderContext context);
+  UnlinkedPublicNameBuilder(base.BuilderContext context);
 
+  /**
+   * The name itself.
+   */
   void set name(String _value) {
     assert(!_finished);
     assert(!_json.containsKey("name"));
@@ -1024,6 +1736,188 @@
     }
   }
 
+  /**
+   * The kind of object referred to by the name.
+   */
+  void set kind(PrelinkedReferenceKind _value) {
+    assert(!_finished);
+    assert(!_json.containsKey("kind"));
+    if (!(_value == null || _value == PrelinkedReferenceKind.classOrEnum)) {
+      _json["kind"] = _value.index;
+    }
+  }
+
+  Map finish() {
+    assert(!_finished);
+    _finished = true;
+    return _json;
+  }
+}
+
+UnlinkedPublicNameBuilder encodeUnlinkedPublicName(base.BuilderContext builderContext, {String name, PrelinkedReferenceKind kind}) {
+  UnlinkedPublicNameBuilder builder = new UnlinkedPublicNameBuilder(builderContext);
+  builder.name = name;
+  builder.kind = kind;
+  return builder;
+}
+
+/**
+ * Unlinked summary information about what a compilation unit contributes to a
+ * library's public namespace.  This is the subset of [UnlinkedUnit] that is
+ * required from dependent libraries in order to perform prelinking.
+ */
+class UnlinkedPublicNamespace extends base.SummaryClass {
+  List<UnlinkedPublicName> _names;
+  List<UnlinkedExport> _exports;
+  List<UnlinkedPart> _parts;
+
+  UnlinkedPublicNamespace.fromJson(Map json)
+    : _names = json["names"]?.map((x) => new UnlinkedPublicName.fromJson(x))?.toList(),
+      _exports = json["exports"]?.map((x) => new UnlinkedExport.fromJson(x))?.toList(),
+      _parts = json["parts"]?.map((x) => new UnlinkedPart.fromJson(x))?.toList();
+
+  @override
+  Map<String, Object> toMap() => {
+    "names": names,
+    "exports": exports,
+    "parts": parts,
+  };
+
+  UnlinkedPublicNamespace.fromBuffer(List<int> buffer) : this.fromJson(JSON.decode(UTF8.decode(buffer)));
+
+  /**
+   * Public names defined in the compilation unit.
+   *
+   * TODO(paulberry): consider sorting these names to reduce unnecessary
+   * relinking.
+   */
+  List<UnlinkedPublicName> get names => _names ?? const <UnlinkedPublicName>[];
+
+  /**
+   * Export declarations in the compilation unit.
+   */
+  List<UnlinkedExport> get exports => _exports ?? const <UnlinkedExport>[];
+
+  /**
+   * Part declarations in the compilation unit.
+   */
+  List<UnlinkedPart> get parts => _parts ?? const <UnlinkedPart>[];
+}
+
+class UnlinkedPublicNamespaceBuilder {
+  final Map _json = {};
+
+  bool _finished = false;
+
+  UnlinkedPublicNamespaceBuilder(base.BuilderContext context);
+
+  /**
+   * Public names defined in the compilation unit.
+   *
+   * TODO(paulberry): consider sorting these names to reduce unnecessary
+   * relinking.
+   */
+  void set names(List<UnlinkedPublicNameBuilder> _value) {
+    assert(!_finished);
+    assert(!_json.containsKey("names"));
+    if (!(_value == null || _value.isEmpty)) {
+      _json["names"] = _value.map((b) => b.finish()).toList();
+    }
+  }
+
+  /**
+   * Export declarations in the compilation unit.
+   */
+  void set exports(List<UnlinkedExportBuilder> _value) {
+    assert(!_finished);
+    assert(!_json.containsKey("exports"));
+    if (!(_value == null || _value.isEmpty)) {
+      _json["exports"] = _value.map((b) => b.finish()).toList();
+    }
+  }
+
+  /**
+   * Part declarations in the compilation unit.
+   */
+  void set parts(List<UnlinkedPartBuilder> _value) {
+    assert(!_finished);
+    assert(!_json.containsKey("parts"));
+    if (!(_value == null || _value.isEmpty)) {
+      _json["parts"] = _value.map((b) => b.finish()).toList();
+    }
+  }
+
+  List<int> toBuffer() => UTF8.encode(JSON.encode(finish()));
+
+  Map finish() {
+    assert(!_finished);
+    _finished = true;
+    return _json;
+  }
+}
+
+UnlinkedPublicNamespaceBuilder encodeUnlinkedPublicNamespace(base.BuilderContext builderContext, {List<UnlinkedPublicNameBuilder> names, List<UnlinkedExportBuilder> exports, List<UnlinkedPartBuilder> parts}) {
+  UnlinkedPublicNamespaceBuilder builder = new UnlinkedPublicNamespaceBuilder(builderContext);
+  builder.names = names;
+  builder.exports = exports;
+  builder.parts = parts;
+  return builder;
+}
+
+/**
+ * Unlinked summary information about a name referred to in one library that
+ * might be defined in another.
+ */
+class UnlinkedReference extends base.SummaryClass {
+  String _name;
+  int _prefixReference;
+
+  UnlinkedReference.fromJson(Map json)
+    : _name = json["name"],
+      _prefixReference = json["prefixReference"];
+
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "prefixReference": prefixReference,
+  };
+
+  /**
+   * Name of the entity being referred to.  The empty string refers to the
+   * pseudo-type `dynamic`.
+   */
+  String get name => _name ?? '';
+
+  /**
+   * Prefix used to refer to the entity, or zero if no prefix is used.  This is
+   * an index into [UnlinkedUnit.references].
+   */
+  int get prefixReference => _prefixReference ?? 0;
+}
+
+class UnlinkedReferenceBuilder {
+  final Map _json = {};
+
+  bool _finished = false;
+
+  UnlinkedReferenceBuilder(base.BuilderContext context);
+
+  /**
+   * Name of the entity being referred to.  The empty string refers to the
+   * pseudo-type `dynamic`.
+   */
+  void set name(String _value) {
+    assert(!_finished);
+    assert(!_json.containsKey("name"));
+    if (_value != null) {
+      _json["name"] = _value;
+    }
+  }
+
+  /**
+   * Prefix used to refer to the entity, or zero if no prefix is used.  This is
+   * an index into [UnlinkedUnit.references].
+   */
   void set prefixReference(int _value) {
     assert(!_finished);
     assert(!_json.containsKey("prefixReference"));
@@ -1039,14 +1933,17 @@
   }
 }
 
-UnlinkedReferenceBuilder encodeUnlinkedReference(builder.BuilderContext builderContext, {String name, int prefixReference}) {
+UnlinkedReferenceBuilder encodeUnlinkedReference(base.BuilderContext builderContext, {String name, int prefixReference}) {
   UnlinkedReferenceBuilder builder = new UnlinkedReferenceBuilder(builderContext);
   builder.name = name;
   builder.prefixReference = prefixReference;
   return builder;
 }
 
-class UnlinkedTypedef {
+/**
+ * Unlinked summary information about a typedef declaration.
+ */
+class UnlinkedTypedef extends base.SummaryClass {
   String _name;
   List<UnlinkedTypeParam> _typeParameters;
   UnlinkedTypeRef _returnType;
@@ -1058,9 +1955,32 @@
       _returnType = json["returnType"] == null ? null : new UnlinkedTypeRef.fromJson(json["returnType"]),
       _parameters = json["parameters"]?.map((x) => new UnlinkedParam.fromJson(x))?.toList();
 
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "typeParameters": typeParameters,
+    "returnType": returnType,
+    "parameters": parameters,
+  };
+
+  /**
+   * Name of the typedef.
+   */
   String get name => _name ?? '';
+
+  /**
+   * Type parameters of the typedef, if any.
+   */
   List<UnlinkedTypeParam> get typeParameters => _typeParameters ?? const <UnlinkedTypeParam>[];
+
+  /**
+   * Return type of the typedef.  Absent if the return type is `void`.
+   */
   UnlinkedTypeRef get returnType => _returnType;
+
+  /**
+   * Parameters of the executable, if any.
+   */
   List<UnlinkedParam> get parameters => _parameters ?? const <UnlinkedParam>[];
 }
 
@@ -1069,8 +1989,11 @@
 
   bool _finished = false;
 
-  UnlinkedTypedefBuilder(builder.BuilderContext context);
+  UnlinkedTypedefBuilder(base.BuilderContext context);
 
+  /**
+   * Name of the typedef.
+   */
   void set name(String _value) {
     assert(!_finished);
     assert(!_json.containsKey("name"));
@@ -1079,14 +2002,20 @@
     }
   }
 
+  /**
+   * Type parameters of the typedef, if any.
+   */
   void set typeParameters(List<UnlinkedTypeParamBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("typeParameters"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["typeParameters"] = _value.map((b) => b.finish()).toList();
     }
   }
 
+  /**
+   * Return type of the typedef.  Absent if the return type is `void`.
+   */
   void set returnType(UnlinkedTypeRefBuilder _value) {
     assert(!_finished);
     assert(!_json.containsKey("returnType"));
@@ -1095,10 +2024,13 @@
     }
   }
 
+  /**
+   * Parameters of the executable, if any.
+   */
   void set parameters(List<UnlinkedParamBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("parameters"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["parameters"] = _value.map((b) => b.finish()).toList();
     }
   }
@@ -1110,7 +2042,7 @@
   }
 }
 
-UnlinkedTypedefBuilder encodeUnlinkedTypedef(builder.BuilderContext builderContext, {String name, List<UnlinkedTypeParamBuilder> typeParameters, UnlinkedTypeRefBuilder returnType, List<UnlinkedParamBuilder> parameters}) {
+UnlinkedTypedefBuilder encodeUnlinkedTypedef(base.BuilderContext builderContext, {String name, List<UnlinkedTypeParamBuilder> typeParameters, UnlinkedTypeRefBuilder returnType, List<UnlinkedParamBuilder> parameters}) {
   UnlinkedTypedefBuilder builder = new UnlinkedTypedefBuilder(builderContext);
   builder.name = name;
   builder.typeParameters = typeParameters;
@@ -1119,7 +2051,10 @@
   return builder;
 }
 
-class UnlinkedTypeParam {
+/**
+ * Unlinked summary information about a type parameter declaration.
+ */
+class UnlinkedTypeParam extends base.SummaryClass {
   String _name;
   UnlinkedTypeRef _bound;
 
@@ -1127,7 +2062,21 @@
     : _name = json["name"],
       _bound = json["bound"] == null ? null : new UnlinkedTypeRef.fromJson(json["bound"]);
 
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "bound": bound,
+  };
+
+  /**
+   * Name of the type parameter.
+   */
   String get name => _name ?? '';
+
+  /**
+   * Bound of the type parameter, if a bound is explicitly declared.  Otherwise
+   * null.
+   */
   UnlinkedTypeRef get bound => _bound;
 }
 
@@ -1136,8 +2085,11 @@
 
   bool _finished = false;
 
-  UnlinkedTypeParamBuilder(builder.BuilderContext context);
+  UnlinkedTypeParamBuilder(base.BuilderContext context);
 
+  /**
+   * Name of the type parameter.
+   */
   void set name(String _value) {
     assert(!_finished);
     assert(!_json.containsKey("name"));
@@ -1146,6 +2098,10 @@
     }
   }
 
+  /**
+   * Bound of the type parameter, if a bound is explicitly declared.  Otherwise
+   * null.
+   */
   void set bound(UnlinkedTypeRefBuilder _value) {
     assert(!_finished);
     assert(!_json.containsKey("bound"));
@@ -1161,14 +2117,17 @@
   }
 }
 
-UnlinkedTypeParamBuilder encodeUnlinkedTypeParam(builder.BuilderContext builderContext, {String name, UnlinkedTypeRefBuilder bound}) {
+UnlinkedTypeParamBuilder encodeUnlinkedTypeParam(base.BuilderContext builderContext, {String name, UnlinkedTypeRefBuilder bound}) {
   UnlinkedTypeParamBuilder builder = new UnlinkedTypeParamBuilder(builderContext);
   builder.name = name;
   builder.bound = bound;
   return builder;
 }
 
-class UnlinkedTypeRef {
+/**
+ * Unlinked summary information about a reference to a type.
+ */
+class UnlinkedTypeRef extends base.SummaryClass {
   int _reference;
   int _paramReference;
   List<UnlinkedTypeRef> _typeArguments;
@@ -1178,8 +2137,50 @@
       _paramReference = json["paramReference"],
       _typeArguments = json["typeArguments"]?.map((x) => new UnlinkedTypeRef.fromJson(x))?.toList();
 
+  @override
+  Map<String, Object> toMap() => {
+    "reference": reference,
+    "paramReference": paramReference,
+    "typeArguments": typeArguments,
+  };
+
+  /**
+   * Index into [UnlinkedUnit.references] for the type being referred to, or
+   * zero if this is a reference to a type parameter.
+   *
+   * Note that since zero is also a valid index into
+   * [UnlinkedUnit.references], we cannot distinguish between references to
+   * type parameters and references to types by checking [reference] against
+   * zero.  To distinguish between references to type parameters and references
+   * to types, check whether [paramReference] is zero.
+   */
   int get reference => _reference ?? 0;
+
+  /**
+   * If this is a reference to a type parameter, one-based index into the list
+   * of [UnlinkedTypeParam]s currently in effect.  Indexing is done using De
+   * Bruijn index conventions; that is, innermost parameters come first, and
+   * if a class or method has multiple parameters, they are indexed from right
+   * to left.  So for instance, if the enclosing declaration is
+   *
+   *     class C<T,U> {
+   *       m<V,W> {
+   *         ...
+   *       }
+   *     }
+   *
+   * Then [paramReference] values of 1, 2, 3, and 4 represent W, V, U, and T,
+   * respectively.
+   *
+   * If the type being referred to is not a type parameter, [paramReference] is
+   * zero.
+   */
   int get paramReference => _paramReference ?? 0;
+
+  /**
+   * If this is an instantiation of a generic type, the type arguments used to
+   * instantiate it.  Trailing type arguments of type `dynamic` are omitted.
+   */
   List<UnlinkedTypeRef> get typeArguments => _typeArguments ?? const <UnlinkedTypeRef>[];
 }
 
@@ -1188,8 +2189,18 @@
 
   bool _finished = false;
 
-  UnlinkedTypeRefBuilder(builder.BuilderContext context);
+  UnlinkedTypeRefBuilder(base.BuilderContext context);
 
+  /**
+   * Index into [UnlinkedUnit.references] for the type being referred to, or
+   * zero if this is a reference to a type parameter.
+   *
+   * Note that since zero is also a valid index into
+   * [UnlinkedUnit.references], we cannot distinguish between references to
+   * type parameters and references to types by checking [reference] against
+   * zero.  To distinguish between references to type parameters and references
+   * to types, check whether [paramReference] is zero.
+   */
   void set reference(int _value) {
     assert(!_finished);
     assert(!_json.containsKey("reference"));
@@ -1198,6 +2209,25 @@
     }
   }
 
+  /**
+   * If this is a reference to a type parameter, one-based index into the list
+   * of [UnlinkedTypeParam]s currently in effect.  Indexing is done using De
+   * Bruijn index conventions; that is, innermost parameters come first, and
+   * if a class or method has multiple parameters, they are indexed from right
+   * to left.  So for instance, if the enclosing declaration is
+   *
+   *     class C<T,U> {
+   *       m<V,W> {
+   *         ...
+   *       }
+   *     }
+   *
+   * Then [paramReference] values of 1, 2, 3, and 4 represent W, V, U, and T,
+   * respectively.
+   *
+   * If the type being referred to is not a type parameter, [paramReference] is
+   * zero.
+   */
   void set paramReference(int _value) {
     assert(!_finished);
     assert(!_json.containsKey("paramReference"));
@@ -1206,10 +2236,14 @@
     }
   }
 
+  /**
+   * If this is an instantiation of a generic type, the type arguments used to
+   * instantiate it.  Trailing type arguments of type `dynamic` are omitted.
+   */
   void set typeArguments(List<UnlinkedTypeRefBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("typeArguments"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["typeArguments"] = _value.map((b) => b.finish()).toList();
     }
   }
@@ -1221,7 +2255,7 @@
   }
 }
 
-UnlinkedTypeRefBuilder encodeUnlinkedTypeRef(builder.BuilderContext builderContext, {int reference, int paramReference, List<UnlinkedTypeRefBuilder> typeArguments}) {
+UnlinkedTypeRefBuilder encodeUnlinkedTypeRef(base.BuilderContext builderContext, {int reference, int paramReference, List<UnlinkedTypeRefBuilder> typeArguments}) {
   UnlinkedTypeRefBuilder builder = new UnlinkedTypeRefBuilder(builderContext);
   builder.reference = reference;
   builder.paramReference = paramReference;
@@ -1229,41 +2263,92 @@
   return builder;
 }
 
-class UnlinkedUnit {
+/**
+ * Unlinked summary information about a compilation unit ("part file").
+ */
+class UnlinkedUnit extends base.SummaryClass {
   String _libraryName;
+  UnlinkedPublicNamespace _publicNamespace;
   List<UnlinkedReference> _references;
   List<UnlinkedClass> _classes;
   List<UnlinkedEnum> _enums;
   List<UnlinkedExecutable> _executables;
-  List<UnlinkedExport> _exports;
   List<UnlinkedImport> _imports;
-  List<UnlinkedPart> _parts;
   List<UnlinkedTypedef> _typedefs;
   List<UnlinkedVariable> _variables;
 
   UnlinkedUnit.fromJson(Map json)
     : _libraryName = json["libraryName"],
+      _publicNamespace = json["publicNamespace"] == null ? null : new UnlinkedPublicNamespace.fromJson(json["publicNamespace"]),
       _references = json["references"]?.map((x) => new UnlinkedReference.fromJson(x))?.toList(),
       _classes = json["classes"]?.map((x) => new UnlinkedClass.fromJson(x))?.toList(),
       _enums = json["enums"]?.map((x) => new UnlinkedEnum.fromJson(x))?.toList(),
       _executables = json["executables"]?.map((x) => new UnlinkedExecutable.fromJson(x))?.toList(),
-      _exports = json["exports"]?.map((x) => new UnlinkedExport.fromJson(x))?.toList(),
       _imports = json["imports"]?.map((x) => new UnlinkedImport.fromJson(x))?.toList(),
-      _parts = json["parts"]?.map((x) => new UnlinkedPart.fromJson(x))?.toList(),
       _typedefs = json["typedefs"]?.map((x) => new UnlinkedTypedef.fromJson(x))?.toList(),
       _variables = json["variables"]?.map((x) => new UnlinkedVariable.fromJson(x))?.toList();
 
+  @override
+  Map<String, Object> toMap() => {
+    "libraryName": libraryName,
+    "publicNamespace": publicNamespace,
+    "references": references,
+    "classes": classes,
+    "enums": enums,
+    "executables": executables,
+    "imports": imports,
+    "typedefs": typedefs,
+    "variables": variables,
+  };
+
   UnlinkedUnit.fromBuffer(List<int> buffer) : this.fromJson(JSON.decode(UTF8.decode(buffer)));
 
+  /**
+   * Name of the library (from a "library" declaration, if present).
+   */
   String get libraryName => _libraryName ?? '';
+
+  /**
+   * Unlinked public namespace of this compilation unit.
+   */
+  UnlinkedPublicNamespace get publicNamespace => _publicNamespace;
+
+  /**
+   * Top level and prefixed names referred to by this compilation unit.  The
+   * zeroth element of this array is always populated and always represents a
+   * reference to the pseudo-type "dynamic".
+   */
   List<UnlinkedReference> get references => _references ?? const <UnlinkedReference>[];
+
+  /**
+   * Classes declared in the compilation unit.
+   */
   List<UnlinkedClass> get classes => _classes ?? const <UnlinkedClass>[];
+
+  /**
+   * Enums declared in the compilation unit.
+   */
   List<UnlinkedEnum> get enums => _enums ?? const <UnlinkedEnum>[];
+
+  /**
+   * Top level executable objects (functions, getters, and setters) declared in
+   * the compilation unit.
+   */
   List<UnlinkedExecutable> get executables => _executables ?? const <UnlinkedExecutable>[];
-  List<UnlinkedExport> get exports => _exports ?? const <UnlinkedExport>[];
+
+  /**
+   * Import declarations in the compilation unit.
+   */
   List<UnlinkedImport> get imports => _imports ?? const <UnlinkedImport>[];
-  List<UnlinkedPart> get parts => _parts ?? const <UnlinkedPart>[];
+
+  /**
+   * Typedefs declared in the compilation unit.
+   */
   List<UnlinkedTypedef> get typedefs => _typedefs ?? const <UnlinkedTypedef>[];
+
+  /**
+   * Top level variables declared in the compilation unit.
+   */
   List<UnlinkedVariable> get variables => _variables ?? const <UnlinkedVariable>[];
 }
 
@@ -1272,8 +2357,11 @@
 
   bool _finished = false;
 
-  UnlinkedUnitBuilder(builder.BuilderContext context);
+  UnlinkedUnitBuilder(base.BuilderContext context);
 
+  /**
+   * Name of the library (from a "library" declaration, if present).
+   */
   void set libraryName(String _value) {
     assert(!_finished);
     assert(!_json.containsKey("libraryName"));
@@ -1282,74 +2370,93 @@
     }
   }
 
+  /**
+   * Unlinked public namespace of this compilation unit.
+   */
+  void set publicNamespace(UnlinkedPublicNamespaceBuilder _value) {
+    assert(!_finished);
+    assert(!_json.containsKey("publicNamespace"));
+    if (_value != null) {
+      _json["publicNamespace"] = _value.finish();
+    }
+  }
+
+  /**
+   * Top level and prefixed names referred to by this compilation unit.  The
+   * zeroth element of this array is always populated and always represents a
+   * reference to the pseudo-type "dynamic".
+   */
   void set references(List<UnlinkedReferenceBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("references"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["references"] = _value.map((b) => b.finish()).toList();
     }
   }
 
+  /**
+   * Classes declared in the compilation unit.
+   */
   void set classes(List<UnlinkedClassBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("classes"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["classes"] = _value.map((b) => b.finish()).toList();
     }
   }
 
+  /**
+   * Enums declared in the compilation unit.
+   */
   void set enums(List<UnlinkedEnumBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("enums"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["enums"] = _value.map((b) => b.finish()).toList();
     }
   }
 
+  /**
+   * Top level executable objects (functions, getters, and setters) declared in
+   * the compilation unit.
+   */
   void set executables(List<UnlinkedExecutableBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("executables"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["executables"] = _value.map((b) => b.finish()).toList();
     }
   }
 
-  void set exports(List<UnlinkedExportBuilder> _value) {
-    assert(!_finished);
-    assert(!_json.containsKey("exports"));
-    if (_value != null || _value.isEmpty) {
-      _json["exports"] = _value.map((b) => b.finish()).toList();
-    }
-  }
-
+  /**
+   * Import declarations in the compilation unit.
+   */
   void set imports(List<UnlinkedImportBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("imports"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["imports"] = _value.map((b) => b.finish()).toList();
     }
   }
 
-  void set parts(List<UnlinkedPartBuilder> _value) {
-    assert(!_finished);
-    assert(!_json.containsKey("parts"));
-    if (_value != null || _value.isEmpty) {
-      _json["parts"] = _value.map((b) => b.finish()).toList();
-    }
-  }
-
+  /**
+   * Typedefs declared in the compilation unit.
+   */
   void set typedefs(List<UnlinkedTypedefBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("typedefs"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["typedefs"] = _value.map((b) => b.finish()).toList();
     }
   }
 
+  /**
+   * Top level variables declared in the compilation unit.
+   */
   void set variables(List<UnlinkedVariableBuilder> _value) {
     assert(!_finished);
     assert(!_json.containsKey("variables"));
-    if (_value != null || _value.isEmpty) {
+    if (!(_value == null || _value.isEmpty)) {
       _json["variables"] = _value.map((b) => b.finish()).toList();
     }
   }
@@ -1363,22 +2470,25 @@
   }
 }
 
-UnlinkedUnitBuilder encodeUnlinkedUnit(builder.BuilderContext builderContext, {String libraryName, List<UnlinkedReferenceBuilder> references, List<UnlinkedClassBuilder> classes, List<UnlinkedEnumBuilder> enums, List<UnlinkedExecutableBuilder> executables, List<UnlinkedExportBuilder> exports, List<UnlinkedImportBuilder> imports, List<UnlinkedPartBuilder> parts, List<UnlinkedTypedefBuilder> typedefs, List<UnlinkedVariableBuilder> variables}) {
+UnlinkedUnitBuilder encodeUnlinkedUnit(base.BuilderContext builderContext, {String libraryName, UnlinkedPublicNamespaceBuilder publicNamespace, List<UnlinkedReferenceBuilder> references, List<UnlinkedClassBuilder> classes, List<UnlinkedEnumBuilder> enums, List<UnlinkedExecutableBuilder> executables, List<UnlinkedImportBuilder> imports, List<UnlinkedTypedefBuilder> typedefs, List<UnlinkedVariableBuilder> variables}) {
   UnlinkedUnitBuilder builder = new UnlinkedUnitBuilder(builderContext);
   builder.libraryName = libraryName;
+  builder.publicNamespace = publicNamespace;
   builder.references = references;
   builder.classes = classes;
   builder.enums = enums;
   builder.executables = executables;
-  builder.exports = exports;
   builder.imports = imports;
-  builder.parts = parts;
   builder.typedefs = typedefs;
   builder.variables = variables;
   return builder;
 }
 
-class UnlinkedVariable {
+/**
+ * Unlinked summary information about a top level variable, local variable, or
+ * a field.
+ */
+class UnlinkedVariable extends base.SummaryClass {
   String _name;
   UnlinkedTypeRef _type;
   bool _isStatic;
@@ -1394,11 +2504,49 @@
       _isConst = json["isConst"],
       _hasImplicitType = json["hasImplicitType"];
 
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "type": type,
+    "isStatic": isStatic,
+    "isFinal": isFinal,
+    "isConst": isConst,
+    "hasImplicitType": hasImplicitType,
+  };
+
+  /**
+   * Name of the variable.
+   */
   String get name => _name ?? '';
+
+  /**
+   * Declared type of the variable.  Note that when strong mode is enabled, the
+   * actual type of the variable may be different due to type inference.
+   */
   UnlinkedTypeRef get type => _type;
+
+  /**
+   * Indicates whether the variable is declared using the `static` keyword.
+   *
+   * Note that for top level variables, this flag is false, since they are not
+   * declared using the `static` keyword (even though they are considered
+   * static for semantic purposes).
+   */
   bool get isStatic => _isStatic ?? false;
+
+  /**
+   * Indicates whether the variable is declared using the `final` keyword.
+   */
   bool get isFinal => _isFinal ?? false;
+
+  /**
+   * Indicates whether the variable is declared using the `const` keyword.
+   */
   bool get isConst => _isConst ?? false;
+
+  /**
+   * Indicates whether this variable lacks an explicit type declaration.
+   */
   bool get hasImplicitType => _hasImplicitType ?? false;
 }
 
@@ -1407,8 +2555,11 @@
 
   bool _finished = false;
 
-  UnlinkedVariableBuilder(builder.BuilderContext context);
+  UnlinkedVariableBuilder(base.BuilderContext context);
 
+  /**
+   * Name of the variable.
+   */
   void set name(String _value) {
     assert(!_finished);
     assert(!_json.containsKey("name"));
@@ -1417,6 +2568,10 @@
     }
   }
 
+  /**
+   * Declared type of the variable.  Note that when strong mode is enabled, the
+   * actual type of the variable may be different due to type inference.
+   */
   void set type(UnlinkedTypeRefBuilder _value) {
     assert(!_finished);
     assert(!_json.containsKey("type"));
@@ -1425,6 +2580,13 @@
     }
   }
 
+  /**
+   * Indicates whether the variable is declared using the `static` keyword.
+   *
+   * Note that for top level variables, this flag is false, since they are not
+   * declared using the `static` keyword (even though they are considered
+   * static for semantic purposes).
+   */
   void set isStatic(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("isStatic"));
@@ -1433,6 +2595,9 @@
     }
   }
 
+  /**
+   * Indicates whether the variable is declared using the `final` keyword.
+   */
   void set isFinal(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("isFinal"));
@@ -1441,6 +2606,9 @@
     }
   }
 
+  /**
+   * Indicates whether the variable is declared using the `const` keyword.
+   */
   void set isConst(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("isConst"));
@@ -1449,6 +2617,9 @@
     }
   }
 
+  /**
+   * Indicates whether this variable lacks an explicit type declaration.
+   */
   void set hasImplicitType(bool _value) {
     assert(!_finished);
     assert(!_json.containsKey("hasImplicitType"));
@@ -1464,7 +2635,7 @@
   }
 }
 
-UnlinkedVariableBuilder encodeUnlinkedVariable(builder.BuilderContext builderContext, {String name, UnlinkedTypeRefBuilder type, bool isStatic, bool isFinal, bool isConst, bool hasImplicitType}) {
+UnlinkedVariableBuilder encodeUnlinkedVariable(base.BuilderContext builderContext, {String name, UnlinkedTypeRefBuilder type, bool isStatic, bool isFinal, bool isConst, bool hasImplicitType}) {
   UnlinkedVariableBuilder builder = new UnlinkedVariableBuilder(builderContext);
   builder.name = name;
   builder.type = type;
diff --git a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
new file mode 100644
index 0000000..bd9e3a2
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
@@ -0,0 +1,109 @@
+// 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.summary.public_namespace_visitor;
+
+import 'package:analyzer/analyzer.dart';
+import 'package:analyzer/src/summary/base.dart';
+import 'package:analyzer/src/summary/format.dart';
+
+/**
+ * Compute the public namespace portion of the summary for the given [unit],
+ * which is presumed to be an unresolved AST.
+ */
+UnlinkedPublicNamespaceBuilder computePublicNamespace(
+    BuilderContext ctx, CompilationUnit unit) {
+  _PublicNamespaceVisitor visitor = new _PublicNamespaceVisitor(ctx);
+  unit.accept(visitor);
+  return encodeUnlinkedPublicNamespace(ctx,
+      names: visitor.names, exports: visitor.exports, parts: visitor.parts);
+}
+
+class _CombinatorEncoder extends SimpleAstVisitor<UnlinkedCombinatorBuilder> {
+  final BuilderContext ctx;
+
+  _CombinatorEncoder(this.ctx);
+
+  List<String> encodeNames(NodeList<SimpleIdentifier> names) =>
+      names.map((SimpleIdentifier id) => id.name).toList();
+
+  @override
+  UnlinkedCombinatorBuilder visitHideCombinator(HideCombinator node) {
+    return encodeUnlinkedCombinator(ctx, hides: encodeNames(node.hiddenNames));
+  }
+
+  @override
+  UnlinkedCombinatorBuilder visitShowCombinator(ShowCombinator node) {
+    return encodeUnlinkedCombinator(ctx, shows: encodeNames(node.shownNames));
+  }
+}
+
+class _PublicNamespaceVisitor extends RecursiveAstVisitor {
+  final BuilderContext ctx;
+  final List<UnlinkedPublicNameBuilder> names = <UnlinkedPublicNameBuilder>[];
+  final List<UnlinkedExportBuilder> exports = <UnlinkedExportBuilder>[];
+  final List<UnlinkedPartBuilder> parts = <UnlinkedPartBuilder>[];
+
+  _PublicNamespaceVisitor(this.ctx);
+
+  void addNameIfPublic(String name, PrelinkedReferenceKind kind) {
+    if (isPublic(name)) {
+      names.add(encodeUnlinkedPublicName(ctx, name: name, kind: kind));
+    }
+  }
+
+  bool isPublic(String name) => !name.startsWith('_');
+
+  @override
+  visitClassDeclaration(ClassDeclaration node) {
+    addNameIfPublic(node.name.name, PrelinkedReferenceKind.classOrEnum);
+  }
+
+  @override
+  visitClassTypeAlias(ClassTypeAlias node) {
+    addNameIfPublic(node.name.name, PrelinkedReferenceKind.classOrEnum);
+  }
+
+  @override
+  visitEnumDeclaration(EnumDeclaration node) {
+    addNameIfPublic(node.name.name, PrelinkedReferenceKind.classOrEnum);
+  }
+
+  @override
+  visitExportDirective(ExportDirective node) {
+    exports.add(encodeUnlinkedExport(ctx,
+        uri: node.uri.stringValue,
+        combinators: node.combinators
+            .map((Combinator c) => c.accept(new _CombinatorEncoder(ctx)))
+            .toList()));
+  }
+
+  @override
+  visitFunctionDeclaration(FunctionDeclaration node) {
+    String name = node.name.name;
+    if (node.isSetter) {
+      name += '=';
+    }
+    addNameIfPublic(name, PrelinkedReferenceKind.other);
+  }
+
+  @override
+  visitFunctionTypeAlias(FunctionTypeAlias node) {
+    addNameIfPublic(node.name.name, PrelinkedReferenceKind.typedef);
+  }
+
+  @override
+  visitPartDirective(PartDirective node) {
+    parts.add(encodeUnlinkedPart(ctx, uri: node.uri.stringValue));
+  }
+
+  @override
+  visitVariableDeclaration(VariableDeclaration node) {
+    String name = node.name.name;
+    addNameIfPublic(name, PrelinkedReferenceKind.other);
+    if (!node.isFinal && !node.isConst) {
+      addNameIfPublic('$name=', PrelinkedReferenceKind.other);
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 719c2f8..e83b661 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -25,66 +25,6 @@
 typedef UnlinkedUnit GetUnlinkedSummaryCallback(String uri);
 
 /**
- * Specialization of [FunctionTypeImpl] used for function types resynthesized
- * from summaries.
- */
-class ResynthesizedFunctionTypeImpl extends FunctionTypeImpl
-    with ResynthesizedType {
-  final SummaryResynthesizer summaryResynthesizer;
-
-  ResynthesizedFunctionTypeImpl(
-      FunctionTypeAliasElement element, String name, this.summaryResynthesizer)
-      : super.elementWithName(element, name);
-
-  int get _numTypeParameters {
-    FunctionTypeAliasElement element = this.element;
-    return element.typeParameters.length;
-  }
-}
-
-/**
- * Specialization of [InterfaceTypeImpl] used for interface types resynthesized
- * from summaries.
- */
-class ResynthesizedInterfaceTypeImpl extends InterfaceTypeImpl
-    with ResynthesizedType {
-  final SummaryResynthesizer summaryResynthesizer;
-
-  ResynthesizedInterfaceTypeImpl(
-      ClassElement element, String name, this.summaryResynthesizer)
-      : super.elementWithName(element, name);
-
-  int get _numTypeParameters => element.typeParameters.length;
-}
-
-/**
- * Common code for types resynthesized from summaries.  This code takes care of
- * filling in the appropriate number of copies of `dynamic` when it is queried
- * for type parameters on a bare type reference (i.e. it converts `List` to
- * `List<dynamic>`).
- */
-abstract class ResynthesizedType implements DartType {
-  /**
-   * The type arguments, if known.  Otherwise `null`.
-   */
-  List<DartType> _typeArguments;
-
-  SummaryResynthesizer get summaryResynthesizer;
-
-  List<DartType> get typeArguments {
-    if (_typeArguments == null) {
-      // Default to replicating "dynamic" as many times as the class element
-      // requires.
-      _typeArguments = new List<DartType>.filled(
-          _numTypeParameters, summaryResynthesizer.typeProvider.dynamicType);
-    }
-    return _typeArguments;
-  }
-
-  int get _numTypeParameters;
-}
-
-/**
  * Implementation of [ElementResynthesizer] used when resynthesizing an element
  * model from summaries.
  */
@@ -112,9 +52,6 @@
   /**
    * The [TypeProvider] used to obtain core types (such as Object, int, List,
    * and dynamic) during resynthesis.
-   *
-   * TODO(paulberry): will this create a chicken-and-egg problem when trying to
-   * resynthesize the core library from summaries?
    */
   final TypeProvider typeProvider;
 
@@ -133,10 +70,9 @@
   final Map<String, LibraryElement> _resynthesizedLibraries =
       <String, LibraryElement>{};
 
-  SummaryResynthesizer(AnalysisContext context, this.getPrelinkedSummary,
-      this.getUnlinkedSummary, this.sourceFactory)
-      : super(context),
-        typeProvider = context.typeProvider;
+  SummaryResynthesizer(AnalysisContext context, this.typeProvider,
+      this.getPrelinkedSummary, this.getUnlinkedSummary, this.sourceFactory)
+      : super(context);
 
   /**
    * Number of libraries that have been resynthesized so far.
@@ -181,7 +117,7 @@
         getUnlinkedSummary(uri)
       ];
       Source librarySource = _getSource(uri);
-      for (UnlinkedPart part in serializedUnits[0].parts) {
+      for (UnlinkedPart part in serializedUnits[0].publicNamespace.parts) {
         String partAbsUri =
             sourceFactory.resolveUri(librarySource, part.uri).uri.toString();
         serializedUnits.add(getUnlinkedSummary(partAbsUri));
@@ -228,6 +164,17 @@
   final Source librarySource;
 
   /**
+   * Indicates whether [librarySource] is the `dart:core` library.
+   */
+  bool isCoreLibrary;
+
+  /**
+   * Classes which should have their supertype set to "object" once
+   * resynthesis is complete.  Only used if [isCoreLibrary] is `true`.
+   */
+  List<ClassElementImpl> delayedObjectSubclasses = <ClassElementImpl>[];
+
+  /**
    * [ElementHolder] into which resynthesized elements should be placed.  This
    * object is recreated afresh for each unit in the library, and is used to
    * populate the [CompilationUnitElement].
@@ -260,7 +207,9 @@
   List<TypeParameterElement> currentTypeParameters;
 
   _LibraryResynthesizer(this.summaryResynthesizer, this.prelinkedLibrary,
-      this.unlinkedUnits, this.librarySource);
+      this.unlinkedUnits, this.librarySource) {
+    isCoreLibrary = librarySource.uri.toString() == 'dart:core';
+  }
 
   /**
    * Resynthesize a [ClassElement] and place it in [unitHolder].
@@ -280,7 +229,11 @@
       if (serializedClass.supertype != null) {
         classElement.supertype = buildType(serializedClass.supertype);
       } else if (!serializedClass.hasNoSupertype) {
-        classElement.supertype = summaryResynthesizer.typeProvider.objectType;
+        if (isCoreLibrary) {
+          delayedObjectSubclasses.add(classElement);
+        } else {
+          classElement.supertype = summaryResynthesizer.typeProvider.objectType;
+        }
       }
       classElement.interfaces =
           serializedClass.interfaces.map(buildType).toList();
@@ -312,7 +265,12 @@
               new ConstructorElementImpl('', -1);
           constructor.synthetic = true;
           constructor.returnType = correspondingType;
-          constructor.type = new FunctionTypeImpl(constructor);
+          constructor.type = new FunctionTypeImpl.elementWithNameAndArgs(
+              constructor,
+              null,
+              currentTypeParameters
+                  .map((TypeParameterElement e) => e.type)
+                  .toList());
           memberHolder.addConstructor(constructor);
         }
         classElement.constructors = memberHolder.constructors;
@@ -335,15 +293,15 @@
   NamespaceCombinator buildCombinator(UnlinkedCombinator serializedCombinator) {
     if (serializedCombinator.shows.isNotEmpty) {
       ShowElementCombinatorImpl combinator = new ShowElementCombinatorImpl();
-      combinator.shownNames = serializedCombinator.shows
-          .map((UnlinkedCombinatorName n) => n.name)
-          .toList();
+      // Note: we call toList() so that we don't retain a reference to the
+      // deserialized data structure.
+      combinator.shownNames = serializedCombinator.shows.toList();
       return combinator;
     } else {
       HideElementCombinatorImpl combinator = new HideElementCombinatorImpl();
-      combinator.hiddenNames = serializedCombinator.hides
-          .map((UnlinkedCombinatorName n) => n.name)
-          .toList();
+      // Note: we call toList() so that we don't retain a reference to the
+      // deserialized data structure.
+      combinator.hiddenNames = serializedCombinator.hides.toList();
       return combinator;
     }
   }
@@ -367,6 +325,7 @@
    * associated fields and implicit accessors.
    */
   void buildEnum(UnlinkedEnum serializedEnum) {
+    assert(!isCoreLibrary);
     // TODO(paulberry): add offset support (for this element type and others)
     ClassElementImpl classElement =
         new ClassElementImpl(serializedEnum.name, -1);
@@ -493,7 +452,12 @@
     } else {
       executableElement.returnType = VoidTypeImpl.instance;
     }
-    executableElement.type = new FunctionTypeImpl(executableElement);
+    executableElement.type = new FunctionTypeImpl.elementWithNameAndArgs(
+        executableElement,
+        null,
+        currentTypeParameters
+            ?.map((TypeParameterElement e) => e.type)
+            ?.toList());
     executableElement.hasImplicitReturnType =
         serializedExecutable.hasImplicitReturnType;
     executableElement.external = serializedExecutable.isExternal;
@@ -572,18 +536,18 @@
    */
   FieldElementImpl buildImplicitField(String name, DartType type,
       UnlinkedExecutableKind kind, ElementHolder holder) {
-    if (holder.getField(name) == null) {
-      FieldElementImpl field = new FieldElementImpl(name, -1);
+    FieldElementImpl field = holder.getField(name);
+    if (field == null) {
+      field = new FieldElementImpl(name, -1);
       field.synthetic = true;
       field.final2 = kind == UnlinkedExecutableKind.getter;
       field.type = type;
       holder.addField(field);
       return field;
     } else {
-      // TODO(paulberry): if adding a setter where there was previously
-      // only a getter, remove "final" modifier.
       // TODO(paulberry): what if the getter and setter have a type mismatch?
-      throw new UnimplementedError();
+      field.final2 = false;
+      return field;
     }
   }
 
@@ -654,11 +618,12 @@
     definingCompilationUnit.librarySource = librarySource;
     List<CompilationUnitElement> parts = <CompilationUnitElement>[];
     UnlinkedUnit unlinkedDefiningUnit = unlinkedUnits[0];
-    assert(
-        unlinkedDefiningUnit.parts.length + 1 == prelinkedLibrary.units.length);
+    assert(unlinkedDefiningUnit.publicNamespace.parts.length + 1 ==
+        prelinkedLibrary.units.length);
     for (int i = 1; i < prelinkedLibrary.units.length; i++) {
-      CompilationUnitElementImpl part =
-          buildPart(unlinkedDefiningUnit.parts[i - 1].uri, unlinkedUnits[i]);
+      CompilationUnitElementImpl part = buildPart(
+          unlinkedDefiningUnit.publicNamespace.parts[i - 1].uri,
+          unlinkedUnits[i]);
       parts.add(part);
     }
     libraryElement.parts = parts;
@@ -669,11 +634,18 @@
     }
     libraryElement.imports = imports;
     libraryElement.exports =
-        unlinkedDefiningUnit.exports.map(buildExport).toList();
+        unlinkedDefiningUnit.publicNamespace.exports.map(buildExport).toList();
     populateUnit(definingCompilationUnit, 0);
     for (int i = 0; i < parts.length; i++) {
       populateUnit(parts[i], i + 1);
     }
+    if (isCoreLibrary) {
+      ClassElement objectElement = libraryElement.getType('Object');
+      assert(objectElement != null);
+      for (ClassElementImpl classElement in delayedObjectSubclasses) {
+        classElement.supertype = objectElement.type;
+      }
+    }
     return libraryElement;
   }
 
@@ -765,7 +737,8 @@
         if (referenceResolution.unit != 0) {
           UnlinkedUnit referencedLibraryDefiningUnit =
               summaryResynthesizer.getUnlinkedSummary(referencedLibraryUri);
-          String uri = referencedLibraryDefiningUnit.parts[0].uri;
+          String uri = referencedLibraryDefiningUnit.publicNamespace.parts[
+              referenceResolution.unit - 1].uri;
           Source partSource = summaryResynthesizer.sourceFactory
               .resolveUri(referencedLibrarySource, uri);
           partUri = partSource.uri.toString();
@@ -780,7 +753,8 @@
       } else {
         referencedLibraryUri = librarySource.uri.toString();
         if (referenceResolution.unit != 0) {
-          String uri = unlinkedUnits[0].parts[referenceResolution.unit - 1].uri;
+          String uri = unlinkedUnits[0].publicNamespace.parts[
+              referenceResolution.unit - 1].uri;
           Source partSource =
               summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri);
           partUri = partSource.uri.toString();
@@ -788,33 +762,36 @@
           partUri = referencedLibraryUri;
         }
       }
-      ResynthesizedType resynthesizedType;
       ElementLocationImpl location = new ElementLocationImpl.con3(
           <String>[referencedLibraryUri, partUri, reference.name]);
+      List<DartType> typeArguments = const <DartType>[];
+      if (referenceResolution.numTypeParameters != 0) {
+        typeArguments = <DartType>[];
+        for (int i = 0; i < referenceResolution.numTypeParameters; i++) {
+          if (i < type.typeArguments.length) {
+            typeArguments.add(buildType(type.typeArguments[i]));
+          } else {
+            typeArguments.add(summaryResynthesizer.typeProvider.dynamicType);
+          }
+        }
+      }
       switch (referenceResolution.kind) {
         case PrelinkedReferenceKind.classOrEnum:
-          resynthesizedType = new ResynthesizedInterfaceTypeImpl(
+          return new InterfaceTypeImpl.elementWithNameAndArgs(
               new ClassElementHandle(summaryResynthesizer, location),
               reference.name,
-              summaryResynthesizer);
-          break;
+              typeArguments);
         case PrelinkedReferenceKind.typedef:
-          resynthesizedType = new ResynthesizedFunctionTypeImpl(
+          return new FunctionTypeImpl.elementWithNameAndArgs(
               new FunctionTypeAliasElementHandle(
                   summaryResynthesizer, location),
               reference.name,
-              summaryResynthesizer);
-          break;
+              typeArguments);
         default:
           // TODO(paulberry): figure out how to handle this case (which should
           // only occur in the event of erroneous code).
           throw new UnimplementedError();
       }
-      if (type.typeArguments.isNotEmpty) {
-        resynthesizedType._typeArguments =
-            type.typeArguments.map(buildType).toList();
-      }
-      return resynthesizedType;
     }
   }
 
diff --git a/pkg/analyzer/lib/src/summary/summarize_elements.dart b/pkg/analyzer/lib/src/summary/summarize_elements.dart
index 9a13020..eddb78c 100644
--- a/pkg/analyzer/lib/src/summary/summarize_elements.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_elements.dart
@@ -9,7 +9,7 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/summary/builder.dart';
+import 'package:analyzer/src/summary/base.dart';
 import 'package:analyzer/src/summary/format.dart';
 
 /**
@@ -156,28 +156,64 @@
    */
   void addCompilationUnitElements(CompilationUnitElement element, int unitNum) {
     UnlinkedUnitBuilder b = new UnlinkedUnitBuilder(ctx);
+    referenceMap.clear();
     unlinkedReferences = <UnlinkedReferenceBuilder>[
       encodeUnlinkedReference(ctx)
     ];
     prelinkedReferences = <PrelinkedReferenceBuilder>[
       encodePrelinkedReference(ctx, kind: PrelinkedReferenceKind.classOrEnum)
     ];
+    List<UnlinkedPublicNameBuilder> names = <UnlinkedPublicNameBuilder>[];
+    for (PropertyAccessorElement accessor in element.accessors) {
+      if (accessor.isPublic) {
+        names.add(encodeUnlinkedPublicName(ctx,
+            kind: PrelinkedReferenceKind.other, name: accessor.name));
+      }
+    }
+    for (ClassElement cls in element.types) {
+      if (cls.isPublic) {
+        names.add(encodeUnlinkedPublicName(ctx,
+            kind: PrelinkedReferenceKind.classOrEnum, name: cls.name));
+      }
+    }
+    for (ClassElement enm in element.enums) {
+      if (enm.isPublic) {
+        names.add(encodeUnlinkedPublicName(ctx,
+            kind: PrelinkedReferenceKind.classOrEnum, name: enm.name));
+      }
+    }
+    for (FunctionElement function in element.functions) {
+      if (function.isPublic) {
+        names.add(encodeUnlinkedPublicName(ctx,
+            kind: PrelinkedReferenceKind.other, name: function.name));
+      }
+    }
+    for (FunctionTypeAliasElement typedef in element.functionTypeAliases) {
+      if (typedef.isPublic) {
+        names.add(encodeUnlinkedPublicName(ctx,
+            kind: PrelinkedReferenceKind.typedef, name: typedef.name));
+      }
+    }
     if (unitNum == 0) {
+      if (libraryElement.name.isNotEmpty) {
+        b.libraryName = libraryElement.name;
+      }
+      b.publicNamespace = encodeUnlinkedPublicNamespace(ctx,
+          exports: libraryElement.exports.map(serializeExport).toList(),
+          parts: libraryElement.parts
+              .map((CompilationUnitElement e) =>
+                  encodeUnlinkedPart(ctx, uri: e.uri))
+              .toList(),
+          names: names);
+      b.imports = libraryElement.imports.map(serializeImport).toList();
+    } else {
       // TODO(paulberry): we need to figure out a way to record library, part,
       // import, and export declarations that appear in non-defining
       // compilation units (even though such declarations are prohibited by the
       // language), so that if the user makes code changes that cause a
       // non-defining compilation unit to become a defining compilation unit,
       // we can create a correct summary by simply re-linking.
-      if (libraryElement.name.isNotEmpty) {
-        b.libraryName = libraryElement.name;
-      }
-      b.exports = libraryElement.exports.map(serializeExport).toList();
-      b.imports = libraryElement.imports.map(serializeImport).toList();
-      b.parts = libraryElement.parts
-          .map(
-              (CompilationUnitElement e) => encodeUnlinkedPart(ctx, uri: e.uri))
-          .toList();
+      b.publicNamespace = encodeUnlinkedPublicNamespace(ctx, names: names);
     }
     b.classes = element.types.map(serializeClass).toList();
     b.enums = element.enums.map(serializeEnum).toList();
@@ -306,21 +342,14 @@
       NamespaceCombinator combinator) {
     UnlinkedCombinatorBuilder b = new UnlinkedCombinatorBuilder(ctx);
     if (combinator is ShowElementCombinator) {
-      b.shows = combinator.shownNames.map(serializeCombinatorName).toList();
+      b.shows = combinator.shownNames;
     } else if (combinator is HideElementCombinator) {
-      b.hides = combinator.hiddenNames.map(serializeCombinatorName).toList();
+      b.hides = combinator.hiddenNames;
     }
     return b;
   }
 
   /**
-   * Serialize the given [name] into an [UnlinkedCombinatorName].
-   */
-  UnlinkedCombinatorNameBuilder serializeCombinatorName(String name) {
-    return encodeUnlinkedCombinatorName(ctx, name: name);
-  }
-
-  /**
    * Return the index of the entry in the dependency table
    * ([PrelinkedLibrary.dependencies]) for the given [dependentLibrary].  A new
    * entry is added to the table if necessary to satisfy the request.
@@ -447,7 +476,9 @@
   /**
    * Serialize the given [parameter] into an [UnlinkedParam].
    */
-  UnlinkedParamBuilder serializeParam(ParameterElement parameter) {
+  UnlinkedParamBuilder serializeParam(ParameterElement parameter,
+      [Element context]) {
+    context ??= parameter;
     UnlinkedParamBuilder b = new UnlinkedParamBuilder(ctx);
     b.name = parameter.name;
     switch (parameter.parameterKind) {
@@ -468,9 +499,11 @@
       if (!type.returnType.isVoid) {
         b.type = serializeTypeRef(type.returnType, parameter);
       }
-      b.parameters = type.parameters.map(serializeParam).toList();
+      b.parameters = type.parameters
+          .map((parameter) => serializeParam(parameter, context))
+          .toList();
     } else {
-      b.type = serializeTypeRef(type, parameter);
+      b.type = serializeTypeRef(type, context);
       b.hasImplicitType = parameter.hasImplicitType;
     }
     return b;
@@ -544,6 +577,10 @@
               element.getAncestor((Element e) => e is CompilationUnitElement);
           int unit = dependentLibrary.units.indexOf(unitElement);
           assert(unit != -1);
+          int numTypeParameters = 0;
+          if (element is TypeParameterizedElement) {
+            numTypeParameters = element.typeParameters.length;
+          }
           int index = unlinkedReferences.length;
           // TODO(paulberry): set UnlinkedReference.prefix.
           unlinkedReferences
@@ -553,7 +590,8 @@
               kind: element is FunctionTypeAliasElement
                   ? PrelinkedReferenceKind.typedef
                   : PrelinkedReferenceKind.classOrEnum,
-              unit: unit));
+              unit: unit,
+              numTypeParameters: numTypeParameters));
           return index;
         });
       }
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
new file mode 100644
index 0000000..70b7bdd
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -0,0 +1,355 @@
+// 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.summary.summary_sdk;
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/context/cache.dart' show CacheEntry;
+import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/constant.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart' show Source, SourceKind;
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/resynthesize.dart';
+import 'package:analyzer/src/task/dart.dart'
+    show
+        LIBRARY_ELEMENT1,
+        LIBRARY_ELEMENT2,
+        LIBRARY_ELEMENT3,
+        LIBRARY_ELEMENT4,
+        LIBRARY_ELEMENT5,
+        LIBRARY_ELEMENT6,
+        LIBRARY_ELEMENT7,
+        LIBRARY_ELEMENT8,
+        READY_LIBRARY_ELEMENT2,
+        READY_LIBRARY_ELEMENT5,
+        READY_LIBRARY_ELEMENT6,
+        TYPE_PROVIDER;
+import 'package:analyzer/task/dart.dart';
+import 'package:analyzer/task/model.dart'
+    show AnalysisTarget, ResultDescriptor, TargetedResult;
+
+/**
+ * An [SdkAnalysisContext] for Dart SDK with a summary [SdkBundle].
+ */
+class SummarySdkAnalysisContext extends SdkAnalysisContext {
+  final SdkBundle bundle;
+  final SummaryTypeProvider typeProvider = new SummaryTypeProvider();
+
+  SummaryResynthesizer resynthesizer;
+
+  SummarySdkAnalysisContext(this.bundle);
+
+  @override
+  bool aboutToComputeResult(CacheEntry entry, ResultDescriptor result) {
+    if (resynthesizer == null) {
+      resynthesizer = new SummaryResynthesizer(this, typeProvider,
+          _getPrelinkedSummary, _getUnlinkedSummary, sourceFactory);
+      _buildCoreLibrary();
+      _buildAsyncLibrary();
+    }
+    if (result == TYPE_PROVIDER) {
+      entry.setValue(result, typeProvider, TargetedResult.EMPTY_LIST);
+      return true;
+    }
+    AnalysisTarget target = entry.target;
+//    print('SummarySdkAnalysisContext: $result of $target');
+    if (target is Source && target.isInSystemLibrary) {
+      if (result == LIBRARY_ELEMENT1 ||
+          result == LIBRARY_ELEMENT2 ||
+          result == LIBRARY_ELEMENT3 ||
+          result == LIBRARY_ELEMENT4 ||
+          result == LIBRARY_ELEMENT5 ||
+          result == LIBRARY_ELEMENT6 ||
+          result == LIBRARY_ELEMENT7 ||
+          result == LIBRARY_ELEMENT8 ||
+          result == LIBRARY_ELEMENT) {
+        // TODO(scheglov) try to find a way to avoid listing every result
+        // e.g. "result.whenComplete == LIBRARY_ELEMENT"
+        String uri = target.uri.toString();
+        LibraryElement libraryElement = resynthesizer.getLibraryElement(uri);
+        entry.setValue(result, libraryElement, TargetedResult.EMPTY_LIST);
+        return true;
+      } else if (result == READY_LIBRARY_ELEMENT2 ||
+          result == READY_LIBRARY_ELEMENT5 ||
+          result == READY_LIBRARY_ELEMENT6) {
+        entry.setValue(result, true, TargetedResult.EMPTY_LIST);
+        return true;
+      } else if (result == SOURCE_KIND) {
+        // TODO(scheglov) not every source is a library
+        entry.setValue(result, SourceKind.LIBRARY, TargetedResult.EMPTY_LIST);
+        return true;
+      } else {
+//        throw new UnimplementedError('$result of $target');
+      }
+    }
+    return false;
+  }
+
+  void _buildAsyncLibrary() {
+    LibraryElement library = resynthesizer.getLibraryElement('dart:async');
+    typeProvider.initializeAsync(library);
+  }
+
+  void _buildCoreLibrary() {
+    LibraryElement library = resynthesizer.getLibraryElement('dart:core');
+    typeProvider.initializeCore(library);
+  }
+
+  PrelinkedLibrary _getPrelinkedSummary(String uri) {
+    for (int i = 0; i < bundle.prelinkedLibraryUris.length; i++) {
+      if (bundle.prelinkedLibraryUris[i] == uri) {
+        return bundle.prelinkedLibraries[i];
+      }
+    }
+    throw new StateError('Unable to find prelinked summary for $uri');
+  }
+
+  UnlinkedUnit _getUnlinkedSummary(String uri) {
+    for (int i = 0; i < bundle.unlinkedUnitUris.length; i++) {
+      if (bundle.unlinkedUnitUris[i] == uri) {
+        return bundle.unlinkedUnits[i];
+      }
+    }
+    throw new StateError('Unable to find unlinked summary for $uri');
+  }
+}
+
+/**
+ * Implementation of [TypeProvider] which can be initialized separately with
+ * `dart:core` and `dart:async` libraries.
+ */
+class SummaryTypeProvider implements TypeProvider {
+  bool _isCoreInitialized = false;
+  bool _isAsyncInitialized = false;
+
+  InterfaceType _boolType;
+  InterfaceType _deprecatedType;
+  InterfaceType _doubleType;
+  InterfaceType _functionType;
+  InterfaceType _futureDynamicType;
+  InterfaceType _futureNullType;
+  InterfaceType _futureType;
+  InterfaceType _intType;
+  InterfaceType _iterableDynamicType;
+  InterfaceType _iterableType;
+  InterfaceType _listType;
+  InterfaceType _mapType;
+  DartObjectImpl _nullObject;
+  InterfaceType _nullType;
+  InterfaceType _numType;
+  InterfaceType _objectType;
+  InterfaceType _stackTraceType;
+  InterfaceType _streamDynamicType;
+  InterfaceType _streamType;
+  InterfaceType _stringType;
+  InterfaceType _symbolType;
+  InterfaceType _typeType;
+
+  @override
+  InterfaceType get boolType {
+    assert(_isCoreInitialized);
+    return _boolType;
+  }
+
+  @override
+  DartType get bottomType => BottomTypeImpl.instance;
+
+  @override
+  InterfaceType get deprecatedType {
+    assert(_isCoreInitialized);
+    return _deprecatedType;
+  }
+
+  @override
+  InterfaceType get doubleType {
+    assert(_isCoreInitialized);
+    return _doubleType;
+  }
+
+  @override
+  DartType get dynamicType => DynamicTypeImpl.instance;
+
+  @override
+  InterfaceType get functionType {
+    assert(_isCoreInitialized);
+    return _functionType;
+  }
+
+  @override
+  InterfaceType get futureDynamicType {
+    assert(_isAsyncInitialized);
+    return _futureDynamicType;
+  }
+
+  @override
+  InterfaceType get futureNullType {
+    assert(_isAsyncInitialized);
+    return _futureNullType;
+  }
+
+  @override
+  InterfaceType get futureType {
+    assert(_isAsyncInitialized);
+    return _futureType;
+  }
+
+  @override
+  InterfaceType get intType {
+    assert(_isCoreInitialized);
+    return _intType;
+  }
+
+  @override
+  InterfaceType get iterableDynamicType {
+    assert(_isCoreInitialized);
+    return _iterableDynamicType;
+  }
+
+  @override
+  InterfaceType get iterableType {
+    assert(_isCoreInitialized);
+    return _iterableType;
+  }
+
+  @override
+  InterfaceType get listType {
+    assert(_isCoreInitialized);
+    return _listType;
+  }
+
+  @override
+  InterfaceType get mapType {
+    assert(_isCoreInitialized);
+    return _mapType;
+  }
+
+  @override
+  List<InterfaceType> get nonSubtypableTypes => <InterfaceType>[
+        nullType,
+        numType,
+        intType,
+        doubleType,
+        boolType,
+        stringType
+      ];
+
+  @override
+  DartObjectImpl get nullObject {
+    if (_nullObject == null) {
+      _nullObject = new DartObjectImpl(nullType, NullState.NULL_STATE);
+    }
+    return _nullObject;
+  }
+
+  @override
+  InterfaceType get nullType {
+    assert(_isCoreInitialized);
+    return _nullType;
+  }
+
+  @override
+  InterfaceType get numType {
+    assert(_isCoreInitialized);
+    return _numType;
+  }
+
+  @override
+  InterfaceType get objectType {
+    assert(_isCoreInitialized);
+    return _objectType;
+  }
+
+  @override
+  InterfaceType get stackTraceType {
+    assert(_isCoreInitialized);
+    return _stackTraceType;
+  }
+
+  @override
+  InterfaceType get streamDynamicType {
+    assert(_isAsyncInitialized);
+    return _streamDynamicType;
+  }
+
+  @override
+  InterfaceType get streamType {
+    assert(_isAsyncInitialized);
+    return _streamType;
+  }
+
+  @override
+  InterfaceType get stringType {
+    assert(_isCoreInitialized);
+    return _stringType;
+  }
+
+  @override
+  InterfaceType get symbolType {
+    assert(_isCoreInitialized);
+    return _symbolType;
+  }
+
+  @override
+  InterfaceType get typeType {
+    assert(_isCoreInitialized);
+    return _typeType;
+  }
+
+  @override
+  DartType get undefinedType => UndefinedTypeImpl.instance;
+
+  /**
+   * Initialize the `dart:async` types provided by this type provider.
+   */
+  void initializeAsync(LibraryElement library) {
+    assert(_isCoreInitialized);
+    assert(!_isAsyncInitialized);
+    _isAsyncInitialized = true;
+    _futureType = _getType(library, "Future");
+    _streamType = _getType(library, "Stream");
+    _futureDynamicType = _futureType.substitute4(<DartType>[dynamicType]);
+    _futureNullType = _futureType.substitute4(<DartType>[_nullType]);
+    _streamDynamicType = _streamType.substitute4(<DartType>[dynamicType]);
+  }
+
+  /**
+   * Initialize the `dart:core` types provided by this type provider.
+   */
+  void initializeCore(LibraryElement library) {
+    assert(!_isCoreInitialized);
+    assert(!_isAsyncInitialized);
+    _isCoreInitialized = true;
+    _boolType = _getType(library, "bool");
+    _deprecatedType = _getType(library, "Deprecated");
+    _doubleType = _getType(library, "double");
+    _functionType = _getType(library, "Function");
+    _intType = _getType(library, "int");
+    _iterableType = _getType(library, "Iterable");
+    _listType = _getType(library, "List");
+    _mapType = _getType(library, "Map");
+    _nullType = _getType(library, "Null");
+    _numType = _getType(library, "num");
+    _objectType = _getType(library, "Object");
+    _stackTraceType = _getType(library, "StackTrace");
+    _stringType = _getType(library, "String");
+    _symbolType = _getType(library, "Symbol");
+    _typeType = _getType(library, "Type");
+    _iterableDynamicType = _iterableType.substitute4(<DartType>[dynamicType]);
+  }
+
+  /**
+   * Return the type with the given [name] from the given [library], or
+   * throw a [StateError] if there is no class with the given name.
+   */
+  InterfaceType _getType(LibraryElement library, String name) {
+    Element element = library.getType(name);
+    if (element == null) {
+      throw new StateError("No definition of type $name");
+    }
+    return (element as ClassElement).type;
+  }
+}
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 5a64d4c..56dc665 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -145,6 +145,114 @@
     new ListResultDescriptor<Source>('CONTAINING_LIBRARIES', Source.EMPTY_LIST);
 
 /**
+ * The flag specifying that [RESOLVED_UNIT] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT =
+    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT1] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT1 =
+    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT1', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT10] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT10 =
+    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT10', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT11] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT11 =
+    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT11', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT2] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT2 =
+    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT2', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT3] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT3 =
+    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT3', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT4] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT4 =
+    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT4', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT5] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT5 =
+    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT5', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT6] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT6 =
+    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT6', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT7] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT7 =
+    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT7', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT8] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT8 =
+    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT8', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT9] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT9 =
+    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT9', false);
+
+/**
  * The sources representing the export closure of a library.
  * The [Source]s include only library sources, not their units.
  *
@@ -738,6 +846,7 @@
       buildInputs, <ResultDescriptor>[
     COMPILATION_UNIT_CONSTANTS,
     COMPILATION_UNIT_ELEMENT,
+    CREATED_RESOLVED_UNIT1,
     RESOLVED_UNIT1
   ]);
 
@@ -790,6 +899,7 @@
     outputs[COMPILATION_UNIT_CONSTANTS] = constants;
     outputs[COMPILATION_UNIT_ELEMENT] = element;
     outputs[RESOLVED_UNIT1] = unit;
+    outputs[CREATED_RESOLVED_UNIT1] = true;
   }
 
   /**
@@ -1099,7 +1209,7 @@
       'BuildEnumMemberElementsTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[RESOLVED_UNIT2]);
+      <ResultDescriptor>[CREATED_RESOLVED_UNIT2, RESOLVED_UNIT2]);
 
   BuildEnumMemberElementsTask(
       InternalAnalysisContext context, AnalysisTarget target)
@@ -1120,6 +1230,7 @@
     //
     EnumMemberBuilder builder = new EnumMemberBuilder(typeProvider);
     unit.accept(builder);
+    outputs[CREATED_RESOLVED_UNIT2] = true;
     outputs[RESOLVED_UNIT2] = unit;
   }
 
@@ -2398,7 +2509,7 @@
       'EvaluateUnitConstantsTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[RESOLVED_UNIT11]);
+      <ResultDescriptor>[CREATED_RESOLVED_UNIT11, RESOLVED_UNIT11]);
 
   EvaluateUnitConstantsTask(AnalysisContext context, LibrarySpecificUnit target)
       : super(context, target);
@@ -2412,6 +2523,7 @@
     // all constants are evaluated before this method is called.
     CompilationUnit unit = getRequiredInput(UNIT_INPUT);
     outputs[RESOLVED_UNIT11] = unit;
+    outputs[CREATED_RESOLVED_UNIT11] = true;
   }
 
   /**
@@ -2891,7 +3003,7 @@
       'InferInstanceMembersInUnitTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[RESOLVED_UNIT9]);
+      <ResultDescriptor>[CREATED_RESOLVED_UNIT9, RESOLVED_UNIT9]);
 
   /**
    * Initialize a newly created task to build a library element for the given
@@ -2923,6 +3035,7 @@
     // Record outputs.
     //
     outputs[RESOLVED_UNIT9] = unit;
+    outputs[CREATED_RESOLVED_UNIT9] = true;
   }
 
   /**
@@ -2941,12 +3054,12 @@
       // Require that field re-resolution be complete for all units in the
       // current library cycle.
       'orderLibraryCycleTasks': LIBRARY_CYCLE_UNITS.of(unit).toList(
-          (CompilationUnitElementImpl unit) => RESOLVED_UNIT8
+          (CompilationUnitElementImpl unit) => CREATED_RESOLVED_UNIT8
               .of(new LibrarySpecificUnit(unit.librarySource, unit.source))),
       // Require that full inference be complete for all dependencies of the
       // current library cycle.
       'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList(
-          (CompilationUnitElementImpl unit) => RESOLVED_UNIT9
+          (CompilationUnitElementImpl unit) => CREATED_RESOLVED_UNIT9
               .of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
     };
   }
@@ -3012,7 +3125,7 @@
       'InferStaticVariableTypesInUnitTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[RESOLVED_UNIT7]);
+      <ResultDescriptor>[CREATED_RESOLVED_UNIT7, RESOLVED_UNIT7]);
 
   /**
    * Initialize a newly created task to build a library element for the given
@@ -3037,6 +3150,7 @@
     // preparing all of the inputs.
     //
     outputs[RESOLVED_UNIT7] = unit;
+    outputs[CREATED_RESOLVED_UNIT7] = true;
   }
 
   /**
@@ -3186,7 +3300,7 @@
       // Require that full inference be complete for all dependencies of the
       // current library cycle.
       'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList(
-          (CompilationUnitElementImpl unit) => RESOLVED_UNIT9
+          (CompilationUnitElementImpl unit) => CREATED_RESOLVED_UNIT9
               .of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
     };
   }
@@ -3599,6 +3713,7 @@
       buildInputs, <ResultDescriptor>[
     INFERABLE_STATIC_VARIABLES_IN_UNIT,
     PROPAGABLE_VARIABLES_IN_UNIT,
+    CREATED_RESOLVED_UNIT5,
     RESOLVED_UNIT5
   ]);
 
@@ -3634,6 +3749,7 @@
     }
     outputs[PROPAGABLE_VARIABLES_IN_UNIT] = visitor.propagableVariables;
     outputs[RESOLVED_UNIT5] = unit;
+    outputs[CREATED_RESOLVED_UNIT5] = true;
   }
 
   /**
@@ -3654,7 +3770,7 @@
       // Require that full inference be complete for all dependencies of the
       // current library cycle.
       'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList(
-          (CompilationUnitElementImpl unit) => RESOLVED_UNIT9
+          (CompilationUnitElementImpl unit) => CREATED_RESOLVED_UNIT9
               .of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
     };
   }
@@ -3799,7 +3915,7 @@
       'PropagateVariableTypesInUnitTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[RESOLVED_UNIT6]);
+      <ResultDescriptor>[CREATED_RESOLVED_UNIT6, RESOLVED_UNIT6]);
 
   PropagateVariableTypesInUnitTask(
       InternalAnalysisContext context, LibrarySpecificUnit unit)
@@ -3820,6 +3936,7 @@
     // preparing all of the inputs.
     //
     outputs[RESOLVED_UNIT6] = unit;
+    outputs[CREATED_RESOLVED_UNIT6] = true;
   }
 
   /**
@@ -4369,7 +4486,7 @@
       'ResolveInstanceFieldsInUnitTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[RESOLVED_UNIT8]);
+      <ResultDescriptor>[CREATED_RESOLVED_UNIT8, RESOLVED_UNIT8]);
 
   /**
    * Initialize a newly created task to build a library element for the given
@@ -4415,6 +4532,7 @@
     // Record outputs.
     //
     outputs[RESOLVED_UNIT8] = unit;
+    outputs[CREATED_RESOLVED_UNIT8] = true;
   }
 
   /**
@@ -4434,12 +4552,12 @@
       // Require that static variable inference  be complete for all units in
       // the current library cycle.
       'orderLibraryCycleTasks': LIBRARY_CYCLE_UNITS.of(unit).toList(
-          (CompilationUnitElementImpl unit) => RESOLVED_UNIT7
+          (CompilationUnitElementImpl unit) => CREATED_RESOLVED_UNIT7
               .of(new LibrarySpecificUnit(unit.librarySource, unit.source))),
       // Require that full inference be complete for all dependencies of the
       // current library cycle.
       'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList(
-          (CompilationUnitElementImpl unit) => RESOLVED_UNIT9
+          (CompilationUnitElementImpl unit) => CREATED_RESOLVED_UNIT9
               .of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
     };
   }
@@ -4689,6 +4807,7 @@
       'ResolveUnitTask', createTask, buildInputs, <ResultDescriptor>[
     CONSTANT_EXPRESSIONS_DEPENDENCIES,
     RESOLVE_UNIT_ERRORS,
+    CREATED_RESOLVED_UNIT10,
     RESOLVED_UNIT10
   ]);
 
@@ -4736,6 +4855,7 @@
     outputs[CONSTANT_EXPRESSIONS_DEPENDENCIES] = constExprDependencies;
     outputs[RESOLVE_UNIT_ERRORS] = getTargetSourceErrors(errorListener, target);
     outputs[RESOLVED_UNIT10] = unit;
+    outputs[CREATED_RESOLVED_UNIT10] = true;
   }
 
   /**
@@ -4755,7 +4875,7 @@
       // Require that inference be complete for all units in the
       // current library cycle.
       'orderLibraryCycleTasks': LIBRARY_CYCLE_UNITS.of(unit).toList(
-          (CompilationUnitElementImpl unit) => RESOLVED_UNIT9
+          (CompilationUnitElementImpl unit) => CREATED_RESOLVED_UNIT9
               .of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
     };
   }
@@ -4793,10 +4913,11 @@
    * The task descriptor describing this kind of task.
    */
   static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ResolveUnitTypeNamesTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[RESOLVE_TYPE_NAMES_ERRORS, RESOLVED_UNIT3]);
+      'ResolveUnitTypeNamesTask', createTask, buildInputs, <ResultDescriptor>[
+    RESOLVE_TYPE_NAMES_ERRORS,
+    CREATED_RESOLVED_UNIT3,
+    RESOLVED_UNIT3
+  ]);
 
   ResolveUnitTypeNamesTask(
       InternalAnalysisContext context, AnalysisTarget target)
@@ -4827,6 +4948,7 @@
     outputs[RESOLVE_TYPE_NAMES_ERRORS] =
         getTargetSourceErrors(errorListener, target);
     outputs[RESOLVED_UNIT3] = unit;
+    outputs[CREATED_RESOLVED_UNIT3] = true;
   }
 
   /**
@@ -4883,8 +5005,11 @@
   static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
       'ResolveVariableReferencesTask',
       createTask,
-      buildInputs,
-      <ResultDescriptor>[RESOLVED_UNIT4, VARIABLE_REFERENCE_ERRORS]);
+      buildInputs, <ResultDescriptor>[
+    CREATED_RESOLVED_UNIT4,
+    RESOLVED_UNIT4,
+    VARIABLE_REFERENCE_ERRORS
+  ]);
 
   ResolveVariableReferencesTask(
       InternalAnalysisContext context, AnalysisTarget target)
@@ -4915,6 +5040,7 @@
     // Record outputs.
     //
     outputs[RESOLVED_UNIT4] = unit;
+    outputs[CREATED_RESOLVED_UNIT4] = true;
     outputs[VARIABLE_REFERENCE_ERRORS] =
         getTargetSourceErrors(errorListener, target);
   }
@@ -5077,10 +5203,11 @@
    * The task descriptor describing this kind of task.
    */
   static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'StrongModeVerifyUnitTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[STRONG_MODE_ERRORS, RESOLVED_UNIT]);
+      'StrongModeVerifyUnitTask', createTask, buildInputs, <ResultDescriptor>[
+    STRONG_MODE_ERRORS,
+    CREATED_RESOLVED_UNIT,
+    RESOLVED_UNIT
+  ]);
 
   StrongModeVerifyUnitTask(
       InternalAnalysisContext context, AnalysisTarget target)
@@ -5101,11 +5228,11 @@
       unit.accept(new CodeChecker(
           typeProvider, new StrongTypeSystemImpl(), errorListener));
     }
-
     //
     // Record outputs.
     //
     outputs[STRONG_MODE_ERRORS] = getUniqueErrors(errorListener.errors);
+    outputs[CREATED_RESOLVED_UNIT] = true;
     outputs[RESOLVED_UNIT] = unit;
   }
 
diff --git a/pkg/analyzer/lib/src/task/driver.dart b/pkg/analyzer/lib/src/task/driver.dart
index 7cdbe1c..db9cd1d 100644
--- a/pkg/analyzer/lib/src/task/driver.dart
+++ b/pkg/analyzer/lib/src/task/driver.dart
@@ -504,7 +504,7 @@
 }
 
 /**
- * Object used by CycleAwareDependencyWalker to report a single strongly
+ * Object used by [CycleAwareDependencyWalker] to report a single strongly
  * connected component of nodes.
  */
 class StronglyConnectedComponent<Node> {
@@ -702,14 +702,19 @@
         //
         throw new UnimplementedError();
       } else if (inputState != CacheState.VALID) {
-        try {
-          TaskDescriptor descriptor =
-              taskManager.findTask(inputTarget, inputResult);
-          return new WorkItem(context, inputTarget, descriptor, inputResult,
-              level + 1, workOrder);
-        } on AnalysisException catch (exception, stackTrace) {
-          this.exception = new CaughtException(exception, stackTrace);
-          return null;
+        if (context.aboutToComputeResult(inputEntry, inputResult)) {
+          inputState = CacheState.VALID;
+          builder.currentValue = inputEntry.getValue(inputResult);
+        } else {
+          try {
+            TaskDescriptor descriptor =
+                taskManager.findTask(inputTarget, inputResult);
+            return new WorkItem(context, inputTarget, descriptor, inputResult,
+                level + 1, workOrder);
+          } on AnalysisException catch (exception, stackTrace) {
+            this.exception = new CaughtException(exception, stackTrace);
+            return null;
+          }
         }
       } else {
         builder.currentValue = inputEntry.getValue(inputResult);
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index 5b9acfe..ebc5a4c 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -52,7 +52,7 @@
 
   /// Valid error `severity`s.
   static final List<String> severities =
-      ErrorSeverity.values.map((s) => s.name).toList();
+      new List.unmodifiable(severityMap.keys);
 
   /// Ways to say `include`.
   static const List<String> includeSynonyms = const ['include', 'true'];
@@ -121,17 +121,22 @@
 
   /// Report an unsupported [node] value, defined in the given [scopeName].
   void reportError(ErrorReporter reporter, String scopeName, YamlNode node) {
-    reporter.reportErrorForSpan(
-        code, node.span, [scopeName, node.value, proposal]);
+    reporter
+        .reportErrorForSpan(code, node.span, [scopeName, node.value, proposal]);
   }
 }
 
 /// Validates `analyzer` error filter options.
 class ErrorFilterOptionValidator extends OptionsValidator {
-  /// Pretty list of legal includes.
-  static final String legalIncludes = StringUtilities.printListOfQuotedNames(
+  /// Legal values.
+  static final List<String> legalValues =
       new List.from(AnalyzerOptions.ignoreSynonyms)
-        ..addAll(AnalyzerOptions.includeSynonyms));
+        ..addAll(AnalyzerOptions.includeSynonyms)
+        ..addAll(AnalyzerOptions.severities);
+
+  /// Pretty String listing legal values.
+  static final String legalValueString =
+      StringUtilities.printListOfQuotedNames(legalValues);
 
   /// Lazily populated set of error codes (hashed for speedy lookup).
   static HashSet<String> _errorCodes;
@@ -170,12 +175,14 @@
         }
         if (v is YamlScalar) {
           value = toLowerCase(v.value);
-          if (!AnalyzerOptions.ignoreSynonyms.contains(value) &&
-              !AnalyzerOptions.includeSynonyms.contains(value)) {
+          if (!legalValues.contains(value)) {
             reporter.reportErrorForSpan(
                 AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUES,
-                v.span,
-                [AnalyzerOptions.errors, v.value?.toString(), legalIncludes]);
+                v.span, [
+              AnalyzerOptions.errors,
+              v.value?.toString(),
+              legalValueString
+            ]);
           }
         }
       });
@@ -451,7 +458,8 @@
 
   void setProcessors(AnalysisContext context, Object codes) {
     ErrorConfig config = new ErrorConfig(codes);
-    context.setConfigurationData(CONFIGURED_ERROR_PROCESSORS, config.processors);
+    context.setConfigurationData(
+        CONFIGURED_ERROR_PROCESSORS, config.processors);
   }
 
   void setStrongMode(AnalysisContext context, Object strongMode) {
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 7ab2b51..607b92c 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.27.1
+version: 0.27.1+2
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: http://www.dartlang.org
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index 6f3aa5d..bb6c95a 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -6356,7 +6356,8 @@
 
   void _assertHasDocRange(
       Element element, int expectedOffset, int expectedLength) {
-    SourceRange docRange = element.docRange;
+    // Cast to dynamic here to avoid a hint about @deprecated docRange.
+    SourceRange docRange = (element as dynamic).docRange;
     expect(docRange, isNotNull);
     expect(docRange.offset, expectedOffset);
     expect(docRange.length, expectedLength);
diff --git a/pkg/analyzer/test/generated/declaration_resolver_test.dart b/pkg/analyzer/test/generated/declaration_resolver_test.dart
index 5ee43e4..3dfae2b 100644
--- a/pkg/analyzer/test/generated/declaration_resolver_test.dart
+++ b/pkg/analyzer/test/generated/declaration_resolver_test.dart
@@ -6,6 +6,7 @@
 
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:unittest/unittest.dart';
 
@@ -17,6 +18,19 @@
 main() {
   initializeTestEnvironment();
   runReflectiveTests(DeclarationResolverTest);
+  runReflectiveTests(StrongModeDeclarationResolverTest);
+}
+
+CompilationUnit _cloneResolveUnit(CompilationUnit unit) {
+  CompilationUnit clonedUnit = AstCloner.clone(unit);
+  new DeclarationResolver().resolve(clonedUnit, unit.element);
+  return clonedUnit;
+}
+
+SimpleIdentifier _findSimpleIdentifier(
+    AstNode root, String code, String search) {
+  return EngineTestCase.findNode(
+      root, code, search, (n) => n is SimpleIdentifier);
 }
 
 @reflectiveTest
@@ -32,11 +46,11 @@
 ''';
     CompilationUnit unit = resolveSource(code);
     PropertyAccessorElement getterElement =
-        findSimpleIdentifier(unit, code, 'zzz =>').staticElement;
+        _findSimpleIdentifier(unit, code, 'zzz =>').staticElement;
     expect(getterElement.isGetter, isTrue);
     // re-resolve
     CompilationUnit unit2 = _cloneResolveUnit(unit);
-    SimpleIdentifier getterName = findSimpleIdentifier(unit2, code, 'zzz =>');
+    SimpleIdentifier getterName = _findSimpleIdentifier(unit2, code, 'zzz =>');
     expect(getterName.staticElement, same(getterElement));
   }
 
@@ -46,11 +60,11 @@
 ''';
     CompilationUnit unit = resolveSource(code);
     PropertyAccessorElement setterElement =
-        findSimpleIdentifier(unit, code, 'zzz(_)').staticElement;
+        _findSimpleIdentifier(unit, code, 'zzz(_)').staticElement;
     expect(setterElement.isSetter, isTrue);
     // re-resolve
     CompilationUnit unit2 = _cloneResolveUnit(unit);
-    SimpleIdentifier getterName = findSimpleIdentifier(unit2, code, 'zzz(_)');
+    SimpleIdentifier getterName = _findSimpleIdentifier(unit2, code, 'zzz(_)');
     expect(getterName.staticElement, same(setterElement));
   }
 
@@ -62,10 +76,10 @@
 ''';
     CompilationUnit unit = resolveSource(code);
     FunctionElement getterElement =
-        findSimpleIdentifier(unit, code, 'zzz =>').staticElement;
+        _findSimpleIdentifier(unit, code, 'zzz =>').staticElement;
     // re-resolve
     CompilationUnit unit2 = _cloneResolveUnit(unit);
-    SimpleIdentifier getterName = findSimpleIdentifier(unit2, code, 'zzz =>');
+    SimpleIdentifier getterName = _findSimpleIdentifier(unit2, code, 'zzz =>');
     expect(getterName.staticElement, same(getterElement));
   }
 
@@ -77,22 +91,67 @@
 ''';
     CompilationUnit unit = resolveSource(code);
     FunctionElement setterElement =
-        findSimpleIdentifier(unit, code, 'zzz(x)').staticElement;
+        _findSimpleIdentifier(unit, code, 'zzz(x)').staticElement;
     // re-resolve
     CompilationUnit unit2 = _cloneResolveUnit(unit);
-    SimpleIdentifier setterName = findSimpleIdentifier(unit2, code, 'zzz(x)');
+    SimpleIdentifier setterName = _findSimpleIdentifier(unit2, code, 'zzz(x)');
     expect(setterName.staticElement, same(setterElement));
   }
+}
 
-  static SimpleIdentifier findSimpleIdentifier(
-      AstNode root, String code, String search) {
-    return EngineTestCase.findNode(
-        root, code, search, (n) => n is SimpleIdentifier);
+/**
+ * Strong mode DeclarationResolver tests
+ */
+@reflectiveTest
+class StrongModeDeclarationResolverTest extends ResolverTestCase {
+  @override
+  void setUp() {
+    resetWithOptions(new AnalysisOptionsImpl()..strongMode = true);
   }
 
-  static CompilationUnit _cloneResolveUnit(CompilationUnit unit) {
-    CompilationUnit clonedUnit = AstCloner.clone(unit);
-    new DeclarationResolver().resolve(clonedUnit, unit.element);
-    return clonedUnit;
+  void test_genericFunction_typeParameter() {
+    String code = r'''
+/*=T*/ max/*<T>*/(/*=T*/ x, /*=T*/ y) => null;
+''';
+    CompilationUnit unit = resolveSource(code);
+    FunctionDeclaration node = _findSimpleIdentifier(unit, code, 'max').parent;
+    TypeParameter t = node.functionExpression.typeParameters.typeParameters[0];
+
+    FunctionElement element = node.name.staticElement;
+    TypeParameterElement tElement = element.typeParameters[0];
+    expect(tElement, isNotNull);
+    expect(element.typeParameters.toString(), "[T]");
+    expect(element.type.toString(), "<T>(T, T) → T");
+    expect(t.element, same(tElement));
+
+    // re-resolve
+    CompilationUnit unit2 = _cloneResolveUnit(unit);
+    node = _findSimpleIdentifier(unit2, code, 'max').parent;
+    t = node.functionExpression.typeParameters.typeParameters[0];
+    expect(t.element, same(tElement));
+  }
+
+  void test_genericMethod_typeParameter() {
+    String code = r'''
+class C {
+  /*=T*/ max/*<T>*/(/*=T*/ x, /*=T*/ y) => null;
+}
+''';
+    CompilationUnit unit = resolveSource(code);
+    MethodDeclaration node = _findSimpleIdentifier(unit, code, 'max').parent;
+    TypeParameter t = node.typeParameters.typeParameters[0];
+
+    MethodElement element = node.name.staticElement;
+    TypeParameterElement tElement = element.typeParameters[0];
+    expect(tElement, isNotNull);
+    expect(element.typeParameters.toString(), "[T]");
+    expect(element.type.toString(), "<T>(T, T) → T");
+    expect(t.element, same(tElement));
+
+    // re-resolve
+    CompilationUnit unit2 = _cloneResolveUnit(unit);
+    node = _findSimpleIdentifier(unit2, code, 'max').parent;
+    t = node.typeParameters.typeParameters[0];
+    expect(t.element, same(tElement));
   }
 }
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
index a404b92..e2b20b3 100644
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ b/pkg/analyzer/test/generated/engine_test.dart
@@ -348,6 +348,12 @@
   }
 
   @override
+  bool aboutToComputeResult(CacheEntry entry, ResultDescriptor result) {
+    fail("Unexpected invocation of aboutToComputeResult");
+    return false;
+  }
+
+  @override
   void addListener(AnalysisListener listener) {
     fail("Unexpected invocation of addListener");
   }
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index ca12036..6a52fce 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -25,7 +25,6 @@
 import 'package:unittest/unittest.dart';
 
 import '../reflective_tests.dart';
-import 'parser_test.dart';
 import 'resolver_test.dart';
 import 'test_support.dart';
 
@@ -1547,6 +1546,34 @@
 ''');
   }
 
+  void test_false_method_getKeyword_add() {
+    _assertDoesNotMatchOK(
+        r'''
+class A {
+  void foo() {}
+}
+''',
+        r'''
+class A {
+  void get foo {}
+}
+''');
+  }
+
+  void test_false_method_getKeyword_remove() {
+    _assertDoesNotMatchOK(
+        r'''
+class A {
+  void get foo {}
+}
+''',
+        r'''
+class A {
+  void foo() {}
+}
+''');
+  }
+
   void test_false_method_list_add() {
     _assertDoesNotMatchOK(
         r'''
@@ -1641,6 +1668,34 @@
 ''');
   }
 
+  void test_false_method_setKeyword_add() {
+    _assertDoesNotMatchOK(
+        r'''
+class A {
+  void foo(x) {}
+}
+''',
+        r'''
+class A {
+  void set foo(x) {}
+}
+''');
+  }
+
+  void test_false_method_setKeyword_remove() {
+    _assertDoesNotMatchOK(
+        r'''
+class A {
+  void set foo(x) {}
+}
+''',
+        r'''
+class A {
+  void foo(x) {}
+}
+''');
+  }
+
   void test_false_part_list_add() {
     addNamedSource('/unitA.dart', 'part of lib; class A {}');
     addNamedSource('/unitB.dart', 'part of lib; class B {}');
@@ -3003,7 +3058,7 @@
     LibraryElement library = resolve2(source);
     CompilationUnit oldUnit = resolveCompilationUnit(source, library);
     // parse
-    CompilationUnit newUnit = ParserTestCase.parseCompilationUnit(newContent);
+    CompilationUnit newUnit = IncrementalResolverTest._parseUnit(newContent);
     // build elements
     {
       ElementHolder holder = new ElementHolder();
@@ -3990,6 +4045,27 @@
 ''');
   }
 
+  void test_inBody_functionExpression() {
+    _resolveUnit(r'''
+class C extends D {
+  static final f = () {
+    var x = 0;
+  }();
+}
+
+class D {}
+''');
+    _updateAndValidate(r'''
+class C extends D {
+  static final f = () {
+    var x = 01;
+  }();
+}
+
+class D {}
+''');
+  }
+
   void test_inBody_insertStatement() {
     _resolveUnit(r'''
 main() {
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 96a4b3e..0f43183 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -7038,6 +7038,30 @@
     expect(declaration.propertyKeyword, isNull);
   }
 
+  void test_parseCompilationUnitMember_function_generic_noReturnType() {
+    enableGenericMethods = true;
+    FunctionDeclaration declaration = parse("parseCompilationUnitMember",
+        <Object>[emptyCommentAndMetadata()], "f<E>() {}");
+    expect(declaration.returnType, isNull);
+    expect(declaration.functionExpression.typeParameters, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_function_generic_returnType() {
+    enableGenericMethods = true;
+    FunctionDeclaration declaration = parse("parseCompilationUnitMember",
+        <Object>[emptyCommentAndMetadata()], "E f<E>() {}");
+    expect(declaration.returnType, isNotNull);
+    expect(declaration.functionExpression.typeParameters, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_function_generic_void() {
+    enableGenericMethods = true;
+    FunctionDeclaration declaration = parse("parseCompilationUnitMember",
+        <Object>[emptyCommentAndMetadata()], "void f<T>(T t) {}");
+    expect(declaration.functionExpression, isNotNull);
+    expect(declaration.propertyKeyword, isNull);
+  }
+
   void test_parseCompilationUnitMember_function_noType() {
     FunctionDeclaration declaration = parse("parseCompilationUnitMember",
         <Object>[emptyCommentAndMetadata()], "f() {}");
@@ -7058,14 +7082,6 @@
     expect(declaration.returnType, isNotNull);
   }
 
-  void test_parseCompilationUnitMember_function_withTypeParameters() {
-    enableGenericMethods = true;
-    FunctionDeclaration declaration = parse("parseCompilationUnitMember",
-        <Object>[emptyCommentAndMetadata()], "void f<T>(T t) {}");
-    expect(declaration.functionExpression, isNotNull);
-    expect(declaration.propertyKeyword, isNull);
-  }
-
   void test_parseCompilationUnitMember_getter_external_noType() {
     FunctionDeclaration declaration = parse("parseCompilationUnitMember",
         <Object>[emptyCommentAndMetadata()], "external get p;");
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 8c24fb2..1f1f2a5 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -201,8 +201,8 @@
         'onValue', futureThenR, [futureElement.typeParameters[0]], null);
 
     DartType futureRType = futureElement.type.substitute4([futureThenR.type]);
-    MethodElementImpl thenMethod = ElementFactory.methodElementWithParameters(
-        futureElement, "then", futureRType, [
+    MethodElementImpl thenMethod = ElementFactory
+        .methodElementWithParameters(futureElement, "then", futureRType, [
       ElementFactory.requiredParameter2("onValue", thenOnValue.type),
       ElementFactory.namedParameter2("onError", provider.functionType)
     ]);
@@ -291,8 +291,8 @@
     ClassElementImpl htmlDocumentElement =
         ElementFactory.classElement("HtmlDocument", documentElement.type);
     htmlDocumentElement.methods = <MethodElement>[
-      ElementFactory.methodElement(
-          "query", elementType, <DartType>[provider.stringType])
+      ElementFactory
+          .methodElement("query", elementType, <DartType>[provider.stringType])
     ];
     htmlUnit.types = <ClassElement>[
       ElementFactory.classElement("AnchorElement", elementType),
@@ -312,8 +312,8 @@
       ElementFactory.functionElement3("query", elementElement,
           <ClassElement>[provider.stringType.element], ClassElement.EMPTY_LIST)
     ];
-    TopLevelVariableElementImpl document = ElementFactory
-        .topLevelVariableElement3(
+    TopLevelVariableElementImpl document =
+        ElementFactory.topLevelVariableElement3(
             "document", false, true, htmlDocumentElement.type);
     htmlUnit.topLevelVariables = <TopLevelVariableElement>[document];
     htmlUnit.accessors = <PropertyAccessorElement>[document.getter];
@@ -5153,7 +5153,8 @@
     _assertNoErrors(classA);
   }
 
-  void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_getter_method() {
+  void
+      test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_getter_method() {
     // class I1 { int m(); }
     // class I2 { int get m; }
     // class A implements I2, I1 {}
@@ -5176,7 +5177,8 @@
         [StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD]);
   }
 
-  void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_int_str() {
+  void
+      test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_int_str() {
     // class I1 { int m(); }
     // class I2 { String m(); }
     // class A implements I1, I2 {}
@@ -5186,8 +5188,8 @@
         ElementFactory.methodElement(methodName, null, [_typeProvider.intType]);
     classI1.methods = <MethodElement>[methodM1];
     ClassElementImpl classI2 = ElementFactory.classElement2("I2");
-    MethodElement methodM2 = ElementFactory.methodElement(
-        methodName, null, [_typeProvider.stringType]);
+    MethodElement methodM2 = ElementFactory
+        .methodElement(methodName, null, [_typeProvider.stringType]);
     classI2.methods = <MethodElement>[methodM2];
     ClassElementImpl classA = ElementFactory.classElement2("A");
     classA.interfaces = <InterfaceType>[classI1.type, classI2.type];
@@ -5199,7 +5201,8 @@
         classA, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]);
   }
 
-  void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_method_getter() {
+  void
+      test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_method_getter() {
     // class I1 { int m(); }
     // class I2 { int get m; }
     // class A implements I1, I2 {}
@@ -5222,7 +5225,8 @@
         [StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD]);
   }
 
-  void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_numOfRequiredParams() {
+  void
+      test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_numOfRequiredParams() {
     // class I1 { dynamic m(int, [int]); }
     // class I2 { dynamic m(int, int, int); }
     // class A implements I1, I2 {}
@@ -5271,14 +5275,15 @@
         classA, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]);
   }
 
-  void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_str_int() {
+  void
+      test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_str_int() {
     // class I1 { int m(); }
     // class I2 { String m(); }
     // class A implements I2, I1 {}
     ClassElementImpl classI1 = ElementFactory.classElement2("I1");
     String methodName = "m";
-    MethodElement methodM1 = ElementFactory.methodElement(
-        methodName, null, [_typeProvider.stringType]);
+    MethodElement methodM1 = ElementFactory
+        .methodElement(methodName, null, [_typeProvider.stringType]);
     classI1.methods = <MethodElement>[methodM1];
     ClassElementImpl classI2 = ElementFactory.classElement2("I2");
     MethodElement methodM2 =
@@ -5380,7 +5385,8 @@
     _assertNoErrors(classA);
   }
 
-  void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_getters() {
+  void
+      test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_getters() {
     // class I1 { int get g; }
     // class I2 { num get g; }
     // class A implements I1, I2 {}
@@ -5404,7 +5410,8 @@
     _assertNoErrors(classA);
   }
 
-  void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_methods() {
+  void
+      test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_methods() {
     // class I1 { dynamic m(int); }
     // class I2 { dynamic m(num); }
     // class A implements I1, I2 {}
@@ -5438,7 +5445,8 @@
     _assertNoErrors(classA);
   }
 
-  void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_setters() {
+  void
+      test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_setters() {
     // class I1 { set s(int); }
     // class I2 { set s(num); }
     // class A implements I1, I2 {}
@@ -5463,7 +5471,8 @@
     _assertNoErrors(classA);
   }
 
-  void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_getters() {
+  void
+      test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_getters() {
     // class A {}
     // class B extends A {}
     // class C extends B {}
@@ -5502,7 +5511,8 @@
     _assertNoErrors(classD);
   }
 
-  void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_methods() {
+  void
+      test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_methods() {
     // class A {}
     // class B extends A {}
     // class C extends B {}
@@ -5556,7 +5566,8 @@
     _assertNoErrors(classD);
   }
 
-  void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_setters() {
+  void
+      test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_setters() {
     // class A {}
     // class B extends A {}
     // class C extends B {}
@@ -5596,7 +5607,8 @@
     _assertNoErrors(classD);
   }
 
-  void test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_2_methods() {
+  void
+      test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_2_methods() {
     // class I1 { int m(); }
     // class I2 { int m([int]); }
     // class A implements I1, I2 {}
@@ -5623,7 +5635,8 @@
     _assertNoErrors(classA);
   }
 
-  void test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_3_methods() {
+  void
+      test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_3_methods() {
     // class I1 { int m(); }
     // class I2 { int m([int]); }
     // class I3 { int m([int, int]); }
@@ -5668,7 +5681,8 @@
     _assertNoErrors(classA);
   }
 
-  void test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_4_methods() {
+  void
+      test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_4_methods() {
     // class I1 { int m(); }
     // class I2 { int m(); }
     // class I3 { int m([int]); }
@@ -9370,7 +9384,9 @@
     expect(declarations, hasLength(2));
     Element expectedElement = (declarations[0] as TopLevelVariableDeclaration)
         .variables
-        .variables[0].name.staticElement;
+        .variables[0]
+        .name
+        .staticElement;
     EngineTestCase.assertInstanceOf((obj) => obj is PropertyInducingElement,
         PropertyInducingElement, expectedElement);
     expectedElement = (expectedElement as PropertyInducingElement).getter;
@@ -9561,7 +9577,9 @@
     expect(declarations, hasLength(2));
     Element expectedElement = (declarations[0] as TopLevelVariableDeclaration)
         .variables
-        .variables[0].name.staticElement;
+        .variables[0]
+        .name
+        .staticElement;
     EngineTestCase.assertInstanceOf((obj) => obj is PropertyInducingElement,
         PropertyInducingElement, expectedElement);
     expectedElement = (expectedElement as PropertyInducingElement).getter;
@@ -11782,19 +11800,27 @@
 @reflectiveTest
 class StrongModeDownwardsInferenceTest extends ResolverTestCase {
   TypeAssertions _assertions;
-  AsserterBuilder<Element, DartType> _hasElement;
-  AsserterBuilder<DartType, DartType> _isType;
-  AsserterBuilder2<Asserter<DartType>, Asserter<DartType>,
-      DartType> _isFunction2Of;
-  AsserterBuilderBuilder<Asserter<DartType>, List<Asserter<DartType>>,
-      DartType> _isInstantiationOf;
+
+  Asserter<DartType> _isDynamic;
+  Asserter<InterfaceType> _isFutureOfDynamic;
+  Asserter<InterfaceType> _isFutureOfInt;
   Asserter<DartType> _isInt;
   Asserter<DartType> _isNum;
   Asserter<DartType> _isString;
-  Asserter<DartType> _isDynamic;
+
+  AsserterBuilder2<Asserter<DartType>, Asserter<DartType>, DartType>
+      _isFunction2Of;
+  AsserterBuilder<List<Asserter<DartType>>, InterfaceType> _isFutureOf;
+  AsserterBuilderBuilder<Asserter<DartType>, List<Asserter<DartType>>, DartType>
+      _isInstantiationOf;
   AsserterBuilder<Asserter<DartType>, InterfaceType> _isListOf;
-  AsserterBuilder2<Asserter<DartType>, Asserter<DartType>,
-      InterfaceType> _isMapOf;
+  AsserterBuilder2<Asserter<DartType>, Asserter<DartType>, InterfaceType>
+      _isMapOf;
+  AsserterBuilder<List<Asserter<DartType>>, InterfaceType> _isStreamOf;
+  AsserterBuilder<DartType, DartType> _isType;
+
+  AsserterBuilder<Element, DartType> _hasElement;
+  AsserterBuilder<DartType, DartType> _sameElement;
 
   @override
   void setUp() {
@@ -11812,6 +11838,187 @@
     _isListOf = _assertions.isListOf;
     _isMapOf = _assertions.isMapOf;
     _isFunction2Of = _assertions.isFunction2Of;
+    _sameElement = _assertions.sameElement;
+    _isFutureOf = _isInstantiationOf(_sameElement(typeProvider.futureType));
+    _isFutureOfDynamic = _isFutureOf([_isDynamic]);
+    _isFutureOfInt = _isFutureOf([_isInt]);
+    _isStreamOf = _isInstantiationOf(_sameElement(typeProvider.streamType));
+  }
+
+  void test_async_method_propagation() {
+    String code = r'''
+      import "dart:async";
+      class A {
+        Future f0() => new Future.value(3);
+        Future f1() async => new Future.value(3);
+        Future f2() async => await new Future.value(3);
+
+        Future<int> f3() => new Future.value(3);
+        Future<int> f4() async => new Future.value(3);
+        Future<int> f5() async => await new Future.value(3);
+
+        Future g0() { return new Future.value(3); }
+        Future g1() async { return new Future.value(3); }
+        Future g2() async { return await new Future.value(3); }
+
+        Future<int> g3() { return new Future.value(3); }
+        Future<int> g4() async { return new Future.value(3); }
+        Future<int> g5() async { return await new Future.value(3); }
+      }
+   ''';
+    CompilationUnit unit = resolveSource(code);
+
+    void check(String name, Asserter<InterfaceType> typeTest) {
+      MethodDeclaration test = AstFinder.getMethodInClass(unit, "A", name);
+      FunctionBody body = test.body;
+      Expression returnExp;
+      if (body is ExpressionFunctionBody) {
+        returnExp = body.expression;
+      } else {
+        ReturnStatement stmt = (body as BlockFunctionBody).block.statements[0];
+        returnExp = stmt.expression;
+      }
+      DartType type = returnExp.staticType;
+      if (returnExp is AwaitExpression) {
+        type = returnExp.expression.staticType;
+      }
+      typeTest(type);
+    }
+
+    check("f0", _isFutureOfDynamic);
+    check("f1", _isFutureOfDynamic);
+    check("f2", _isFutureOfDynamic);
+
+    check("f3", _isFutureOfInt);
+    // This should be int when we handle the implicit Future<T> | T union
+    // https://github.com/dart-lang/sdk/issues/25322
+    check("f4", _isFutureOfDynamic);
+    check("f5", _isFutureOfInt);
+
+    check("g0", _isFutureOfDynamic);
+    check("g1", _isFutureOfDynamic);
+    check("g2", _isFutureOfDynamic);
+
+    check("g3", _isFutureOfInt);
+    // This should be int when we handle the implicit Future<T> | T union
+    // https://github.com/dart-lang/sdk/issues/25322
+    check("g4", _isFutureOfDynamic);
+    check("g5", _isFutureOfInt);
+  }
+
+  void test_async_propagation() {
+    String code = r'''
+      import "dart:async";
+
+      Future f0() => new Future.value(3);
+      Future f1() async => new Future.value(3);
+      Future f2() async => await new Future.value(3);
+
+      Future<int> f3() => new Future.value(3);
+      Future<int> f4() async => new Future.value(3);
+      Future<int> f5() async => await new Future.value(3);
+
+      Future g0() { return new Future.value(3); }
+      Future g1() async { return new Future.value(3); }
+      Future g2() async { return await new Future.value(3); }
+
+      Future<int> g3() { return new Future.value(3); }
+      Future<int> g4() async { return new Future.value(3); }
+      Future<int> g5() async { return await new Future.value(3); }
+   ''';
+    CompilationUnit unit = resolveSource(code);
+
+    void check(String name, Asserter<InterfaceType> typeTest) {
+      FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, name);
+      FunctionBody body = test.functionExpression.body;
+      Expression returnExp;
+      if (body is ExpressionFunctionBody) {
+        returnExp = body.expression;
+      } else {
+        ReturnStatement stmt = (body as BlockFunctionBody).block.statements[0];
+        returnExp = stmt.expression;
+      }
+      DartType type = returnExp.staticType;
+      if (returnExp is AwaitExpression) {
+        type = returnExp.expression.staticType;
+      }
+      typeTest(type);
+    }
+
+    check("f0", _isFutureOfDynamic);
+    check("f1", _isFutureOfDynamic);
+    check("f2", _isFutureOfDynamic);
+
+    check("f3", _isFutureOfInt);
+    // This should be int when we handle the implicit Future<T> | T union
+    // https://github.com/dart-lang/sdk/issues/25322
+    check("f4", _isFutureOfDynamic);
+    check("f5", _isFutureOfInt);
+
+    check("g0", _isFutureOfDynamic);
+    check("g1", _isFutureOfDynamic);
+    check("g2", _isFutureOfDynamic);
+
+    check("g3", _isFutureOfInt);
+    // This should be int when we handle the implicit Future<T> | T union
+    // https://github.com/dart-lang/sdk/issues/25322
+    check("g4", _isFutureOfDynamic);
+    check("g5", _isFutureOfInt);
+  }
+
+  void test_async_star_method_propagation() {
+    String code = r'''
+      import "dart:async";
+      class A {
+        Stream g0() async* { yield []; }
+        Stream g1() async* { yield* new Stream(); }
+
+        Stream<List<int>> g2() async* { yield []; }
+        Stream<List<int>> g3() async* { yield* new Stream(); }
+      }
+    ''';
+    CompilationUnit unit = resolveSource(code);
+
+    void check(String name, Asserter<InterfaceType> typeTest) {
+      MethodDeclaration test = AstFinder.getMethodInClass(unit, "A", name);
+      BlockFunctionBody body = test.body;
+      YieldStatement stmt = body.block.statements[0];
+      Expression exp = stmt.expression;
+      typeTest(exp.staticType);
+    }
+
+    check("g0", _isListOf(_isDynamic));
+    check("g1", _isStreamOf([_isDynamic]));
+
+    check("g2", _isListOf(_isInt));
+    check("g3", _isStreamOf([_isListOf(_isInt)]));
+  }
+
+  void test_async_star_propagation() {
+    String code = r'''
+      import "dart:async";
+
+      Stream g0() async* { yield []; }
+      Stream g1() async* { yield* new Stream(); }
+
+      Stream<List<int>> g2() async* { yield []; }
+      Stream<List<int>> g3() async* { yield* new Stream(); }
+   ''';
+    CompilationUnit unit = resolveSource(code);
+
+    void check(String name, Asserter<InterfaceType> typeTest) {
+      FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, name);
+      BlockFunctionBody body = test.functionExpression.body;
+      YieldStatement stmt = body.block.statements[0];
+      Expression exp = stmt.expression;
+      typeTest(exp.staticType);
+    }
+
+    check("g0", _isListOf(_isDynamic));
+    check("g1", _isStreamOf([_isDynamic]));
+
+    check("g2", _isListOf(_isInt));
+    check("g3", _isStreamOf([_isListOf(_isInt)]));
   }
 
   void test_cascadeExpression() {
@@ -12751,6 +12958,61 @@
     Expression exp = invocation.argumentList.arguments[0];
     _isListOf(_isString)(exp.staticType);
   }
+
+  void test_sync_star_method_propagation() {
+    String code = r'''
+      import "dart:async";
+      class A {
+        Iterable f0() sync* { yield []; }
+        Iterable f1() sync* { yield* new List(); }
+
+        Iterable<List<int>> f2() sync* { yield []; }
+        Iterable<List<int>> f3() sync* { yield* new List(); }
+      }
+   ''';
+    CompilationUnit unit = resolveSource(code);
+
+    void check(String name, Asserter<InterfaceType> typeTest) {
+      MethodDeclaration test = AstFinder.getMethodInClass(unit, "A", name);
+      BlockFunctionBody body = test.body;
+      YieldStatement stmt = body.block.statements[0];
+      Expression exp = stmt.expression;
+      typeTest(exp.staticType);
+    }
+
+    check("f0", _isListOf(_isDynamic));
+    check("f1", _isListOf(_isDynamic));
+
+    check("f2", _isListOf(_isInt));
+    check("f3", _isListOf(_isListOf(_isInt)));
+  }
+
+  void test_sync_star_propagation() {
+    String code = r'''
+      import "dart:async";
+
+      Iterable f0() sync* { yield []; }
+      Iterable f1() sync* { yield* new List(); }
+
+      Iterable<List<int>> f2() sync* { yield []; }
+      Iterable<List<int>> f3() sync* { yield* new List(); }
+   ''';
+    CompilationUnit unit = resolveSource(code);
+
+    void check(String name, Asserter<InterfaceType> typeTest) {
+      FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, name);
+      BlockFunctionBody body = test.functionExpression.body;
+      YieldStatement stmt = body.block.statements[0];
+      Expression exp = stmt.expression;
+      typeTest(exp.staticType);
+    }
+
+    check("f0", _isListOf(_isDynamic));
+    check("f1", _isListOf(_isDynamic));
+
+    check("f2", _isListOf(_isInt));
+    check("f3", _isListOf(_isListOf(_isInt)));
+  }
 }
 
 /**
@@ -14025,7 +14287,8 @@
         code, typeProvider.dynamicType, typeProvider.intType);
   }
 
-  void test_finalPropertyInducingVariable_classMember_instance_propagatedTarget() {
+  void
+      test_finalPropertyInducingVariable_classMember_instance_propagatedTarget() {
     addNamedSource(
         "/lib.dart",
         r'''
@@ -14244,7 +14507,8 @@
     expect(vParameter.identifier.propagatedType, same(stringType));
   }
 
-  void test_functionExpression_asInvocationArgument_functionExpressionInvocation() {
+  void
+      test_functionExpression_asInvocationArgument_functionExpressionInvocation() {
     String code = r'''
 main() {
   (f(String value)) {} ((v) {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_test.dart b/pkg/analyzer/test/src/summary/resynthesize_test.dart
index cffd7d9..642b60b 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_test.dart
@@ -6,7 +6,7 @@
 
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/summary/builder.dart';
+import 'package:analyzer/src/summary/base.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/resynthesize.dart';
 import 'package:analyzer/src/summary/summarize_elements.dart';
@@ -349,9 +349,11 @@
     // TODO(paulberry): test evaluationResult
   }
 
-  void compareTypeImpls(TypeImpl resynthesized, TypeImpl original) {
-    expect(resynthesized.element.location, original.element.location);
-    expect(resynthesized.name, original.name);
+  void compareTypeImpls(
+      TypeImpl resynthesized, TypeImpl original, String desc) {
+    expect(resynthesized.element.location, original.element.location,
+        reason: desc);
+    expect(resynthesized.name, original.name, reason: desc);
   }
 
   void compareTypeParameterElements(TypeParameterElementImpl resynthesized,
@@ -366,7 +368,7 @@
       expect(resynthesized, isNull, reason: desc);
     } else if (resynthesized is InterfaceTypeImpl &&
         original is InterfaceTypeImpl) {
-      compareTypeImpls(resynthesized, original);
+      compareTypeImpls(resynthesized, original, desc);
       expect(resynthesized.typeArguments.length, original.typeArguments.length);
       for (int i = 0; i < resynthesized.typeArguments.length; i++) {
         compareTypes(resynthesized.typeArguments[i], original.typeArguments[i],
@@ -374,7 +376,7 @@
       }
     } else if (resynthesized is TypeParameterTypeImpl &&
         original is TypeParameterTypeImpl) {
-      compareTypeImpls(resynthesized, original);
+      compareTypeImpls(resynthesized, original, desc);
     } else if (resynthesized is DynamicTypeImpl &&
         original is DynamicTypeImpl) {
       expect(resynthesized, same(original));
@@ -383,17 +385,38 @@
       expect(resynthesized, same(original));
     } else if (resynthesized is FunctionTypeImpl &&
         original is FunctionTypeImpl) {
-      compareTypeImpls(resynthesized, original);
+      compareTypeImpls(resynthesized, original, desc);
       if (original.element.isSynthetic &&
           original.element is FunctionTypeAliasElementImpl &&
           resynthesized.element is FunctionTypeAliasElementImpl) {
         compareFunctionTypeAliasElements(
             resynthesized.element, original.element, desc);
       }
+      expect(resynthesized.typeArguments.length, original.typeArguments.length,
+          reason: desc);
       for (int i = 0; i < resynthesized.typeArguments.length; i++) {
         compareTypes(resynthesized.typeArguments[i], original.typeArguments[i],
             '$desc type argument ${original.typeArguments[i].name}');
       }
+      if (original.typeParameters == null) {
+        expect(resynthesized.typeParameters, isNull, reason: desc);
+      } else {
+        expect(resynthesized.typeParameters, isNotNull, reason: desc);
+        expect(
+            resynthesized.typeParameters.length, original.typeParameters.length,
+            reason: desc);
+        for (int i = 0; i < resynthesized.typeParameters.length; i++) {
+          compareTypeParameterElements(resynthesized.typeParameters[i],
+              original.typeParameters[i], '$desc type parameter $i');
+        }
+      }
+      expect(resynthesized.boundTypeParameters.length,
+          original.boundTypeParameters.length,
+          reason: desc);
+      for (int i = 0; i < resynthesized.boundTypeParameters.length; i++) {
+        compareTypeParameterElements(resynthesized.boundTypeParameters[i],
+            original.boundTypeParameters[i], '$desc bound type parameter $i');
+      }
     } else if (resynthesized is VoidTypeImpl && original is VoidTypeImpl) {
       expect(resynthesized, same(original));
     } else if (resynthesized.runtimeType != original.runtimeType) {
@@ -463,6 +486,7 @@
     }
     SummaryResynthesizer resynthesizer = new SummaryResynthesizer(
         analysisContext,
+        analysisContext.typeProvider,
         getPrelinkedSummary,
         getUnlinkedSummary,
         analysisContext.sourceFactory);
@@ -599,6 +623,14 @@
     checkLibrary('class C { int get x => null; get y => null; }');
   }
 
+  test_class_implicitField_getterFirst() {
+    checkLibrary('class C { int get x => 0; void set x(int value) {} }');
+  }
+
+  test_class_implicitField_setterFirst() {
+    checkLibrary('class C { void set x(int value) {} int get x => 0; }');
+  }
+
   test_class_interfaces() {
     checkLibrary('class C implements D, E {} class D {} class E {}');
   }
@@ -942,6 +974,13 @@
     checkLibrary('import "a.dart"; C c; E e; F f;');
   }
 
+  test_type_reference_to_import_part2() {
+    addLibrarySource('/a.dart', 'library l; part "p1.dart"; part "p2.dart";');
+    addNamedSource('/p1.dart', 'part of l; class C1 {}');
+    addNamedSource('/p2.dart', 'part of l; class C2 {}');
+    checkLibrary('import "a.dart"; C1 c1; C2 c2;');
+  }
+
   test_type_reference_to_import_part_in_subdir() {
     addLibrarySource('/a/b.dart', 'library l; part "c.dart";');
     addNamedSource(
diff --git a/pkg/analyzer/test/src/summary/summary_test.dart b/pkg/analyzer/test/src/summary/summary_test.dart
index a658d2b..e9d46b4 100644
--- a/pkg/analyzer/test/src/summary/summary_test.dart
+++ b/pkg/analyzer/test/src/summary/summary_test.dart
@@ -5,11 +5,18 @@
 library analyzer.test.src.summary.summary_test;
 
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_engine_io.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/summary/builder.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/summary/base.dart';
 import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/public_namespace_computer.dart'
+    as public_namespace;
 import 'package:analyzer/src/summary/summarize_elements.dart'
     as summarize_elements;
 import 'package:unittest/unittest.dart';
@@ -27,10 +34,54 @@
  */
 @reflectiveTest
 class SummarizeElementsTest extends ResolverTestCase with SummaryTest {
+  final BuilderContext builderContext = new BuilderContext();
+
+  /**
+   * The list of absolute unit URIs corresponding to the compilation units in
+   * [unlinkedUnits].
+   */
+  List<String> unitUris;
+
   @override
   bool get checkAstDerivedData => false;
 
   /**
+   * Convert a summary object (or a portion of one) into a canonical form that
+   * can be easily compared using [expect].  If [orderByName] is true, and the
+   * object is a [List], it is sorted by the `name` field of its elements.
+   */
+  Object canonicalize(Object obj, {bool orderByName: false}) {
+    if (obj is SummaryClass) {
+      Map<String, Object> result = <String, Object>{};
+      obj.toMap().forEach((String key, Object value) {
+        bool orderByName = false;
+        if (obj is UnlinkedPublicNamespace && key == 'names') {
+          orderByName = true;
+        }
+        result[key] = canonicalize(value, orderByName: orderByName);
+      });
+      return result;
+    } else if (obj is List) {
+      List<Object> result = <Object>[];
+      for (Object item in obj) {
+        result.add(canonicalize(item));
+      }
+      if (orderByName) {
+        result.sort((Object a, Object b) {
+          if (a is Map && b is Map) {
+            return Comparable.compare(a['name'], b['name']);
+          } else {
+            return 0;
+          }
+        });
+      }
+      return result;
+    } else {
+      return obj;
+    }
+  }
+
+  /**
    * Serialize the library containing the given class [element], then
    * deserialize it and return the summary of the class.
    */
@@ -41,10 +92,9 @@
 
   /**
    * Serialize the given [library] element, then deserialize it and store the
-   * resulting summary in [lib].
+   * resulting summary in [prelinked] and [unlinkedUnits].
    */
   void serializeLibraryElement(LibraryElement library) {
-    BuilderContext builderContext = new BuilderContext();
     summarize_elements.LibrarySerializationResult serializedLib =
         summarize_elements.serializeLibrary(
             builderContext, library, typeProvider);
@@ -54,6 +104,7 @@
         .map((UnlinkedUnitBuilder b) =>
             new UnlinkedUnit.fromBuffer(b.toBuffer()))
         .toList();
+    unitUris = serializedLib.unitUris;
   }
 
   @override
@@ -71,6 +122,7 @@
       expect(unlinkedUnits[i].references.length,
           prelinked.units[i].references.length);
     }
+    verifyPublicNamespace();
   }
 
   @override
@@ -86,6 +138,30 @@
     expect(cls.supertype, isNull);
     expect(cls.hasNoSupertype, isTrue);
   }
+
+  /**
+   * Verify that [public_namespace.computePublicNamespace] produces data that's
+   * equivalent to that produced by [summarize_elements.serializeLibrary].
+   */
+  void verifyPublicNamespace() {
+    for (int i = 0; i < unlinkedUnits.length; i++) {
+      Source source = analysisContext.sourceFactory.forUri(unitUris[i]);
+      String text = analysisContext.getContents(source).data;
+      CharacterReader reader = new CharSequenceReader(text);
+      Scanner scanner =
+          new Scanner(source, reader, AnalysisErrorListener.NULL_LISTENER);
+      Parser parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER);
+      parser.parseGenericMethods = true;
+      CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize());
+      UnlinkedPublicNamespace namespace =
+          new UnlinkedPublicNamespace.fromBuffer(public_namespace
+              .computePublicNamespace(builderContext, unit)
+              .toBuffer());
+      expect(canonicalize(namespace),
+          canonicalize(unlinkedUnits[i].publicNamespace),
+          reason: 'publicNamespace(${unitUris[i]})');
+    }
+  }
 }
 
 /**
@@ -135,16 +211,6 @@
   addNamedSource(String filePath, String contents);
 
   /**
-   * Verify that the [combinatorName] correctly represents the given [expected]
-   * name.
-   */
-  void checkCombinatorName(
-      UnlinkedCombinatorName combinatorName, String expected) {
-    expect(combinatorName, new isInstanceOf<UnlinkedCombinatorName>());
-    expect(combinatorName.name, expected);
-  }
-
-  /**
    * Verify that the [dependency]th element of the dependency table represents
    * a file reachable via the given [absoluteUri] and [relativeUri].
    */
@@ -239,7 +305,8 @@
    * specified they are assumed to refer to the defining compilation unit.
    * [expectedTargetUnit] is the index of the compilation unit in which the
    * target of the [typeRef] is expected to appear; if not specified it is
-   * assumed to be the defining compilation unit.
+   * assumed to be the defining compilation unit.  [numTypeParameters] is the
+   * number of type parameters of the thing being referred to.
    */
   void checkTypeRef(UnlinkedTypeRef typeRef, String absoluteUri,
       String relativeUri, String expectedName,
@@ -248,7 +315,8 @@
       PrelinkedReferenceKind expectedKind: PrelinkedReferenceKind.classOrEnum,
       int expectedTargetUnit: 0,
       PrelinkedUnit prelinkedSourceUnit,
-      UnlinkedUnit unlinkedSourceUnit}) {
+      UnlinkedUnit unlinkedSourceUnit,
+      int numTypeParameters: 0}) {
     prelinkedSourceUnit ??= definingUnit;
     unlinkedSourceUnit ??= unlinkedUnits[0];
     expect(typeRef, new isInstanceOf<UnlinkedTypeRef>());
@@ -284,6 +352,7 @@
     }
     expect(referenceResolution.kind, expectedKind);
     expect(referenceResolution.unit, expectedTargetUnit);
+    expect(referenceResolution.numTypeParameters, numTypeParameters);
   }
 
   /**
@@ -492,7 +561,8 @@
   UnlinkedTypeRef serializeTypeText(String text,
       {String otherDeclarations: '', bool allowErrors: false}) {
     return serializeVariableText('$otherDeclarations\n$text v;',
-        allowErrors: allowErrors).type;
+            allowErrors: allowErrors)
+        .type;
   }
 
   /**
@@ -646,8 +716,12 @@
 
   test_class_alias_concrete() {
     UnlinkedClass cls =
-        serializeClassText('class C = D with E; class D {} class E {}');
+        serializeClassText('class C = _D with _E; class _D {} class _E {}');
     expect(cls.isAbstract, false);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+        PrelinkedReferenceKind.classOrEnum);
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
   }
 
   test_class_alias_flag() {
@@ -680,6 +754,26 @@
     expect(cls.executables, isEmpty);
   }
 
+  test_class_alias_private() {
+    serializeClassText('class _C = _D with _E; class _D {} class _E {}', '_C');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+  }
+
+  test_class_alias_reference_generic() {
+    UnlinkedTypeRef typeRef = serializeTypeText('C',
+        otherDeclarations: 'class C<D, E> = F with G; class F {} class G {}');
+    checkTypeRef(typeRef, null, null, 'C', numTypeParameters: 2);
+  }
+
+  test_class_alias_reference_generic_imported() {
+    addNamedSource(
+        '/lib.dart', 'class C<D, E> = F with G; class F {} class G {}');
+    UnlinkedTypeRef typeRef =
+        serializeTypeText('C', otherDeclarations: 'import "lib.dart";');
+    checkTypeRef(typeRef, absUri('/lib.dart'), 'lib.dart', 'C',
+        numTypeParameters: 2);
+  }
+
   test_class_alias_supertype() {
     UnlinkedClass cls =
         serializeClassText('class C = D with E; class D {} class E {}');
@@ -690,6 +784,10 @@
   test_class_concrete() {
     UnlinkedClass cls = serializeClassText('class C {}');
     expect(cls.isAbstract, false);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+        PrelinkedReferenceKind.classOrEnum);
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
   }
 
   test_class_interface() {
@@ -764,6 +862,25 @@
     expect(cls.isMixinApplication, false);
   }
 
+  test_class_private() {
+    serializeClassText('class _C {}', '_C');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+  }
+
+  test_class_reference_generic() {
+    UnlinkedTypeRef typeRef =
+        serializeTypeText('C', otherDeclarations: 'class C<D, E> {}');
+    checkTypeRef(typeRef, null, null, 'C', numTypeParameters: 2);
+  }
+
+  test_class_reference_generic_imported() {
+    addNamedSource('/lib.dart', 'class C<D, E> {}');
+    UnlinkedTypeRef typeRef =
+        serializeTypeText('C', otherDeclarations: 'import "lib.dart";');
+    checkTypeRef(typeRef, absUri('/lib.dart'), 'lib.dart', 'C',
+        numTypeParameters: 2);
+  }
+
   test_class_superclass() {
     UnlinkedClass cls = serializeClassText('class C {}');
     expect(cls.supertype, isNull);
@@ -783,7 +900,7 @@
     expect(cls.typeParameters[0].name, 'T');
     expect(cls.typeParameters[0].bound, isNotNull);
     checkTypeRef(cls.typeParameters[0].bound, 'dart:core', 'dart:core', 'List',
-        allowTypeParameters: true);
+        allowTypeParameters: true, numTypeParameters: 1);
   }
 
   test_class_type_param_f_bound() {
@@ -901,7 +1018,7 @@
     checkDynamicTypeRef(parameter.type);
   }
 
-  test_constructor_initializing_formal_function_typed_no_prameters() {
+  test_constructor_initializing_formal_function_typed_no_parameters() {
     UnlinkedExecutable executable = findExecutable('',
         executables: serializeClassText('class C { C(this.x()); final x; }')
             .executables);
@@ -909,7 +1026,7 @@
     expect(parameter.parameters, isEmpty);
   }
 
-  test_constructor_initializing_formal_function_typed_prameter() {
+  test_constructor_initializing_formal_function_typed_parameter() {
     UnlinkedExecutable executable = findExecutable('',
         executables: serializeClassText('class C { C(this.x(a)); final x; }')
             .executables);
@@ -917,7 +1034,7 @@
     expect(parameter.parameters, hasLength(1));
   }
 
-  test_constructor_initializing_formal_function_typed_prameter_order() {
+  test_constructor_initializing_formal_function_typed_parameter_order() {
     UnlinkedExecutable executable = findExecutable('',
         executables: serializeClassText('class C { C(this.x(a, b)); final x; }')
             .executables);
@@ -980,6 +1097,15 @@
     expect(parameter.kind, UnlinkedParamKind.required);
   }
 
+  test_constructor_initializing_formal_typedef() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables: serializeClassText(
+                'typedef F<T>(T x); class C<X> { C(this.f); F<X> f; }')
+            .executables);
+    UnlinkedParam parameter = executable.parameters[0];
+    expect(parameter.parameters, hasLength(1));
+  }
+
   test_constructor_named() {
     UnlinkedExecutable executable = findExecutable('foo',
         executables: serializeClassText('class C { C.foo(); }').executables);
@@ -1008,7 +1134,7 @@
     UnlinkedExecutable executable = findExecutable('',
         executables: serializeClassText('class C<T, U> { C(); }').executables);
     checkTypeRef(executable.returnType, null, null, 'C',
-        allowTypeParameters: true);
+        allowTypeParameters: true, numTypeParameters: 2);
     expect(executable.returnType.typeArguments, hasLength(2));
     {
       UnlinkedTypeRef typeRef = executable.returnType.typeArguments[0];
@@ -1129,6 +1255,10 @@
     expect(e.name, 'E');
     expect(e.values, hasLength(1));
     expect(e.values[0].name, 'v1');
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+        PrelinkedReferenceKind.classOrEnum);
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'E');
   }
 
   test_enum_order() {
@@ -1138,6 +1268,11 @@
     expect(e.values[1].name, 'v2');
   }
 
+  test_enum_private() {
+    serializeEnumText('enum _E { v1 }', '_E');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+  }
+
   test_executable_abstract() {
     UnlinkedExecutable executable =
         serializeClassText('abstract class C { f(); }').executables[0];
@@ -1156,6 +1291,10 @@
     expect(executable.hasImplicitReturnType, isTrue);
     checkDynamicTypeRef(executable.returnType);
     expect(executable.isExternal, isFalse);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+        PrelinkedReferenceKind.other);
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'f');
   }
 
   test_executable_function_explicit_return() {
@@ -1170,6 +1309,11 @@
     expect(executable.isExternal, isTrue);
   }
 
+  test_executable_function_private() {
+    serializeExecutableText('_f() {}', '_f');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+  }
+
   test_executable_getter() {
     UnlinkedExecutable executable = serializeExecutableText('int get f => 1;');
     expect(executable.kind, UnlinkedExecutableKind.getter);
@@ -1177,6 +1321,10 @@
     expect(executable.isExternal, isFalse);
     expect(findVariable('f'), isNull);
     expect(findExecutable('f='), isNull);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+        PrelinkedReferenceKind.other);
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'f');
   }
 
   test_executable_getter_external() {
@@ -1185,6 +1333,11 @@
     expect(executable.isExternal, isTrue);
   }
 
+  test_executable_getter_private() {
+    serializeExecutableText('int get _f => 1;', '_f');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+  }
+
   test_executable_getter_type() {
     UnlinkedExecutable executable = serializeExecutableText('int get f => 1;');
     checkTypeRef(executable.returnType, 'dart:core', 'dart:core', 'int');
@@ -1347,7 +1500,8 @@
 
   test_executable_operator_index_set() {
     UnlinkedExecutable executable = serializeClassText(
-        'class C { void operator[]=(int i, bool v) => null; }').executables[0];
+            'class C { void operator[]=(int i, bool v) => null; }')
+        .executables[0];
     expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
     expect(executable.name, '[]=');
     expect(executable.hasImplicitReturnType, false);
@@ -1496,6 +1650,10 @@
     expect(executable.isExternal, isFalse);
     expect(findVariable('f'), isNull);
     expect(findExecutable('f'), isNull);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+        PrelinkedReferenceKind.other);
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'f=');
   }
 
   test_executable_setter_external() {
@@ -1512,6 +1670,11 @@
     checkDynamicTypeRef(executable.returnType);
   }
 
+  test_executable_setter_private() {
+    serializeExecutableText('void set _f(value) {}', '_f=');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+  }
+
   test_executable_setter_type() {
     UnlinkedExecutable executable =
         serializeExecutableText('void set f(int value) {}', 'f=');
@@ -1528,62 +1691,88 @@
     expect(executable.isStatic, isTrue);
   }
 
-  test_executable_type_param_f_bound() {
-    // TODO(paulberry): also test top level executables.
+  test_executable_type_param_f_bound_function() {
+    UnlinkedExecutable ex =
+        serializeExecutableText('void f<T, U extends List<T>>() {}');
+    UnlinkedTypeRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
+    checkParamTypeRef(typeArgument, 2);
+  }
+
+  test_executable_type_param_f_bound_method() {
     UnlinkedExecutable ex =
         serializeMethodText('void f<T, U extends List<T>>() {}');
     UnlinkedTypeRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
     checkParamTypeRef(typeArgument, 2);
   }
 
-  test_executable_type_param_f_bound_self_ref() {
-    // TODO(paulberry): also test top level executables.
+  test_executable_type_param_f_bound_self_ref_function() {
+    UnlinkedExecutable ex =
+        serializeExecutableText('void f<T, U extends List<U>>() {}');
+    UnlinkedTypeRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
+    checkParamTypeRef(typeArgument, 1);
+  }
+
+  test_executable_type_param_f_bound_self_ref_method() {
     UnlinkedExecutable ex =
         serializeMethodText('void f<T, U extends List<U>>() {}');
     UnlinkedTypeRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
     checkParamTypeRef(typeArgument, 1);
   }
 
-  test_executable_type_param_in_parameter() {
-    // TODO(paulberry): also test top level executables.
+  test_executable_type_param_in_parameter_function() {
+    UnlinkedExecutable ex = serializeExecutableText('void f<T>(T t) {}');
+    checkParamTypeRef(ex.parameters[0].type, 1);
+  }
+
+  test_executable_type_param_in_parameter_method() {
     UnlinkedExecutable ex = serializeMethodText('void f<T>(T t) {}');
     checkParamTypeRef(ex.parameters[0].type, 1);
   }
 
-  test_executable_type_param_in_return_type() {
-    // TODO(paulberry): also test top level executables.
+  test_executable_type_param_in_return_type_function() {
+    UnlinkedExecutable ex = serializeExecutableText('T f<T>() => null;');
+    checkParamTypeRef(ex.returnType, 1);
+  }
+
+  test_executable_type_param_in_return_type_method() {
     UnlinkedExecutable ex = serializeMethodText('T f<T>() => null;');
     checkParamTypeRef(ex.returnType, 1);
   }
 
   test_export_hide_order() {
     serializeLibraryText('export "dart:async" hide Future, Stream;');
-    expect(unlinkedUnits[0].exports, hasLength(1));
-    expect(unlinkedUnits[0].exports[0].combinators, hasLength(1));
-    expect(unlinkedUnits[0].exports[0].combinators[0].shows, isEmpty);
-    expect(unlinkedUnits[0].exports[0].combinators[0].hides, hasLength(2));
-    checkCombinatorName(
-        unlinkedUnits[0].exports[0].combinators[0].hides[0], 'Future');
-    checkCombinatorName(
-        unlinkedUnits[0].exports[0].combinators[0].hides[1], 'Stream');
+    expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
+    expect(
+        unlinkedUnits[0].publicNamespace.exports[0].combinators, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows,
+        isEmpty);
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides,
+        hasLength(2));
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides[0],
+        'Future');
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides[1],
+        'Stream');
   }
 
   test_export_no_combinators() {
     serializeLibraryText('export "dart:async";');
-    expect(unlinkedUnits[0].exports, hasLength(1));
-    expect(unlinkedUnits[0].exports[0].combinators, isEmpty);
+    expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators, isEmpty);
   }
 
   test_export_show_order() {
     serializeLibraryText('export "dart:async" show Future, Stream;');
-    expect(unlinkedUnits[0].exports, hasLength(1));
-    expect(unlinkedUnits[0].exports[0].combinators, hasLength(1));
-    expect(unlinkedUnits[0].exports[0].combinators[0].shows, hasLength(2));
-    expect(unlinkedUnits[0].exports[0].combinators[0].hides, isEmpty);
-    checkCombinatorName(
-        unlinkedUnits[0].exports[0].combinators[0].shows[0], 'Future');
-    checkCombinatorName(
-        unlinkedUnits[0].exports[0].combinators[0].shows[1], 'Stream');
+    expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
+    expect(
+        unlinkedUnits[0].publicNamespace.exports[0].combinators, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows,
+        hasLength(2));
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides,
+        isEmpty);
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows[0],
+        'Future');
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows[1],
+        'Stream');
   }
 
   test_export_uri() {
@@ -1591,8 +1780,8 @@
     String uriString = '"a.dart"';
     String libraryText = 'export $uriString;';
     serializeLibraryText(libraryText);
-    expect(unlinkedUnits[0].exports, hasLength(1));
-    expect(unlinkedUnits[0].exports[0].uri, 'a.dart');
+    expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.exports[0].uri, 'a.dart');
   }
 
   test_field() {
@@ -1662,10 +1851,8 @@
     expect(unlinkedUnits[0].imports[0].combinators, hasLength(1));
     expect(unlinkedUnits[0].imports[0].combinators[0].shows, isEmpty);
     expect(unlinkedUnits[0].imports[0].combinators[0].hides, hasLength(2));
-    checkCombinatorName(
-        unlinkedUnits[0].imports[0].combinators[0].hides[0], 'Future');
-    checkCombinatorName(
-        unlinkedUnits[0].imports[0].combinators[0].hides[1], 'Stream');
+    expect(unlinkedUnits[0].imports[0].combinators[0].hides[0], 'Future');
+    expect(unlinkedUnits[0].imports[0].combinators[0].hides[1], 'Stream');
   }
 
   test_import_implicit() {
@@ -1735,17 +1922,25 @@
     expect(unlinkedUnits[0].imports[0].prefixReference, 0);
   }
 
+  test_import_prefix_not_in_public_namespace() {
+    serializeLibraryText('import "dart:async" as a; a.Future v;');
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(2));
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'v');
+    expect(unlinkedUnits[0].publicNamespace.names[1].name, 'v=');
+  }
+
   test_import_prefix_reference() {
     UnlinkedVariable variable =
         serializeVariableText('import "dart:async" as a; a.Future v;');
     checkTypeRef(variable.type, 'dart:async', 'dart:async', 'Future',
-        expectedPrefix: 'a');
+        expectedPrefix: 'a', numTypeParameters: 1);
   }
 
   test_import_reference() {
     UnlinkedVariable variable =
         serializeVariableText('import "dart:async"; Future v;');
-    checkTypeRef(variable.type, 'dart:async', 'dart:async', 'Future');
+    checkTypeRef(variable.type, 'dart:async', 'dart:async', 'Future',
+        numTypeParameters: 1);
   }
 
   test_import_reference_merged_no_prefix() {
@@ -1756,8 +1951,10 @@
 Future f;
 Stream s;
 ''');
-    checkTypeRef(findVariable('f').type, 'dart:async', 'dart:async', 'Future');
-    checkTypeRef(findVariable('s').type, 'dart:async', 'dart:async', 'Stream');
+    checkTypeRef(findVariable('f').type, 'dart:async', 'dart:async', 'Future',
+        numTypeParameters: 1);
+    checkTypeRef(findVariable('s').type, 'dart:async', 'dart:async', 'Stream',
+        numTypeParameters: 1);
   }
 
   test_import_reference_merged_prefixed() {
@@ -1769,9 +1966,9 @@
 a.Stream s;
 ''');
     checkTypeRef(findVariable('f').type, 'dart:async', 'dart:async', 'Future',
-        expectedPrefix: 'a');
+        expectedPrefix: 'a', numTypeParameters: 1);
     checkTypeRef(findVariable('s').type, 'dart:async', 'dart:async', 'Stream',
-        expectedPrefix: 'a');
+        expectedPrefix: 'a', numTypeParameters: 1);
   }
 
   test_import_show_order() {
@@ -1783,10 +1980,8 @@
     expect(unlinkedUnits[0].imports[0].combinators, hasLength(1));
     expect(unlinkedUnits[0].imports[0].combinators[0].shows, hasLength(2));
     expect(unlinkedUnits[0].imports[0].combinators[0].hides, isEmpty);
-    checkCombinatorName(
-        unlinkedUnits[0].imports[0].combinators[0].shows[0], 'Future');
-    checkCombinatorName(
-        unlinkedUnits[0].imports[0].combinators[0].shows[1], 'Stream');
+    expect(unlinkedUnits[0].imports[0].combinators[0].shows[0], 'Future');
+    expect(unlinkedUnits[0].imports[0].combinators[0].shows[1], 'Stream');
   }
 
   test_import_uri() {
@@ -1812,7 +2007,7 @@
   test_parts_defining_compilation_unit() {
     serializeLibraryText('');
     expect(prelinked.units, hasLength(1));
-    expect(unlinkedUnits[0].parts, isEmpty);
+    expect(unlinkedUnits[0].publicNamespace.parts, isEmpty);
   }
 
   test_parts_included() {
@@ -1821,14 +2016,22 @@
     String libraryText = 'library my.lib; part $partString;';
     serializeLibraryText(libraryText);
     expect(prelinked.units, hasLength(2));
-    expect(unlinkedUnits[0].parts, hasLength(1));
-    expect(unlinkedUnits[0].parts[0].uri, 'part1.dart');
+    expect(unlinkedUnits[0].publicNamespace.parts, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.parts[0].uri, 'part1.dart');
+  }
+
+  test_public_namespace_of_part() {
+    addNamedSource('/a.dart', 'part of foo; class C {}');
+    serializeLibraryText('library foo; part "a.dart";');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+    expect(unlinkedUnits[1].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[1].publicNamespace.names[0].name, 'C');
   }
 
   test_type_arguments_explicit() {
     UnlinkedTypeRef typeRef = serializeTypeText('List<int>');
     checkTypeRef(typeRef, 'dart:core', 'dart:core', 'List',
-        allowTypeParameters: true);
+        allowTypeParameters: true, numTypeParameters: 1);
     expect(typeRef.typeArguments, hasLength(1));
     checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'dart:core', 'int');
   }
@@ -1836,7 +2039,7 @@
   test_type_arguments_explicit_dynamic() {
     UnlinkedTypeRef typeRef = serializeTypeText('List<dynamic>');
     checkTypeRef(typeRef, 'dart:core', 'dart:core', 'List',
-        allowTypeParameters: true);
+        allowTypeParameters: true, numTypeParameters: 1);
     expect(typeRef.typeArguments, isEmpty);
   }
 
@@ -1845,7 +2048,8 @@
         serializeTypeText('F<dynamic>', otherDeclarations: 'typedef T F<T>();');
     checkTypeRef(typeRef, null, null, 'F',
         allowTypeParameters: true,
-        expectedKind: PrelinkedReferenceKind.typedef);
+        expectedKind: PrelinkedReferenceKind.typedef,
+        numTypeParameters: 1);
     expect(typeRef.typeArguments, isEmpty);
   }
 
@@ -1854,7 +2058,8 @@
         serializeTypeText('F<int>', otherDeclarations: 'typedef T F<T>();');
     checkTypeRef(typeRef, null, null, 'F',
         allowTypeParameters: true,
-        expectedKind: PrelinkedReferenceKind.typedef);
+        expectedKind: PrelinkedReferenceKind.typedef,
+        numTypeParameters: 1);
     expect(typeRef.typeArguments, hasLength(1));
     checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'dart:core', 'int');
   }
@@ -1862,7 +2067,7 @@
   test_type_arguments_implicit() {
     UnlinkedTypeRef typeRef = serializeTypeText('List');
     checkTypeRef(typeRef, 'dart:core', 'dart:core', 'List',
-        allowTypeParameters: true);
+        allowTypeParameters: true, numTypeParameters: 1);
     expect(typeRef.typeArguments, isEmpty);
   }
 
@@ -1871,14 +2076,15 @@
         serializeTypeText('F', otherDeclarations: 'typedef T F<T>();');
     checkTypeRef(typeRef, null, null, 'F',
         allowTypeParameters: true,
-        expectedKind: PrelinkedReferenceKind.typedef);
+        expectedKind: PrelinkedReferenceKind.typedef,
+        numTypeParameters: 1);
     expect(typeRef.typeArguments, isEmpty);
   }
 
   test_type_arguments_order() {
     UnlinkedTypeRef typeRef = serializeTypeText('Map<int, Object>');
     checkTypeRef(typeRef, 'dart:core', 'dart:core', 'Map',
-        allowTypeParameters: true);
+        allowTypeParameters: true, numTypeParameters: 2);
     expect(typeRef.typeArguments, hasLength(2));
     checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'dart:core', 'int');
     checkTypeRef(typeRef.typeArguments[1], 'dart:core', 'dart:core', 'Object');
@@ -1992,15 +2198,14 @@
   }
 
   test_type_reference_to_part() {
-    addNamedSource('/a.dart', 'part of foo; class C {}');
-    checkTypeRef(
-        serializeTypeText('C',
-            otherDeclarations: 'library foo; part "a.dart";'),
-        null,
-        null,
-        'C',
+    addNamedSource('/a.dart', 'part of foo; class C { C(); }');
+    serializeLibraryText('library foo; part "a.dart"; C c;');
+    UnlinkedClass classA = findClass('C', unit: unlinkedUnits[1]);
+    checkTypeRef(classA.executables.single.returnType, null, null, 'C',
         expectedKind: PrelinkedReferenceKind.classOrEnum,
-        expectedTargetUnit: 1);
+        expectedTargetUnit: 1,
+        prelinkedSourceUnit: prelinked.units[1],
+        unlinkedSourceUnit: unlinkedUnits[1]);
   }
 
   test_type_reference_to_typedef() {
@@ -2030,6 +2235,10 @@
   test_typedef_name() {
     UnlinkedTypedef type = serializeTypedefText('typedef F();');
     expect(type.name, 'F');
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+        PrelinkedReferenceKind.typedef);
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'F');
   }
 
   test_typedef_param_none() {
@@ -2044,6 +2253,26 @@
     expect(type.parameters[1].name, 'y');
   }
 
+  test_typedef_private() {
+    serializeTypedefText('typedef _F();', '_F');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+  }
+
+  test_typedef_reference_generic() {
+    UnlinkedTypeRef typeRef =
+        serializeTypeText('F', otherDeclarations: 'typedef void F<A, B>();');
+    checkTypeRef(typeRef, null, null, 'F',
+        numTypeParameters: 2, expectedKind: PrelinkedReferenceKind.typedef);
+  }
+
+  test_typedef_reference_generic_imported() {
+    addNamedSource('/lib.dart', 'typedef void F<A, B>();');
+    UnlinkedTypeRef typeRef =
+        serializeTypeText('F', otherDeclarations: 'import "lib.dart";');
+    checkTypeRef(typeRef, absUri('/lib.dart'), 'lib.dart', 'F',
+        numTypeParameters: 2, expectedKind: PrelinkedReferenceKind.typedef);
+  }
+
   test_typedef_return_type_explicit() {
     UnlinkedTypedef type = serializeTypedefText('typedef int F();');
     checkTypeRef(type.returnType, 'dart:core', 'dart:core', 'int');
@@ -2075,6 +2304,13 @@
     serializeVariableText('int i;', variableName: 'i');
     expect(findExecutable('i'), isNull);
     expect(findExecutable('i='), isNull);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(2));
+    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+        PrelinkedReferenceKind.other);
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'i');
+    expect(unlinkedUnits[0].publicNamespace.names[1].kind,
+        PrelinkedReferenceKind.other);
+    expect(unlinkedUnits[0].publicNamespace.names[1].name, 'i=');
   }
 
   test_variable_const() {
@@ -2151,4 +2387,9 @@
         serializeVariableText('int i;', variableName: 'i');
     checkTypeRef(variable.type, 'dart:core', 'dart:core', 'int');
   }
+
+  test_varible_private() {
+    serializeVariableText('int _i;', variableName: '_i');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+  }
 }
diff --git a/pkg/analyzer/test/src/summary/test_all.dart b/pkg/analyzer/test/src/summary/test_all.dart
new file mode 100644
index 0000000..189d00f
--- /dev/null
+++ b/pkg/analyzer/test/src/summary/test_all.dart
@@ -0,0 +1,20 @@
+// 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 test.src.serialization.test_all;
+
+import 'package:unittest/unittest.dart';
+
+import '../../utils.dart';
+import 'resynthesize_test.dart' as resynthesize_test;
+import 'summary_test.dart' as summary_test;
+
+/// Utility for manually running all tests.
+main() {
+  initializeTestEnvironment();
+  group('summary tests', () {
+    resynthesize_test.main();
+    summary_test.main();
+  });
+}
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index fd4fee2..b81e72a 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -147,6 +147,19 @@
   Source source;
   LibrarySpecificUnit target;
 
+  test_created_resolved_unit() {
+    Source source = newSource(
+        '/test.dart',
+        r'''
+library lib;
+class A {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT1);
+    expect(outputs[RESOLVED_UNIT1], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT1], isTrue);
+  }
+
   test_perform_find_constants() {
     _performBuildTask('''
 const x = 1;
@@ -189,10 +202,11 @@
 }
 class B = Object with A;
 ''');
-    expect(outputs, hasLength(3));
+    expect(outputs, hasLength(4));
     expect(outputs[COMPILATION_UNIT_CONSTANTS], isNotNull);
     expect(outputs[COMPILATION_UNIT_ELEMENT], isNotNull);
     expect(outputs[RESOLVED_UNIT1], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT1], isTrue);
   }
 
   test_perform_reuseElement() {
@@ -470,6 +484,19 @@
 
 @reflectiveTest
 class BuildEnumMemberElementsTaskTest extends _AbstractDartTaskTest {
+  test_created_resolved_unit() {
+    Source source = newSource(
+        '/test.dart',
+        r'''
+library lib;
+class A {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT2);
+    expect(outputs[RESOLVED_UNIT2], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT2], isTrue);
+  }
+
   test_perform() {
     Source source = newSource(
         '/test.dart',
@@ -1344,6 +1371,19 @@
     enableStrongMode();
   }
 
+  test_created_resolved_unit() {
+    Source source = newSource(
+        '/test.dart',
+        r'''
+library lib;
+class A {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT5);
+    expect(outputs[RESOLVED_UNIT5], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT5], isTrue);
+  }
+
   test_perform() {
     AnalysisTarget source = newSource(
         '/test.dart',
@@ -2024,6 +2064,19 @@
 
 @reflectiveTest
 class EvaluateUnitConstantsTaskTest extends _AbstractDartTaskTest {
+  test_created_resolved_unit() {
+    Source source = newSource(
+        '/test.dart',
+        r'''
+library lib;
+class A {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT11);
+    expect(outputs[RESOLVED_UNIT11], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT11], isTrue);
+  }
+
   test_perform() {
     Source source = newSource(
         '/test.dart',
@@ -2488,6 +2541,19 @@
 
 @reflectiveTest
 class InferInstanceMembersInUnitTaskTest extends _AbstractDartTaskTest {
+  test_created_resolved_unit() {
+    Source source = newSource(
+        '/test.dart',
+        r'''
+library lib;
+class A {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT9);
+    expect(outputs[RESOLVED_UNIT9], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT9], isTrue);
+  }
+
   void test_perform() {
     enableStrongMode();
     AnalysisTarget source = newSource(
@@ -2589,6 +2655,19 @@
 
 @reflectiveTest
 class InferStaticVariableTypesInUnitTaskTest extends _AbstractDartTaskTest {
+  test_created_resolved_unit() {
+    Source source = newSource(
+        '/test.dart',
+        r'''
+library lib;
+class A {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT7);
+    expect(outputs[RESOLVED_UNIT7], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT7], isTrue);
+  }
+
   void test_perform_const_field() {
     enableStrongMode();
     AnalysisTarget source = newSource(
@@ -3204,6 +3283,19 @@
 
 @reflectiveTest
 class PropagateVariableTypesInUnitTaskTest extends _AbstractDartTaskTest {
+  test_created_resolved_unit() {
+    Source source = newSource(
+        '/test.dart',
+        r'''
+library lib;
+class A {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT6);
+    expect(outputs[RESOLVED_UNIT6], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT6], isTrue);
+  }
+
   void test_perform_cycle() {
     AnalysisTarget source = newSource(
         '/test.dart',
@@ -3329,6 +3421,19 @@
     enableStrongMode();
   }
 
+  test_created_resolved_unit() {
+    Source source = newSource(
+        '/test.dart',
+        r'''
+library lib;
+class A {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT8);
+    expect(outputs[RESOLVED_UNIT8], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT8], isTrue);
+  }
+
   // Test inference of instance fields across units
   void test_perform_inference_cross_unit_instance() {
     List<Source> sources = newSources({
@@ -3423,7 +3528,7 @@
     computeResult(
         new LibrarySpecificUnit(sources[2], sources[2]), RESOLVED_UNIT8);
 
-    // A.a2 should now be fully resolved and inferred.
+    // A.a2 should now be fully resolved and inferred (but not re-resolved).
     assertVariableDeclarationTypes(
         AstFinder.getFieldInClass(unit0, "A", "a2"), dynamicType, dynamicType);
   }
@@ -3535,7 +3640,7 @@
     computeResult(
         new LibrarySpecificUnit(sources[1], sources[1]), RESOLVED_UNIT8);
 
-    // A.a2 should now be fully resolved and inferred.
+    // A.a2 should now be fully resolved and inferred (but not re-resolved).
     assertVariableDeclarationTypes(
         AstFinder.getFieldInClass(unit0, "A", "a2"), dynamicType, dynamicType);
 
@@ -3634,6 +3739,19 @@
 
 @reflectiveTest
 class ResolveUnitTaskTest extends _AbstractDartTaskTest {
+  test_created_resolved_unit() {
+    Source source = newSource(
+        '/test.dart',
+        r'''
+library lib;
+class A {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT10);
+    expect(outputs[RESOLVED_UNIT10], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT10], isTrue);
+  }
+
   void test_perform() {
     AnalysisTarget source = newSource(
         '/test.dart',
@@ -3697,6 +3815,19 @@
 
 @reflectiveTest
 class ResolveUnitTypeNamesTaskTest extends _AbstractDartTaskTest {
+  test_created_resolved_unit() {
+    Source source = newSource(
+        '/test.dart',
+        r'''
+library lib;
+class A {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT3);
+    expect(outputs[RESOLVED_UNIT3], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT3], isTrue);
+  }
+
   test_perform() {
     Source source = newSource(
         '/test.dart',
@@ -3796,6 +3927,19 @@
     expect(variable.isPotentiallyMutatedInScope, mutatedInScope);
   }
 
+  test_created_resolved_unit() {
+    Source source = newSource(
+        '/test.dart',
+        r'''
+library lib;
+class A {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT4);
+    expect(outputs[RESOLVED_UNIT4], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT4], isTrue);
+  }
+
   test_perform_buildClosureLibraryElements() {
     Source source = newSource(
         '/test.dart',
@@ -4414,6 +4558,19 @@
     enableStrongMode();
   }
 
+  test_created_resolved_unit() {
+    Source source = newSource(
+        '/test.dart',
+        r'''
+library lib;
+class A {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT);
+    expect(outputs[RESOLVED_UNIT], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT], isTrue);
+  }
+
   void test_perform_recordDynamicInvoke() {
     enableStrongMode();
     AnalysisTarget source = newSource(
diff --git a/pkg/analyzer/test/src/task/driver_test.dart b/pkg/analyzer/test/src/task/driver_test.dart
index b0f8181..221636a 100644
--- a/pkg/analyzer/test/src/task/driver_test.dart
+++ b/pkg/analyzer/test/src/task/driver_test.dart
@@ -36,6 +36,7 @@
   void setUp() {
     context = new _InternalAnalysisContextMock();
     analysisDriver = new AnalysisDriver(taskManager, workManagers, context);
+    when(context.aboutToComputeResult(anyObject, anyObject)).thenReturn(false);
   }
 }
 
@@ -698,6 +699,61 @@
     expect(result, isNull);
     expect(item.exception, isNotNull);
   }
+
+  test_gatherInputs_aboutToComputeResult_hasResult() {
+    AnalysisTarget target = new TestSource();
+    ResultDescriptor resultA = new ResultDescriptor('resultA', null);
+    ResultDescriptor resultB = new ResultDescriptor('resultB', null);
+    // prepare tasks
+    TaskDescriptor task1 = new TaskDescriptor(
+        'task',
+        (context, target) =>
+            new TestAnalysisTask(context, target, results: [resultA]),
+        (target) => {},
+        [resultA]);
+    TaskDescriptor task2 = new TaskDescriptor(
+        'task',
+        (context, target) => new TestAnalysisTask(context, target),
+        (target) => {'one': resultA.of(target)},
+        [resultB]);
+    taskManager.addTaskDescriptor(task1);
+    taskManager.addTaskDescriptor(task2);
+    // configure mocks
+    when(context.aboutToComputeResult(anyObject, resultA)).thenReturn(true);
+    // gather inputs
+    WorkItem item = new WorkItem(context, target, task2, null, 0, null);
+    WorkItem inputItem = item.gatherInputs(taskManager, []);
+    expect(inputItem, isNull);
+  }
+
+  test_gatherInputs_aboutToComputeResult_noResult() {
+    AnalysisTarget target = new TestSource();
+    ResultDescriptor resultA = new ResultDescriptor('resultA', null);
+    ResultDescriptor resultB = new ResultDescriptor('resultB', null);
+    // prepare tasks
+    TaskDescriptor task1 = new TaskDescriptor(
+        'task',
+        (context, target) =>
+            new TestAnalysisTask(context, target, results: [resultA]),
+        (target) => {},
+        [resultA]);
+    TaskDescriptor task2 = new TaskDescriptor(
+        'task',
+        (context, target) => new TestAnalysisTask(context, target),
+        (target) => {'one': resultA.of(target)},
+        [resultB]);
+    taskManager.addTaskDescriptor(task1);
+    taskManager.addTaskDescriptor(task2);
+    // configure ResultProvider
+    // configure mocks
+    when(context.aboutToComputeResult(anyObject, resultA)).thenReturn(false);
+    // gather inputs
+    WorkItem item = new WorkItem(context, target, task2, null, 0, null);
+    WorkItem inputItem = item.gatherInputs(taskManager, []);
+    expect(inputItem, isNotNull);
+    expect(inputItem.target, target);
+    expect(inputItem.descriptor, task1);
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index 6d35a3e..c3f670b 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -237,6 +237,9 @@
 analyzer:
   errors:
     unused_local_variable: ignore
+    invalid_assignment: warning
+    missing_return: error
+    dead_code: info
 ''',
         []);
   }
diff --git a/pkg/analyzer/test/src/test_all.dart b/pkg/analyzer/test/src/test_all.dart
index b97bc81..14226d8 100644
--- a/pkg/analyzer/test/src/test_all.dart
+++ b/pkg/analyzer/test/src/test_all.dart
@@ -9,6 +9,7 @@
 import '../utils.dart';
 import 'context/test_all.dart' as context;
 import 'plugin/plugin_config_test.dart' as plugin;
+import 'summary/test_all.dart' as summary;
 import 'task/test_all.dart' as task;
 import 'util/test_all.dart' as util;
 
@@ -18,6 +19,7 @@
   group('src tests', () {
     context.main();
     plugin.main();
+    summary.main();
     task.main();
     util.main();
   });
diff --git a/pkg/analyzer/tool/generate_files b/pkg/analyzer/tool/generate_files
index 1e0322f..4f0ea0d 100755
--- a/pkg/analyzer/tool/generate_files
+++ b/pkg/analyzer/tool/generate_files
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # 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.
diff --git a/pkg/analyzer/tool/summary/build_sdk_summary.dart b/pkg/analyzer/tool/summary/build_sdk_summary.dart
new file mode 100644
index 0000000..52862e3
--- /dev/null
+++ b/pkg/analyzer/tool/summary/build_sdk_summary.dart
@@ -0,0 +1,89 @@
+import 'dart:io';
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/java_io.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/sdk_io.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/base.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/summarize_elements.dart';
+
+main(List<String> args) {
+  if (args.length < 1 || args.length > 2) {
+    _printUsage();
+    return;
+  }
+  //
+  // Prepare output file path.
+  //
+  String outputFilePath = args[0];
+  if (FileSystemEntity.isDirectorySync(outputFilePath)) {
+    print("'$outputFilePath' is a directory.");
+    _printUsage();
+    return;
+  }
+  //
+  // Prepare SDK path.
+  //
+  String sdkPath;
+  if (args.length == 2) {
+    sdkPath = args[1];
+    if (!FileSystemEntity.isDirectorySync('$sdkPath/lib')) {
+      print("'$sdkPath/lib' does not exist.");
+      _printUsage();
+      return;
+    }
+  } else {
+    sdkPath = DirectoryBasedDartSdk.defaultSdkDirectory.getAbsolutePath();
+  }
+  //
+  // Prepare SDK.
+  //
+  DirectoryBasedDartSdk sdk = new DirectoryBasedDartSdk(new JavaFile(sdkPath));
+  AnalysisContext context = sdk.context;
+  //
+  // Serialize each SDK library.
+  //
+  List<String> prelinkedLibraryUris = <String>[];
+  List<PrelinkedLibraryBuilder> prelinkedLibraries =
+      <PrelinkedLibraryBuilder>[];
+  List<String> unlinkedUnitUris = <String>[];
+  List<UnlinkedUnitBuilder> unlinkedUnits = <UnlinkedUnitBuilder>[];
+  BuilderContext builderContext = new BuilderContext();
+  for (SdkLibrary lib in sdk.sdkLibraries) {
+    print('Resolving and serializing: ${lib.shortName}');
+    Source librarySource = sdk.mapDartUri(lib.shortName);
+    LibraryElement libraryElement =
+        context.computeLibraryElement(librarySource);
+    LibrarySerializationResult libraryResult =
+        serializeLibrary(builderContext, libraryElement, context.typeProvider);
+    prelinkedLibraryUris.add(lib.shortName);
+    prelinkedLibraries.add(libraryResult.prelinked);
+    unlinkedUnitUris.addAll(libraryResult.unitUris);
+    unlinkedUnits.addAll(libraryResult.unlinkedUnits);
+  }
+  //
+  // Write the whole SDK bundle.
+  //
+  SdkBundleBuilder sdkBundle = encodeSdkBundle(builderContext,
+      prelinkedLibraryUris: prelinkedLibraryUris,
+      prelinkedLibraries: prelinkedLibraries,
+      unlinkedUnitUris: unlinkedUnitUris,
+      unlinkedUnits: unlinkedUnits);
+  File file = new File(outputFilePath);
+  file.writeAsBytesSync(sdkBundle.toBuffer(), mode: FileMode.WRITE_ONLY);
+}
+
+/**
+ * The name of the SDK summary builder application.
+ */
+const BINARY_NAME = "build_sdk_summary";
+
+/**
+ * Print information about how to use the SDK summary builder.
+ */
+void _printUsage() {
+  print('Usage: $BINARY_NAME output_file_path [sdk_path]');
+}
diff --git a/pkg/analyzer/tool/summary/generate.dart b/pkg/analyzer/tool/summary/generate.dart
index 03593db..9ff31d6 100644
--- a/pkg/analyzer/tool/summary/generate.dart
+++ b/pkg/analyzer/tool/summary/generate.dart
@@ -13,7 +13,7 @@
  * - A "builder" class which can be used to generate serialized summary data.
  *   This class has write-only semantics.
  *
- * Each of the "builder" classess has a single `finish` method which finalizes
+ * Each of the "builder" classes has a single `finish` method which finalizes
  * the entity being built and returns it as an [Object].  This object should
  * only be passed to other builders (or to [BuilderContext.getBuffer]);
  * otherwise the client should treat it as opaque, since it exposes
@@ -54,10 +54,11 @@
   CharacterReader idlReader = new CharSequenceReader(idlText);
   Scanner scanner = new Scanner(idlSource, idlReader, errorListener);
   Token tokenStream = scanner.tokenize();
+  LineInfo lineInfo = new LineInfo(scanner.lineStarts);
   Parser parser = new Parser(idlSource, new BooleanErrorListener());
   CompilationUnit idlParsed = parser.parseCompilationUnit(tokenStream);
   _CodeGenerator codeGenerator = new _CodeGenerator();
-  codeGenerator.processCompilationUnit(idlParsed);
+  codeGenerator.processCompilationUnit(lineInfo, idlParsed);
   return codeGenerator._outBuffer.toString();
 });
 
@@ -83,18 +84,22 @@
    */
   void checkIdl() {
     _idl.classes.forEach((String name, idlModel.ClassDeclaration cls) {
-      cls.fields.forEach((String fieldName, idlModel.FieldType type) {
+      for (idlModel.FieldDeclaration field in cls.fields) {
+        String fieldName = field.name;
+        idlModel.FieldType type = field.type;
         if (type.isList) {
           if (_idl.classes.containsKey(type.typeName)) {
             // List of classes is ok
           } else if (type.typeName == 'int') {
             // List of ints is ok
+          } else if (type.typeName == 'String') {
+            // List of strings is ok
           } else {
             throw new Exception(
                 '$name.$fieldName: illegal type (list of ${type.typeName})');
           }
         }
-      });
+      }
     });
   }
 
@@ -152,7 +157,7 @@
    * Process the AST in [idlParsed] and store the resulting semantic model in
    * [_idl].  Also perform some error checking.
    */
-  void extractIdl(CompilationUnit idlParsed) {
+  void extractIdl(LineInfo lineInfo, CompilationUnit idlParsed) {
     _idl = new idlModel.Idl();
     for (CompilationUnitMember decl in idlParsed.declarations) {
       if (decl is ClassDeclaration) {
@@ -163,9 +168,10 @@
             isTopLevel = true;
           }
         }
+        String doc = _getNodeDoc(lineInfo, decl);
         idlModel.ClassDeclaration cls =
-            new idlModel.ClassDeclaration(isTopLevel);
-        _idl.classes[decl.name.name] = cls;
+            new idlModel.ClassDeclaration(doc, decl.name.name, isTopLevel);
+        _idl.classes[cls.name] = cls;
         for (ClassMember classMember in decl.members) {
           if (classMember is FieldDeclaration) {
             TypeName type = classMember.fields.type;
@@ -179,23 +185,27 @@
             if (type.typeArguments != null) {
               throw new Exception('Cannot handle type arguments in `$type`');
             }
+            String doc = _getNodeDoc(lineInfo, classMember);
             idlModel.FieldType fieldType =
                 new idlModel.FieldType(type.name.name, isList);
             for (VariableDeclaration field in classMember.fields.variables) {
-              cls.fields[field.name.name] = fieldType;
+              cls.fields.add(new idlModel.FieldDeclaration(
+                  doc, field.name.name, fieldType));
             }
           } else {
             throw new Exception('Unexpected class member `$classMember`');
           }
         }
       } else if (decl is EnumDeclaration) {
-        idlModel.EnumDeclaration enm = new idlModel.EnumDeclaration();
-        _idl.enums[decl.name.name] = enm;
+        String doc = _getNodeDoc(lineInfo, decl);
+        idlModel.EnumDeclaration enm =
+            new idlModel.EnumDeclaration(doc, decl.name.name);
+        _idl.enums[enm.name] = enm;
         for (EnumConstantDeclaration constDecl in decl.constants) {
           enm.values.add(constDecl.name.name);
         }
       } else if (decl is TopLevelVariableDeclaration) {
-        // Ignore top leve variable declarations; they are present just to make
+        // Ignore top level variable declarations; they are present just to make
         // the IDL analyze without warnings.
       } else {
         throw new Exception('Unexpected declaration `$decl`');
@@ -228,12 +238,18 @@
     }
   }
 
+  void outDoc(String documentation) {
+    if (documentation != null) {
+      documentation.split('\n').forEach(out);
+    }
+  }
+
   /**
    * Entry point to the code generator.  Interpret the AST in [idlParsed],
    * generate code, and output it to [_outBuffer].
    */
-  void processCompilationUnit(CompilationUnit idlParsed) {
-    extractIdl(idlParsed);
+  void processCompilationUnit(LineInfo lineInfo, CompilationUnit idlParsed) {
+    extractIdl(lineInfo, idlParsed);
     checkIdl();
     out('// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file');
     out('// for details. All rights reserved. Use of this source code is governed by a');
@@ -245,9 +261,10 @@
     out('library analyzer.src.summary.format;');
     out();
     out("import 'dart:convert';");
-    out("import 'builder.dart' as builder;");
+    out("import 'base.dart' as base;");
     out();
     _idl.enums.forEach((String name, idlModel.EnumDeclaration enm) {
+      outDoc(enm.documentation);
       out('enum $name {');
       indent(() {
         for (String value in enm.values) {
@@ -258,22 +275,29 @@
       out();
     });
     _idl.classes.forEach((String name, idlModel.ClassDeclaration cls) {
-      out('class $name {');
+      outDoc(cls.documentation);
+      out('class $name extends base.SummaryClass {');
       indent(() {
-        cls.fields.forEach((String fieldName, idlModel.FieldType type) {
+        for (idlModel.FieldDeclaration field in cls.fields) {
+          String fieldName = field.name;
+          idlModel.FieldType type = field.type;
           out('${dartType(type)} _$fieldName;');
-        });
+        }
         out();
         out('$name.fromJson(Map json)');
         indent(() {
           List<String> initializers = <String>[];
-          cls.fields.forEach((String fieldName, idlModel.FieldType type) {
+          for (idlModel.FieldDeclaration field in cls.fields) {
+            String fieldName = field.name;
+            idlModel.FieldType type = field.type;
             String convert = 'json[${quoted(fieldName)}]';
-            if (type.isList && type.typeName == 'int') {
-              // No conversion necessary.
-            } else if (type.isList) {
-              convert =
-                  '$convert?.map((x) => new ${type.typeName}.fromJson(x))?.toList()';
+            if (type.isList) {
+              if (type.typeName == 'int' || type.typeName == 'String') {
+                // No conversion necessary.
+              } else {
+                convert =
+                    '$convert?.map((x) => new ${type.typeName}.fromJson(x))?.toList()';
+              }
             } else if (_idl.classes.containsKey(type.typeName)) {
               convert =
                   '$convert == null ? null : new ${type.typeName}.fromJson($convert)';
@@ -282,7 +306,7 @@
                   '$convert == null ? null : ${type.typeName}.values[$convert]';
             }
             initializers.add('_$fieldName = $convert');
-          });
+          }
           for (int i = 0; i < initializers.length; i++) {
             String prefix = i == 0 ? ': ' : '  ';
             String suffix = i == initializers.length - 1 ? ';' : ',';
@@ -290,13 +314,29 @@
           }
         });
         out();
+        out('@override');
+        out('Map<String, Object> toMap() => {');
+        indent(() {
+          for (idlModel.FieldDeclaration field in cls.fields) {
+            String fieldName = field.name;
+            out('${quoted(fieldName)}: $fieldName,');
+          }
+        });
+        out('};');
+        out();
         if (cls.isTopLevel) {
           out('$name.fromBuffer(List<int> buffer) : this.fromJson(JSON.decode(UTF8.decode(buffer)));');
           out();
         }
-        cls.fields.forEach((String fieldName, idlModel.FieldType type) {
+        cls.fields.asMap().forEach((index, field) {
+          String fieldName = field.name;
+          idlModel.FieldType type = field.type;
+          if (index != 0) {
+            out();
+          }
           String def = defaultValue(type);
           String defaultSuffix = def == null ? '' : ' ?? $def';
+          outDoc(field.documentation);
           out('${dartType(type)} get $fieldName => _$fieldName$defaultSuffix;');
         });
       });
@@ -309,9 +349,12 @@
         out();
         out('bool _finished = false;');
         out();
-        out('${name}Builder(builder.BuilderContext context);');
-        cls.fields.forEach((String fieldName, idlModel.FieldType type) {
+        out('${name}Builder(base.BuilderContext context);');
+        for (idlModel.FieldDeclaration field in cls.fields) {
+          String fieldName = field.name;
+          idlModel.FieldType type = field.type;
           out();
+          outDoc(field.documentation);
           String conversion = '_value';
           String condition = '';
           if (type.isList) {
@@ -332,14 +375,18 @@
           indent(() {
             out('assert(!_finished);');
             out('assert(!_json.containsKey(${quoted(fieldName)}));');
-            out('if (_value != null$condition) {');
+            if (condition.isEmpty) {
+              out('if (_value != null) {');
+            } else {
+              out('if (!(_value == null$condition)) {');
+            }
             indent(() {
               out('_json[${quoted(fieldName)}] = $conversion;');
             });
             out('}');
           });
           out('}');
-        });
+        }
         if (cls.isTopLevel) {
           out();
           out('List<int> toBuffer() => UTF8.encode(JSON.encode(finish()));');
@@ -355,12 +402,13 @@
       });
       out('}');
       out();
-      out('${name}Builder encode$name(builder.BuilderContext builderContext, {${builderParams.join(', ')}}) {');
+      out('${name}Builder encode$name(base.BuilderContext builderContext, {${builderParams.join(', ')}}) {');
       indent(() {
         out('${name}Builder builder = new ${name}Builder(builderContext);');
-        cls.fields.forEach((String fieldName, idlModel.FieldType type) {
+        for (idlModel.FieldDeclaration field in cls.fields) {
+          String fieldName = field.name;
           out('builder.$fieldName = $fieldName;');
-        });
+        }
         out('return builder;');
       });
       out('}');
@@ -374,4 +422,27 @@
   String quoted(String s) {
     return JSON.encode(s);
   }
+
+  /**
+   * Return the documentation text of the given [node], or `null` if the [node]
+   * does not have a comment.  Each line is `\n` separated.
+   */
+  String _getNodeDoc(LineInfo lineInfo, AnnotatedNode node) {
+    Comment comment = node.documentationComment;
+    if (comment != null &&
+        comment.isDocumentation &&
+        comment.tokens.length == 1 &&
+        comment.tokens.first.type == TokenType.MULTI_LINE_COMMENT) {
+      Token token = comment.tokens.first;
+      int column = lineInfo.getLocation(token.offset).columnNumber;
+      String indent = ' ' * (column - 1);
+      return token.lexeme.split('\n').map((String line) {
+        if (line.startsWith(indent)) {
+          line = line.substring(indent.length);
+        }
+        return line;
+      }).join('\n');
+    }
+    return null;
+  }
 }
diff --git a/pkg/analyzer/tool/summary/idl.dart b/pkg/analyzer/tool/summary/idl.dart
index 117dfe4..28d0da5 100644
--- a/pkg/analyzer/tool/summary/idl.dart
+++ b/pkg/analyzer/tool/summary/idl.dart
@@ -98,7 +98,7 @@
   List<PrelinkedDependency> dependencies;
 
   /**
-   * For each import in [UnlinkedLibrary.imports], an index into [dependencies]
+   * For each import in [UnlinkedUnit.imports], an index into [dependencies]
    * of the library being imported.
    *
    * TODO(paulberry): if [dependencies] is removed, this can be removed as
@@ -130,6 +130,12 @@
    * represent parts in the order of the corresponding `part` declarations.
    */
   int unit;
+
+  /**
+   * If the entity being referred to is generic, the number of type parameters
+   * it accepts.  Otherwise zero.
+   */
+  int numTypeParameters;
 }
 
 /**
@@ -175,6 +181,32 @@
 }
 
 /**
+ * Information about SDK.
+ */
+@topLevel
+class SdkBundle {
+  /**
+   * The list of URIs of items in [prelinkedLibraries], e.g. `dart:core`.
+   */
+  List<String> prelinkedLibraryUris;
+
+  /**
+   * Pre-linked libraries.
+   */
+  List<PrelinkedLibrary> prelinkedLibraries;
+
+  /**
+   * The list of URIs of items in [unlinkedUnits], e.g. `dart:core/bool.dart`.
+   */
+  List<String> unlinkedUnitUris;
+
+  /**
+   * Unlinked information for the compilation units constituting the SDK.
+   */
+  List<UnlinkedUnit> unlinkedUnits;
+}
+
+/**
  * Unlinked summary information about a class declaration.
  */
 class UnlinkedClass {
@@ -240,23 +272,12 @@
   /**
    * List of names which are shown.  Empty if this is a `hide` combinator.
    */
-  List<UnlinkedCombinatorName> shows;
+  List<String> shows;
 
   /**
    * List of names which are hidden.  Empty if this is a `show` combinator.
    */
-  List<UnlinkedCombinatorName> hides;
-}
-
-/**
- * Unlinked summary information about a single name in a `show` or `hide`
- * combinator.
- */
-class UnlinkedCombinatorName {
-  /**
-   * The name itself.
-   */
-  String name;
+  List<String> hides;
 }
 
 /**
@@ -516,6 +537,58 @@
 }
 
 /**
+ * Unlinked summary information about a specific name contributed by a
+ * compilation unit to a library's public namespace.
+ *
+ * TODO(paulberry): add a count of generic parameters, so that resynthesis
+ * doesn't have to peek into the library to obtain this info.
+ *
+ * TODO(paulberry): for classes, add info about static members and
+ * constructors, since this will be needed to prelink info about constants.
+ *
+ * TODO(paulberry): some of this information is redundant with information
+ * elsewhere in the summary.  Consider reducing the redundancy to reduce
+ * summary size.
+ */
+class UnlinkedPublicName {
+  /**
+   * The name itself.
+   */
+  String name;
+
+  /**
+   * The kind of object referred to by the name.
+   */
+  PrelinkedReferenceKind kind;
+}
+
+/**
+ * Unlinked summary information about what a compilation unit contributes to a
+ * library's public namespace.  This is the subset of [UnlinkedUnit] that is
+ * required from dependent libraries in order to perform prelinking.
+ */
+@topLevel
+class UnlinkedPublicNamespace {
+  /**
+   * Public names defined in the compilation unit.
+   *
+   * TODO(paulberry): consider sorting these names to reduce unnecessary
+   * relinking.
+   */
+  List<UnlinkedPublicName> names;
+
+  /**
+   * Export declarations in the compilation unit.
+   */
+  List<UnlinkedExport> exports;
+
+  /**
+   * Part declarations in the compilation unit.
+   */
+  List<UnlinkedPart> parts;
+}
+
+/**
  * Unlinked summary information about a name referred to in one library that
  * might be defined in another.
  */
@@ -629,6 +702,11 @@
   String libraryName;
 
   /**
+   * Unlinked public namespace of this compilation unit.
+   */
+  UnlinkedPublicNamespace publicNamespace;
+
+  /**
    * Top level and prefixed names referred to by this compilation unit.  The
    * zeroth element of this array is always populated and always represents a
    * reference to the pseudo-type "dynamic".
@@ -652,21 +730,11 @@
   List<UnlinkedExecutable> executables;
 
   /**
-   * Export declarations in the compilation unit.
-   */
-  List<UnlinkedExport> exports;
-
-  /**
    * Import declarations in the compilation unit.
    */
   List<UnlinkedImport> imports;
 
   /**
-   * Part declarations in the compilation unit.
-   */
-  List<UnlinkedPart> parts;
-
-  /**
    * Typedefs declared in the compilation unit.
    */
   List<UnlinkedTypedef> typedefs;
diff --git a/pkg/analyzer/tool/summary/idl_model.dart b/pkg/analyzer/tool/summary/idl_model.dart
index e298b97..07be039 100644
--- a/pkg/analyzer/tool/summary/idl_model.dart
+++ b/pkg/analyzer/tool/summary/idl_model.dart
@@ -12,28 +12,62 @@
 /**
  * Information about a single class defined in the IDL.
  */
-class ClassDeclaration {
+class ClassDeclaration extends Declaration {
   /**
    * Fields defined in the class.
    */
-  final Map<String, FieldType> fields = <String, FieldType>{};
+  final List<FieldDeclaration> fields = <FieldDeclaration>[];
 
   /**
    * Indicates whether the class has the `topLevel` annotation.
    */
   final bool isTopLevel;
 
-  ClassDeclaration(this.isTopLevel);
+  ClassDeclaration(String documentation, String name, this.isTopLevel)
+      : super(documentation, name);
+}
+
+/**
+ * Information about a declaration in the IDL.
+ */
+class Declaration {
+  /**
+   * The optional documentation, may be `null`.
+   */
+  final String documentation;
+
+  /**
+   * The name of the declaration.
+   */
+  final String name;
+
+  Declaration(this.documentation, this.name);
 }
 
 /**
  * Information about a single enum defined in the IDL.
  */
-class EnumDeclaration {
+class EnumDeclaration extends Declaration {
   /**
    * List of enumerated values.
    */
   final List<String> values = <String>[];
+
+  EnumDeclaration(String documentation, String name)
+      : super(documentation, name);
+}
+
+/**
+ * Information about a single class field defined in the IDL.
+ */
+class FieldDeclaration extends Declaration {
+  /**
+   * The file of the field.
+   */
+  final FieldType type;
+
+  FieldDeclaration(String documentation, String name, this.type)
+      : super(documentation, name);
 }
 
 /**
diff --git a/pkg/analyzer/tool/task_dependency_graph/generate.dart b/pkg/analyzer/tool/task_dependency_graph/generate.dart
index 91560b2..9b960f3 100644
--- a/pkg/analyzer/tool/task_dependency_graph/generate.dart
+++ b/pkg/analyzer/tool/task_dependency_graph/generate.dart
@@ -127,9 +127,8 @@
     DartSdk sdk = DirectoryBasedDartSdk.defaultSdk;
     context = AnalysisEngine.instance.createAnalysisContext();
     String packageRootPath;
-    if (Platform.packageRoot.isNotEmpty) {
-      Uri packageRootUri = Uri.parse(Platform.packageRoot);
-      packageRootPath = packageRootUri.toFilePath();
+    if (Platform.packageRoot != null) {
+      packageRootPath = Uri.parse(Platform.packageRoot).toFilePath();
     } else {
       packageRootPath = path.join(rootDir, 'packages');
     }
diff --git a/pkg/analyzer/tool/task_dependency_graph/tasks.dot b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
index baacc31..49a1c1a 100644
--- a/pkg/analyzer/tool/task_dependency_graph/tasks.dot
+++ b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
@@ -15,9 +15,11 @@
   BUILD_LIBRARY_ERRORS [shape=box]
   BuildCompilationUnitElementTask -> COMPILATION_UNIT_CONSTANTS
   BuildCompilationUnitElementTask -> COMPILATION_UNIT_ELEMENT
+  BuildCompilationUnitElementTask -> CREATED_RESOLVED_UNIT1
   BuildCompilationUnitElementTask -> RESOLVED_UNIT1
   BuildDirectiveElementsTask -> BUILD_DIRECTIVES_ERRORS
   BuildDirectiveElementsTask -> LIBRARY_ELEMENT2
+  BuildEnumMemberElementsTask -> CREATED_RESOLVED_UNIT2
   BuildEnumMemberElementsTask -> RESOLVED_UNIT2
   BuildExportNamespaceTask -> LIBRARY_ELEMENT4
   BuildLibraryElementTask -> BUILD_LIBRARY_ERRORS
@@ -40,6 +42,25 @@
   CONTAINING_LIBRARIES [shape=box]
   CONTENT -> ScanDartTask
   CONTENT [shape=box]
+  CREATED_RESOLVED_UNIT [shape=box]
+  CREATED_RESOLVED_UNIT1 [shape=box]
+  CREATED_RESOLVED_UNIT10 [shape=box]
+  CREATED_RESOLVED_UNIT11 [shape=box]
+  CREATED_RESOLVED_UNIT2 [shape=box]
+  CREATED_RESOLVED_UNIT3 [shape=box]
+  CREATED_RESOLVED_UNIT4 [shape=box]
+  CREATED_RESOLVED_UNIT5 [shape=box]
+  CREATED_RESOLVED_UNIT6 [shape=box]
+  CREATED_RESOLVED_UNIT7 -> ResolveInstanceFieldsInUnitTask
+  CREATED_RESOLVED_UNIT7 [shape=box]
+  CREATED_RESOLVED_UNIT8 -> InferInstanceMembersInUnitTask
+  CREATED_RESOLVED_UNIT8 [shape=box]
+  CREATED_RESOLVED_UNIT9 -> InferInstanceMembersInUnitTask
+  CREATED_RESOLVED_UNIT9 -> InferStaticVariableTypeTask
+  CREATED_RESOLVED_UNIT9 -> PartiallyResolveUnitReferencesTask
+  CREATED_RESOLVED_UNIT9 -> ResolveInstanceFieldsInUnitTask
+  CREATED_RESOLVED_UNIT9 -> ResolveUnitTask
+  CREATED_RESOLVED_UNIT9 [shape=box]
   ComputeConstantDependenciesTask -> CONSTANT_DEPENDENCIES
   ComputeConstantValueTask -> CONSTANT_VALUE
   ComputeInferableStaticVariableDependenciesTask -> INFERABLE_STATIC_VARIABLE_DEPENDENCIES
@@ -63,6 +84,7 @@
   EXPORTED_LIBRARIES [shape=box]
   EXPORT_SOURCE_CLOSURE -> BuildExportNamespaceTask
   EXPORT_SOURCE_CLOSURE [shape=box]
+  EvaluateUnitConstantsTask -> CREATED_RESOLVED_UNIT11
   EvaluateUnitConstantsTask -> RESOLVED_UNIT11
   GatherUsedImportedElementsTask -> USED_IMPORTED_ELEMENTS
   GatherUsedLocalElementsTask -> USED_LOCAL_ELEMENTS
@@ -88,8 +110,10 @@
   INFERRED_STATIC_VARIABLE -> InferStaticVariableTypesInUnitTask
   INFERRED_STATIC_VARIABLE [shape=box]
   IS_LAUNCHABLE [shape=box]
+  InferInstanceMembersInUnitTask -> CREATED_RESOLVED_UNIT9
   InferInstanceMembersInUnitTask -> RESOLVED_UNIT9
   InferStaticVariableTypeTask -> INFERRED_STATIC_VARIABLE
+  InferStaticVariableTypesInUnitTask -> CREATED_RESOLVED_UNIT7
   InferStaticVariableTypesInUnitTask -> RESOLVED_UNIT7
   LIBRARY_CYCLE [shape=box]
   LIBRARY_CYCLE_DEPENDENCIES -> InferInstanceMembersInUnitTask
@@ -170,12 +194,14 @@
   ParseDartTask -> PARSE_ERRORS
   ParseDartTask -> SOURCE_KIND
   ParseDartTask -> UNITS
+  PartiallyResolveUnitReferencesTask -> CREATED_RESOLVED_UNIT5
   PartiallyResolveUnitReferencesTask -> INFERABLE_STATIC_VARIABLES_IN_UNIT
   PartiallyResolveUnitReferencesTask -> PROPAGABLE_VARIABLES_IN_UNIT
   PartiallyResolveUnitReferencesTask -> RESOLVED_UNIT5
   PropagateVariableTypeTask -> PROPAGATED_VARIABLE
   PropagateVariableTypesInLibraryClosureTask -> LIBRARY_ELEMENT7
   PropagateVariableTypesInLibraryTask -> LIBRARY_ELEMENT6
+  PropagateVariableTypesInUnitTask -> CREATED_RESOLVED_UNIT6
   PropagateVariableTypesInUnitTask -> RESOLVED_UNIT6
   READY_LIBRARY_ELEMENT2 -> ComputeLibraryCycleTask
   READY_LIBRARY_ELEMENT2 -> ReadyLibraryElement2Task
@@ -233,10 +259,6 @@
   RESOLVED_UNIT7 [shape=box]
   RESOLVED_UNIT8 -> InferInstanceMembersInUnitTask
   RESOLVED_UNIT8 [shape=box]
-  RESOLVED_UNIT9 -> InferInstanceMembersInUnitTask
-  RESOLVED_UNIT9 -> InferStaticVariableTypeTask
-  RESOLVED_UNIT9 -> PartiallyResolveUnitReferencesTask
-  RESOLVED_UNIT9 -> ResolveInstanceFieldsInUnitTask
   RESOLVED_UNIT9 -> ResolveUnitTask
   RESOLVED_UNIT9 [shape=box]
   RESOLVE_TYPE_NAMES_ERRORS -> LibraryUnitErrorsTask
@@ -249,16 +271,20 @@
   ReadyResolvedUnit10Task -> READY_RESOLVED_UNIT10
   ReadyResolvedUnit11Task -> READY_RESOLVED_UNIT11
   ReadyResolvedUnitTask -> READY_RESOLVED_UNIT
+  ResolveInstanceFieldsInUnitTask -> CREATED_RESOLVED_UNIT8
   ResolveInstanceFieldsInUnitTask -> RESOLVED_UNIT8
   ResolveLibraryReferencesTask -> LIBRARY_ELEMENT8
   ResolveLibraryReferencesTask -> REFERENCED_NAMES
   ResolveLibraryTask -> LIBRARY_ELEMENT
   ResolveLibraryTypeNamesTask -> LIBRARY_ELEMENT5
   ResolveUnitTask -> CONSTANT_EXPRESSIONS_DEPENDENCIES
+  ResolveUnitTask -> CREATED_RESOLVED_UNIT10
   ResolveUnitTask -> RESOLVED_UNIT10
   ResolveUnitTask -> RESOLVE_UNIT_ERRORS
+  ResolveUnitTypeNamesTask -> CREATED_RESOLVED_UNIT3
   ResolveUnitTypeNamesTask -> RESOLVED_UNIT3
   ResolveUnitTypeNamesTask -> RESOLVE_TYPE_NAMES_ERRORS
+  ResolveVariableReferencesTask -> CREATED_RESOLVED_UNIT4
   ResolveVariableReferencesTask -> RESOLVED_UNIT4
   ResolveVariableReferencesTask -> VARIABLE_REFERENCE_ERRORS
   SCAN_ERRORS -> dartErrorsForSource
@@ -270,6 +296,7 @@
   ScanDartTask -> LINE_INFO
   ScanDartTask -> SCAN_ERRORS
   ScanDartTask -> TOKEN_STREAM
+  StrongModeVerifyUnitTask -> CREATED_RESOLVED_UNIT
   StrongModeVerifyUnitTask -> RESOLVED_UNIT
   StrongModeVerifyUnitTask -> STRONG_MODE_ERRORS
   TOKEN_STREAM -> ParseDartTask
diff --git a/pkg/analyzer_cli/lib/src/perf_report.dart b/pkg/analyzer_cli/lib/src/perf_report.dart
index 03791d8..208e560 100644
--- a/pkg/analyzer_cli/lib/src/perf_report.dart
+++ b/pkg/analyzer_cli/lib/src/perf_report.dart
@@ -9,6 +9,7 @@
 
 import 'package:analyzer/src/generated/utilities_general.dart'
     show PerformanceTag;
+import 'package:analyzer/task/model.dart' show AnalysisTask;
 import 'package:analyzer_cli/src/options.dart' show CommandLineOptions;
 
 const _JSON = const JsonEncoder.withIndent("  ");
@@ -70,13 +71,36 @@
   }
   perfTagsJson['other'] = otherTime;
 
-  var json = <String, dynamic>{
+  // Generate task table.
+  var taskRows = <_TaskRow>[];
+  int totalTaskTime = 0;
+  for (var key in AnalysisTask.stopwatchMap.keys) {
+    var time = AnalysisTask.stopwatchMap[key].elapsedMilliseconds;
+    if (time == 0) continue;
+    totalTaskTime += time;
+    var count = AnalysisTask.countMap[key];
+    taskRows.add(new _TaskRow(key.toString(), time, count));
+  }
+  taskRows.sort((a, b) => b.time.compareTo(a.time));
+
+  var reportJson = <String, dynamic>{
     'perfReportVersion': 0,
     'platform': platformJson,
     'options': optionsJson,
     'totalElapsedTime': totalTime,
-    'performanceTags': perfTagsJson
+    'totalTaskTime': totalTaskTime,
+    'performanceTags': perfTagsJson,
+    'tasks': taskRows.map((r) => r.toJson()).toList(),
   };
 
-  return _JSON.convert(json);
+  return _JSON.convert(reportJson);
+}
+
+class _TaskRow {
+  final String name;
+  final int time;
+  final int count;
+  _TaskRow(this.name, this.time, this.count);
+
+  Map toJson() => <String, dynamic>{'name': name, 'time': time, 'count': count};
 }
diff --git a/pkg/compiler/lib/src/common/names.dart b/pkg/compiler/lib/src/common/names.dart
index 27b844f..f777c0a 100644
--- a/pkg/compiler/lib/src/common/names.dart
+++ b/pkg/compiler/lib/src/common/names.dart
@@ -72,6 +72,8 @@
   static const Name CALL_NAME = Names.call;
 
   static const Name length = const PublicName(Identifiers.length);
+
+  static const Name runtimeType_ = const PublicName(Identifiers.runtimeType_);
 }
 
 /// [Selector]s commonly used.
@@ -114,13 +116,15 @@
 
   static final Selector index = new Selector.index();
 
+  static final Selector runtimeType_ = new Selector.getter(Names.runtimeType_);
+
   /// List of all the selectors held in static fields.
   ///
   /// These objects are shared between different runs in batch-mode and must
   /// thus remain in the [Selector.canonicalizedValues] map.
   static final List<Selector> ALL = <Selector>[
       cancel, current, iterator, moveNext, noSuchMethod_, toString_,
-      hashCode_, compareTo, equals, length, codeUnitAt, index];
+      hashCode_, compareTo, equals, length, codeUnitAt, index, runtimeType_];
 }
 
 /// [Uri]s commonly used.
diff --git a/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart b/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart
new file mode 100644
index 0000000..e5caa83
--- /dev/null
+++ b/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart
@@ -0,0 +1,131 @@
+library dart2js.cps_ir.backward_null_check_remover;
+
+import 'cps_ir_nodes.dart';
+import 'optimizers.dart' show Pass;
+import '../common/names.dart';
+import '../universe/selector.dart';
+import 'type_mask_system.dart';
+import 'cps_fragment.dart';
+
+/// Removes null checks that are follwed by another instruction that will
+/// perform the same check.
+///
+/// For example:
+///
+///     x.toString; // NullCheck instruction
+///     print(x.length);
+///
+/// ==>
+///
+///     print(x.length);
+///
+/// `x.length` will throw when x is null, so the original [NullCheck] is not
+/// needed.  This changes the error message, but at least for now we are
+/// willing to accept this.
+///
+/// Note that code motion may not occur after this pass, since the [NullCheck]
+/// nodes are not there to restrict it.
+//
+// TODO(asgerf): It would be nice with a clear specification of when we allow
+//   the wording of error message to change.  E.g. "toString" is already pretty
+//   bad so changing that should be ok, but changing a field access is not as
+//   clear.
+//
+class BackwardNullCheckRemover extends TrampolineRecursiveVisitor
+                               implements Pass {
+  String get passName => 'Backward null-check remover';
+
+  final TypeMaskSystem typeSystem;
+
+  /// When the analysis of an expression completes, [nullCheckValue] refers to
+  /// a value that is checked in the beginning of that expression.
+  Primitive nullCheckedValue;
+
+  BackwardNullCheckRemover(this.typeSystem);
+
+  void rewrite(FunctionDefinition node) {
+    visit(node);
+  }
+
+  /// Returns a reference to an operand of [prim], where [prim] throws if null
+  /// is passed into that operand.
+  Reference<Primitive> getNullCheckedOperand(Primitive prim) {
+    if (prim is NullCheck) return prim.value;
+    if (prim is GetLength) return prim.object;
+    if (prim is GetField) return prim.object;
+    if (prim is GetIndex) return prim.object;
+    if (prim is SetField) return prim.object;
+    if (prim is SetIndex) return prim.object;
+    if (prim is InvokeMethod && !nullSelectors.contains(prim.selector)) {
+      return prim.dartReceiverReference;
+    }
+    return null;
+  }
+
+  static final List<Selector> nullSelectors = <Selector>[
+      Selectors.equals, Selectors.hashCode_, Selectors.noSuchMethod_,
+      Selectors.runtimeType_];
+
+  /// It has been determined that the null check in [prim] made redundant by
+  /// [newNullCheck].  Eliminate [prim] if it is not needed any more.
+  void tryEliminateRedundantNullCheck(Primitive prim, Primitive newNullCheck) {
+    if (prim is NullCheck) {
+      Primitive value = prim.value.definition;
+      LetPrim let = prim.parent;
+      prim..replaceUsesWith(value)..destroy();
+      let.remove();
+    } else if (prim is GetLength || prim is GetField || prim is GetIndex) {
+      if (prim.hasNoEffectiveUses) {
+        destroyRefinementsOfDeadPrimitive(prim);
+        LetPrim let = prim.parent;
+        prim..destroy();
+        let.remove();
+      }
+    }
+  }
+
+  /// True if [prim] can be moved above a null check.  This is safe if [prim]
+  /// cannot throw or have side effects and does not carry any path-sensitive
+  /// type information, such as [Refinement] nodes do.
+  //
+  // TODO(asgerf): This prevents elimination of the .length created for a bounds
+  //   check, because there is a refinement node below it.  To handle this, we
+  //   would have to relocate the [Refinement] node below the new null check.
+  bool canMoveAboveNullCheck(Primitive prim) {
+    return prim.isSafeForReordering;
+  }
+
+  Expression traverseLetPrim(LetPrim node) {
+    Primitive prim = node.primitive;
+    Primitive receiver = getNullCheckedOperand(prim)?.definition;
+    if (receiver != null) {
+      pushAction(() {
+        Primitive successor = nullCheckedValue;
+        if (successor != null && receiver.sameValue(successor)) {
+          tryEliminateRedundantNullCheck(prim, successor);
+        }
+        nullCheckedValue = receiver;
+      });
+    } else if (!canMoveAboveNullCheck(prim)) {
+      pushAction(() {
+        nullCheckedValue = null;
+      });
+    }
+    return node.body;
+  }
+
+  Expression traverseContinuation(Continuation cont) {
+    pushAction(() {
+      nullCheckedValue = null;
+    });
+    return cont.body;
+  }
+
+  Expression traverseLetHandler(LetHandler node) {
+    push(node.handler);
+    pushAction(() {
+      nullCheckedValue = null;
+    });
+    return node.body;
+  }
+}
diff --git a/pkg/compiler/lib/src/cps_ir/bounds_checker.dart b/pkg/compiler/lib/src/cps_ir/bounds_checker.dart
index 223c24a..44cbbb0 100644
--- a/pkg/compiler/lib/src/cps_ir/bounds_checker.dart
+++ b/pkg/compiler/lib/src/cps_ir/bounds_checker.dart
@@ -493,7 +493,6 @@
   void visitBoundsCheck(BoundsCheck node) {
     if (node.checks == BoundsCheck.NONE) return;
     assert(node.index != null); // Because there is at least one check.
-    Primitive object = node.object.definition;
     SignedVariable length = node.length == null
         ? null
         : getValue(node.length.definition);
diff --git a/pkg/compiler/lib/src/cps_ir/cps_fragment.dart b/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
index 5d56560..a4bd305 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
@@ -130,11 +130,14 @@
 
   /// Inserts an invocation and returns a primitive holding the returned value.
   Primitive invokeMethod(Primitive receiver,
-                         Selector selector,
-                         TypeMask mask,
-                         List<Primitive> arguments) {
-    return letPrim(new InvokeMethod(receiver, selector, mask, arguments,
-        sourceInformation));
+      Selector selector,
+      TypeMask mask,
+      List<Primitive> arguments,
+      [CallingConvention callingConvention = CallingConvention.Normal]) {
+    InvokeMethod invoke =
+        new InvokeMethod(receiver, selector, mask, arguments, sourceInformation)
+            ..callingConvention = callingConvention;
+    return letPrim(invoke);
   }
 
   /// Inserts an invocation and returns a primitive holding the returned value.
@@ -346,3 +349,17 @@
   parent.body = newNode;
   newNode.parent = parent;
 }
+
+/// Removes all [Refinement] uses of a given primitive that has no effective
+/// uses.
+void destroyRefinementsOfDeadPrimitive(Primitive prim) {
+  while (prim.firstRef != null) {
+    Refinement refine = prim.firstRef.parent;
+    destroyRefinementsOfDeadPrimitive(refine);
+    LetPrim letPrim = refine.parent;
+    InteriorNode parent = letPrim.parent;
+    parent.body = letPrim.body;
+    letPrim.body.parent = parent;
+    prim.firstRef.unlink();
+  }
+}
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
index a80f2f7..76b2d22 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
@@ -653,14 +653,6 @@
     return primitive;
   }
 
-  ir.Primitive _continueWithExpression(ir.Expression build(ir.Continuation k)) {
-    ir.Parameter v = new ir.Parameter(null);
-    ir.Continuation k = new ir.Continuation([v]);
-    ir.Expression expression = build(k);
-    add(new ir.LetCont(k, expression));
-    return v;
-  }
-
   ir.Primitive _buildInvokeStatic(Element element,
                                   Selector selector,
                                   List<ir.Primitive> arguments,
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
index afc4cd7..ee7a870 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
@@ -3565,10 +3565,8 @@
           ConstantValue interceptorValue =
               new InterceptorConstantValue(constant.representedType);
           return irBuilder.buildConstant(interceptorValue);
-        } else {
-          internalError(argument, 'expected Type as argument');
         }
-        break;
+        return internalError(argument, 'expected Type as argument');
 
       case 'JS_EFFECT':
         return irBuilder.buildNullConstant();
@@ -3649,8 +3647,7 @@
             CallStructure.TWO_ARGS);
 
       default:
-        giveup(node, 'unplemented native construct: ${function.name}');
-        break;
+        return giveup(node, 'unplemented native construct: ${function.name}');
     }
   }
 
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
index 02b963e..e34a4a4 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -4,6 +4,7 @@
 library dart2js.ir_nodes;
 
 import 'dart:collection';
+import 'cps_fragment.dart' show CpsFragment;
 import '../constants/values.dart' as values;
 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType;
 import '../elements/elements.dart';
@@ -203,18 +204,7 @@
 ///
 /// All primitives except [Parameter] must be bound by a [LetPrim].
 abstract class Primitive extends Variable<Primitive> {
-  /// The [VariableElement] or [ParameterElement] from which the primitive
-  /// binding originated.
-  Entity hint;
-
-  /// Use the given element as a hint for naming this primitive.
-  ///
-  /// Has no effect if this primitive already has a non-null [element].
-  void useElementAsHint(Entity hint) {
-    if (this.hint == null) {
-      this.hint = hint;
-    }
-  }
+  Primitive() : super(null);
 
   /// True if this primitive has a value that can be used by other expressions.
   bool get hasValue;
@@ -295,6 +285,23 @@
     newDefinition.parent = let;
     newDefinition.useElementAsHint(hint);
   }
+
+  /// Replaces this definition with a CPS fragment (a term with a hole in it),
+  /// given the value to replace the uses of the definition with.
+  ///
+  /// This can be thought of as substituting:
+  ///
+  ///     let x = OLD in BODY
+  ///       ==>
+  ///     FRAGMENT[BODY{newPrimitive/x}]
+  void replaceWithFragment(CpsFragment fragment, Primitive newPrimitive) {
+    assert(this is! Parameter);
+    replaceUsesWith(newPrimitive);
+    destroy();
+    LetPrim let = parent;
+    fragment.insertBelow(let);
+    let.remove();
+  }
 }
 
 /// A primitive that is generally not safe for elimination, but may be marked
@@ -464,6 +471,43 @@
   }
 }
 
+enum CallingConvention {
+  /// JS receiver is the Dart receiver, there are no extra arguments.
+  ///
+  /// This includes cases (e.g., static functions, constructors) where there
+  /// is no receiver.
+  ///
+  /// For example: `foo.bar$1(x)`
+  Normal,
+
+  /// JS receiver is an interceptor, the first argument is the Dart receiver.
+  ///
+  /// For example: `getInterceptor(foo).bar$1(foo, x)`
+  Intercepted,
+
+  /// JS receiver is the Dart receiver, the first argument is a dummy value.
+  ///
+  /// For example: `foo.bar$1(0, x)`
+  DummyIntercepted,
+
+  /// JS receiver is the Dart receiver, there are no extra arguments.
+  ///
+  /// Compiles to a one-shot interceptor, e.g: `J.bar$1(foo, x)`
+  OneShotIntercepted,
+}
+
+/// Base class of function invocations.
+///
+/// This class defines the common interface of function invocations.
+abstract class InvocationPrimitive extends UnsafePrimitive {
+  Reference<Primitive> get receiver => null;
+  List<Reference<Primitive>> get arguments;
+  SourceInformation get sourceInformation;
+
+  Reference<Primitive> get dartReceiverReference => null;
+  CallingConvention get callingConvention => CallingConvention.Normal;
+}
+
 /// Invoke a static function.
 ///
 /// All optional arguments declared by [target] are passed in explicitly, and
@@ -472,7 +516,7 @@
 /// Discussion:
 /// All information in the [selector] is technically redundant; it will likely
 /// be removed.
-class InvokeStatic extends UnsafePrimitive {
+class InvokeStatic extends InvocationPrimitive {
   final FunctionElement target;
   final Selector selector;
   final List<Reference<Primitive>> arguments;
@@ -498,28 +542,6 @@
   }
 }
 
-enum CallingConvention {
-  /// JS receiver is the Dart receiver, there are no extra arguments.
-  ///
-  /// For example: `foo.bar$1(x)`
-  Normal,
-
-  /// JS receiver is an interceptor, the first argument is the Dart receiver.
-  ///
-  /// For example: `getInterceptor(foo).bar$1(foo, x)`
-  Intercepted,
-
-  /// JS receiver is the Dart receiver, the first argument is a dummy value.
-  ///
-  /// For example: `foo.bar$1(0, x)`
-  DummyIntercepted,
-
-  /// JS receiver is the Dart receiver, there are no extra arguments.
-  ///
-  /// Compiles to a one-shot interceptor, e.g: `J.bar$1(foo, x)`
-  OneShotIntercepted,
-}
-
 /// Invoke a method on an object.
 ///
 /// This includes getters, setters, operators, and index getter/setters.
@@ -529,7 +551,7 @@
 ///
 /// The [selector] records the names of named arguments. The value of named
 /// arguments occur at the end of the [arguments] list, in normalized order.
-class InvokeMethod extends UnsafePrimitive {
+class InvokeMethod extends InvocationPrimitive {
   Reference<Primitive> receiver;
   Selector selector;
   TypeMask mask;
@@ -606,7 +628,7 @@
 ///
 /// All optional arguments declared by [target] are passed in explicitly, and
 /// occur at the end of [arguments] list, in normalized order.
-class InvokeMethodDirectly extends UnsafePrimitive {
+class InvokeMethodDirectly extends InvocationPrimitive {
   Reference<Primitive> receiver;
   final FunctionElement target;
   final Selector selector;
@@ -664,7 +686,7 @@
 ///
 /// Note that [InvokeConstructor] does it itself allocate an object.
 /// The invoked constructor will do that using [CreateInstance].
-class InvokeConstructor extends UnsafePrimitive {
+class InvokeConstructor extends InvocationPrimitive {
   final DartType dartType;
   final ConstructorElement target;
   final List<Reference<Primitive>> arguments;
@@ -1688,13 +1710,24 @@
   ///
   /// Is `null` until initialized by type propagation.
   TypeMask type;
+
+  /// The [VariableElement] or [ParameterElement] from which the variable
+  /// binding originated.
+  Entity hint;
+
+  Variable(this.hint);
+
+  /// Use the given element as a hint for naming this primitive.
+  ///
+  /// Has no effect if this primitive already has a non-null [element].
+  void useElementAsHint(Entity hint) {
+    this.hint ??= hint;
+  }
 }
 
 /// Identifies a mutable variable.
 class MutableVariable extends Variable<MutableVariable> {
-  Entity hint;
-
-  MutableVariable(this.hint);
+  MutableVariable(Entity hint) : super(hint);
 
   accept(Visitor v) => v.visitMutableVariable(this);
 
@@ -1874,23 +1907,23 @@
   T visitLetHandler(LetHandler node);
   T visitLetMutable(LetMutable node);
   T visitInvokeContinuation(InvokeContinuation node);
+  T visitThrow(Throw node);
+  T visitRethrow(Rethrow node);
+  T visitBranch(Branch node);
+  T visitUnreachable(Unreachable node);
+
+  // Definitions.
   T visitInvokeStatic(InvokeStatic node);
   T visitInvokeMethod(InvokeMethod node);
   T visitInvokeMethodDirectly(InvokeMethodDirectly node);
   T visitInvokeConstructor(InvokeConstructor node);
-  T visitThrow(Throw node);
-  T visitRethrow(Rethrow node);
-  T visitBranch(Branch node);
   T visitTypeCast(TypeCast node);
   T visitSetMutable(SetMutable node);
   T visitSetStatic(SetStatic node);
-  T visitGetLazyStatic(GetLazyStatic node);
   T visitSetField(SetField node);
-  T visitUnreachable(Unreachable node);
+  T visitGetLazyStatic(GetLazyStatic node);
   T visitAwait(Await node);
   T visitYield(Yield node);
-
-  // Definitions.
   T visitLiteralList(LiteralList node);
   T visitLiteralMap(LiteralMap node);
   T visitConstant(Constant node);
@@ -2392,3 +2425,373 @@
     (new RemovalVisitor()).visit(node);
   }
 }
+
+/// A visitor to copy instances of [Definition] or its subclasses, except for
+/// instances of [Continuation].
+///
+/// The visitor maintains a map from original definitions to their copies.
+/// When the [copy] method is called for a non-Continuation definition,
+/// a copy is created, added to the map and returned as the result. Copying a
+/// definition assumes that the definitions of all references have already
+/// been copied by the same visitor.
+class DefinitionCopyingVisitor extends Visitor<Definition> {
+  Map<Definition, Definition> _copies = <Definition, Definition>{};
+
+  /// Put a copy into the map.
+  ///
+  /// This method should be used instead of directly adding copies to the map.
+  Definition putCopy(Definition original, Definition copy) {
+    if (copy is Variable) {
+      Variable originalVariable = original;
+      copy.type = originalVariable.type;
+      copy.hint = originalVariable.hint;
+    }
+    return _copies[original] = copy;
+  }
+
+  /// Get the copy of a [Reference]'s definition from the map.
+  Definition getCopy(Reference reference) => _copies[reference.definition];
+
+  /// Map a list of [Reference]s to the list of their definition's copies.
+  List<Definition> getList(List<Reference> list) => list.map(getCopy).toList();
+
+  /// Copy a non-[Continuation] [Definition].
+  Definition copy(Definition node) {
+    assert (node is! Continuation);
+    return putCopy(node, visit(node));
+  }
+
+  Definition visit(Node node) => node.accept(this);
+
+  visitFunctionDefinition(FunctionDefinition node) {}
+  visitLetPrim(LetPrim node) {}
+  visitLetCont(LetCont node) {}
+  visitLetHandler(LetHandler node) {}
+  visitLetMutable(LetMutable node) {}
+  visitInvokeContinuation(InvokeContinuation node) {}
+  visitThrow(Throw node) {}
+  visitRethrow(Rethrow node) {}
+  visitBranch(Branch node) {}
+  visitUnreachable(Unreachable node) {}
+  visitContinuation(Continuation node) {}
+
+  Definition visitInvokeStatic(InvokeStatic node) {
+    return new InvokeStatic(node.target, node.selector, getList(node.arguments),
+        node.sourceInformation);
+  }
+
+  Definition visitInvokeMethod(InvokeMethod node) {
+    return new InvokeMethod(getCopy(node.receiver), node.selector, node.mask,
+        getList(node.arguments),
+        node.sourceInformation);
+  }
+
+  Definition visitInvokeMethodDirectly(InvokeMethodDirectly node) {
+    return new InvokeMethodDirectly(getCopy(node.receiver), node.target,
+        node.selector,
+        getList(node.arguments),
+        node.sourceInformation);
+  }
+
+  Definition visitInvokeConstructor(InvokeConstructor node) {
+    return new InvokeConstructor(node.dartType, node.target, node.selector,
+        getList(node.arguments),
+        node.sourceInformation);
+  }
+
+  Definition visitTypeCast(TypeCast node) {
+    return new TypeCast(getCopy(node.value), node.dartType,
+        getList(node.typeArguments));
+  }
+
+  Definition visitSetMutable(SetMutable node) {
+    return new SetMutable(getCopy(node.variable), getCopy(node.value));
+  }
+
+  Definition visitSetStatic(SetStatic node) {
+    return new SetStatic(node.element, getCopy(node.value),
+        node.sourceInformation);
+  }
+
+  Definition visitSetField(SetField node) {
+    return new SetField(getCopy(node.object), node.field, getCopy(node.value));
+  }
+
+  Definition visitGetLazyStatic(GetLazyStatic node) {
+    return new GetLazyStatic(node.element, node.sourceInformation);
+  }
+
+  Definition visitAwait(Await node) {
+    return new Await(getCopy(node.input));
+  }
+
+  Definition visitYield(Yield node) {
+    return new Yield(getCopy(node.input), node.hasStar);
+  }
+
+  Definition visitLiteralList(LiteralList node) {
+    return new LiteralList(node.dartType, getList(node.values));
+  }
+
+  Definition visitLiteralMap(LiteralMap node) {
+    List<LiteralMapEntry> entries = node.entries.map((LiteralMapEntry entry) {
+      return new LiteralMapEntry(getCopy(entry.key), getCopy(entry.value));
+    }).toList();
+    return new LiteralMap(node.dartType, entries);
+  }
+
+  Definition visitConstant(Constant node) {
+    return new Constant(node.value, sourceInformation: node.sourceInformation);
+  }
+
+  Definition visitGetMutable(GetMutable node) {
+    return new GetMutable(getCopy(node.variable));
+  }
+
+  Definition visitParameter(Parameter node) {
+    return new Parameter(node.hint);
+  }
+
+  Definition visitMutableVariable(MutableVariable node) {
+    return new MutableVariable(node.hint);
+  }
+
+  Definition visitGetStatic(GetStatic node) {
+    return new GetStatic(node.element, node.sourceInformation);
+  }
+
+  Definition visitInterceptor(Interceptor node) {
+    return new Interceptor(getCopy(node.input), node.sourceInformation)
+        ..interceptedClasses.addAll(node.interceptedClasses);
+  }
+
+  Definition visitCreateInstance(CreateInstance node) {
+    return new CreateInstance(node.classElement, getList(node.arguments),
+        getList(node.typeInformation),
+        node.sourceInformation);
+  }
+
+  Definition visitGetField(GetField node) {
+    return new GetField(getCopy(node.object), node.field);
+  }
+
+  Definition visitCreateBox(CreateBox node) {
+    return new CreateBox();
+  }
+
+  Definition visitReifyRuntimeType(ReifyRuntimeType node) {
+    return new ReifyRuntimeType(getCopy(node.value), node.sourceInformation);
+  }
+
+  Definition visitReadTypeVariable(ReadTypeVariable node) {
+    return new ReadTypeVariable(node.variable, getCopy(node.target),
+        node.sourceInformation);
+  }
+
+  Definition visitTypeExpression(TypeExpression node) {
+    return new TypeExpression(node.dartType, getList(node.arguments));
+  }
+
+  Definition visitCreateInvocationMirror(CreateInvocationMirror node) {
+    return new CreateInvocationMirror(node.selector, getList(node.arguments));
+  }
+
+  Definition visitTypeTest(TypeTest node) {
+    return new TypeTest(getCopy(node.value), node.dartType,
+        getList(node.typeArguments));
+  }
+
+  Definition visitTypeTestViaFlag(TypeTestViaFlag node) {
+    return new TypeTestViaFlag(getCopy(node.interceptor), node.dartType);
+  }
+
+  Definition visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
+    return new ApplyBuiltinOperator(node.operator, getList(node.arguments),
+        node.sourceInformation);
+  }
+
+  Definition visitApplyBuiltinMethod(ApplyBuiltinMethod node) {
+    return new ApplyBuiltinMethod(node.method, getCopy(node.receiver),
+        getList(node.arguments),
+        node.sourceInformation,
+        receiverIsNotNull: node.receiverIsNotNull);
+  }
+
+  Definition visitGetLength(GetLength node) {
+    return new GetLength(getCopy(node.object));
+  }
+
+  Definition visitGetIndex(GetIndex node) {
+    return new GetIndex(getCopy(node.object), getCopy(node.index));
+  }
+
+  Definition visitSetIndex(SetIndex node) {
+    return new SetIndex(getCopy(node.object), getCopy(node.index),
+        getCopy(node.value));
+  }
+
+  Definition visitRefinement(Refinement node) {
+    return new Refinement(getCopy(node.value), node.refineType);
+  }
+
+  Definition visitBoundsCheck(BoundsCheck node) {
+    if (node.hasNoChecks) {
+      return new BoundsCheck.noCheck(getCopy(node.object),
+          node.sourceInformation);
+    } else {
+      return new BoundsCheck(getCopy(node.object), getCopy(node.index),
+          getCopy(node.length),
+          node.checks,
+          node.sourceInformation);
+    }
+  }
+
+  Definition visitNullCheck(NullCheck node) {
+    return new NullCheck(getCopy(node.value), node.sourceInformation);
+  }
+
+  Definition visitForeignCode(ForeignCode node) {
+    return new ForeignCode(node.codeTemplate, node.type,
+        getList(node.arguments),
+        node.nativeBehavior,
+        dependency: node.dependency);
+  }
+}
+
+/// A trampolining visitor to copy [FunctionDefinition]s.
+class CopyingVisitor extends TrampolineRecursiveVisitor {
+  // The visitor maintains a map from original continuations to their copies.
+  Map<Continuation, Continuation> _copies = <Continuation, Continuation>{};
+
+  // The visitor uses an auxiliary visitor to copy definitions.
+  DefinitionCopyingVisitor _definitions = new DefinitionCopyingVisitor();
+
+  // While copying a block, the state of the visitor is a 'linked list' of
+  // the expressions in the block's body, with a pointer to the last element
+  // of the list.
+  Expression _first = null;
+  Expression _current = null;
+
+  void plug(Expression body) {
+    if (_first == null) {
+      _first = body;
+    } else {
+      assert(_current != null);
+      InteriorExpression interior = _current;
+      interior.body = body;
+    }
+    _current = body;
+  }
+
+  // Continuations are added to the visitor's stack to be visited after copying
+  // the current block is finished.  The stack action saves the current block,
+  // copies the continuation's body, sets the body on the copy of the
+  // continuation, and restores the current block.
+  //
+  // Note that continuations are added to the copy map before the stack action
+  // to visit them is performed.
+  void push(Continuation cont) {
+    assert(!cont.isReturnContinuation);
+    _stack.add(() {
+      Expression savedFirst = _first;
+      _first = _current = null;
+      _processBlock(cont.body);
+      _copies[cont].body = _first;
+      _first = savedFirst;
+      _current = null;
+    });
+  }
+
+  FunctionDefinition copy(FunctionDefinition node) {
+    assert(_first == null && _current == null);
+    _first = _current = null;
+    // Definitions are copied where they are bound, before processing
+    // expressions in the scope of their binding.
+    Parameter thisParameter = node.thisParameter == null
+        ? null
+        : _definitions.copy(node.thisParameter);
+    List<Parameter> parameters =
+        node.parameters.map(_definitions.copy).toList();
+    // Though the return continuation's parameter does not have any uses,
+    // we still make a proper copy to ensure that hints, type, etc. are
+    // copied.
+    Parameter returnParameter =
+        _definitions.copy(node.returnContinuation.parameters.first);
+    Continuation returnContinuation = _copies[node.returnContinuation] =
+        new Continuation([returnParameter]);
+
+    visit(node.body);
+    FunctionDefinition copy = new FunctionDefinition(node.element,
+        thisParameter,
+        parameters,
+        returnContinuation,
+        _first);
+    _first = _current = null;
+    return copy;
+  }
+
+  Node visit(Node node) => node.accept(this);
+
+  Expression traverseLetCont(LetCont node) {
+    // Continuations are copied where they are bound, before processing
+    // expressions in the scope of their binding.
+    List<Continuation> continuations = node.continuations.map((Continuation c) {
+      push(c);
+      return _copies[c] =
+          new Continuation(c.parameters.map(_definitions.copy).toList());
+    }).toList();
+    plug(new LetCont.many(continuations, null));
+    return node.body;
+  }
+
+  Expression traverseLetHandler(LetHandler node) {
+    // Continuations are copied where they are bound, before processing
+    // expressions in the scope of their binding.
+    push(node.handler);
+    Continuation handler = _copies[node.handler] =
+        new Continuation(node.handler.parameters.map(_definitions.copy)
+            .toList());
+    plug(new LetHandler(handler, null));
+    return node.body;
+  }
+
+  Expression traverseLetPrim(LetPrim node) {
+    plug(new LetPrim(_definitions.copy(node.primitive)));
+    return node.body;
+  }
+
+  Expression traverseLetMutable(LetMutable node) {
+    plug(new LetMutable(_definitions.copy(node.variable),
+        _definitions.getCopy(node.value)));
+    return node.body;
+  }
+
+  // Tail expressions do not have references, so we do not need to map them
+  // to their copies.
+  visitInvokeContinuation(InvokeContinuation node) {
+    plug(new InvokeContinuation(_copies[node.continuation.definition],
+        _definitions.getList(node.arguments),
+        isRecursive: node.isRecursive,
+        isEscapingTry: node.isEscapingTry,
+        sourceInformation: node.sourceInformation));
+  }
+
+  visitThrow(Throw node) {
+    plug(new Throw(_definitions.getCopy(node.value)));
+  }
+
+  visitRethrow(Rethrow node) {
+    plug(new Rethrow());
+  }
+
+  visitBranch(Branch node) {
+    plug(new Branch.loose(_definitions.getCopy(node.condition),
+        _copies[node.trueContinuation.definition],
+        _copies[node.falseContinuation.definition])
+      ..isStrictCheck = node.isStrictCheck);
+  }
+
+  visitUnreachable(Unreachable node) {
+    plug(new Unreachable());
+  }
+}
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
index bf857f9..bde9b0e 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
@@ -48,6 +48,7 @@
   /// Main entry point for creating a [String] from a [Node].  All recursive
   /// calls must go through this method.
   String visit(Node node) {
+    if (node == null) return '**** NULL ****';
     String s = node.accept(this);
     return decorator(node, s);
   }
@@ -112,20 +113,25 @@
   }
 
   String formatArguments(CallStructure call,
-        List<Reference<Primitive>> arguments,
-        [CallingConvention callingConvention = CallingConvention.Normal]) {
+      List<Reference<Primitive>> arguments,
+      [CallingConvention callingConvention = CallingConvention.Normal]) {
     int positionalArgumentCount = call.positionalArgumentCount;
-    if (callingConvention == CallingConvention.Intercepted) {
+    if (callingConvention == CallingConvention.Intercepted ||
+        callingConvention == CallingConvention.DummyIntercepted) {
       ++positionalArgumentCount;
     }
     List<String> args =
-        arguments.getRange(0, positionalArgumentCount).map(access).toList();
+        arguments.take(positionalArgumentCount).map(access).toList();
     List<String> argumentNames = call.getOrderedNamedArguments();
     for (int i = 0; i < argumentNames.length; ++i) {
       String name = argumentNames[i];
       String arg = access(arguments[positionalArgumentCount + i]);
       args.add("($name: $arg)");
     }
+    // Constructors can have type parameter after the named arguments.
+    args.addAll(
+        arguments.skip(positionalArgumentCount + argumentNames.length)
+            .map(access));
     return '(${args.join(' ')})';
   }
 
@@ -170,7 +176,8 @@
     String name = access(node.continuation);
     if (node.isRecursive) name = 'rec $name';
     String args = node.arguments.map(access).join(' ');
-    return '$indentation(InvokeContinuation $name ($args))';
+    String escaping = node.isEscapingTry ? ' escape' : '';
+    return '$indentation(InvokeContinuation $name ($args)$escaping)';
   }
 
   String visitThrow(Throw node) {
diff --git a/pkg/compiler/lib/src/cps_ir/inline.dart b/pkg/compiler/lib/src/cps_ir/inline.dart
new file mode 100644
index 0000000..d3d2672
--- /dev/null
+++ b/pkg/compiler/lib/src/cps_ir/inline.dart
@@ -0,0 +1,515 @@
+// 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 cps_ir.optimization.inline;
+
+import 'cps_fragment.dart';
+import 'cps_ir_builder.dart' show ThisParameterLocal;
+import 'cps_ir_nodes.dart';
+import 'optimizers.dart';
+import 'type_mask_system.dart' show TypeMaskSystem;
+import '../dart_types.dart' show DartType, GenericType;
+import '../world.dart' show World;
+import '../elements/elements.dart';
+import '../js_backend/js_backend.dart' show JavaScriptBackend;
+import '../js_backend/codegen/task.dart' show CpsFunctionCompiler;
+import '../types/types.dart' show
+    FlatTypeMask, ForwardingTypeMask, TypeMask, UnionTypeMask;
+import '../universe/call_structure.dart' show CallStructure;
+import '../universe/selector.dart' show Selector;
+
+/// Inlining stack entries.
+///
+/// During inlining, a stack is used to detect cycles in the call graph.
+class StackEntry {
+  // Dynamically resolved calls might be targeting an adapter function that
+  // fills in optional arguments not passed at the call site.  Therefore these
+  // calls are represented by the eventual target and the call structure at
+  // the call site, which together identify the target.  Statically resolved
+  // calls are represented by the target element and a null call structure.
+  final ExecutableElement target;
+  final CallStructure callStructure;
+
+  StackEntry(this.target, this.callStructure);
+
+  bool match(ExecutableElement otherTarget, CallStructure otherCallStructure) {
+    if (target != otherTarget) return false;
+    if (callStructure == null) return otherCallStructure == null;
+    return otherCallStructure != null &&
+        callStructure.match(otherCallStructure);
+  }
+}
+
+/// Inlining cache entries.
+class CacheEntry {
+  // The cache maps a function element to a list of entries, where each entry
+  // is a tuple of (call structure, abstract receiver, abstract arguments)
+  // along with the inlining decision and optional IR function definition.
+  final CallStructure callStructure;
+  final TypeMask receiver;
+  final List<TypeMask> arguments;
+
+  final bool decision;
+  final FunctionDefinition function;
+
+  CacheEntry(this.callStructure, this.receiver, this.arguments, this.decision,
+      this.function);
+
+  bool match(CallStructure otherCallStructure, TypeMask otherReceiver,
+      List<TypeMask> otherArguments) {
+    if (callStructure == null) {
+      if (otherCallStructure != null) return false;
+    } else if (otherCallStructure == null ||
+               !callStructure.match(otherCallStructure)) {
+      return false;
+    }
+
+    if (receiver != otherReceiver) return false;
+    assert(arguments.length == otherArguments.length);
+    for (int i = 0; i < arguments.length; ++i) {
+      if (arguments[i] != otherArguments[i]) return false;
+    }
+    return true;
+  }
+}
+
+/// An inlining cache.
+///
+/// During inlining a cache is used to remember inlining decisions for shared
+/// parts of the call graph, to avoid exploring them more than once.
+///
+/// The cache maps a tuple of (function element, call structure,
+/// abstract receiver, abstract arguments) to a boolean inlining decision and
+/// an IR function definition if the decision is positive.
+class InliningCache {
+  static const int ABSENT = -1;
+  static const int NO_INLINE = 0;
+
+  final Map<ExecutableElement, List<CacheEntry>> map =
+      <ExecutableElement, List<CacheEntry>>{};
+
+  // When function definitions are put into or removed from the cache, they are
+  // copied because the compiler passes will mutate them.
+  final CopyingVisitor copier = new CopyingVisitor();
+
+  void _putInternal(ExecutableElement element, CallStructure callStructure,
+      TypeMask receiver,
+      List<TypeMask> arguments,
+      bool decision,
+      FunctionDefinition function) {
+    map.putIfAbsent(element, () => <CacheEntry>[])
+        .add(new CacheEntry(callStructure, receiver, arguments, decision,
+            function));
+  }
+
+  /// Put a positive inlining decision in the cache.
+  ///
+  /// A positive inlining decision maps to an IR function definition.
+  void putPositive(ExecutableElement element, CallStructure callStructure,
+      TypeMask receiver,
+      List<TypeMask> arguments,
+      FunctionDefinition function) {
+    _putInternal(element, callStructure, receiver, arguments, true,
+        copier.copy(function));
+  }
+
+  /// Put a negative inlining decision in the cache.
+  void putNegative(ExecutableElement element,
+      CallStructure callStructure,
+      TypeMask receiver,
+      List<TypeMask> arguments) {
+    _putInternal(element, callStructure, receiver, arguments, false, null);
+  }
+
+  /// Look up a tuple in the cache.
+  ///
+  /// A positive lookup result return the IR function definition.  A negative
+  /// lookup result returns [NO_INLINE].  If there is no cached result,
+  /// [ABSENT] is returned.
+  get(ExecutableElement element, CallStructure callStructure, TypeMask receiver,
+      List<TypeMask> arguments) {
+    List<CacheEntry> entries = map[element];
+    if (entries != null) {
+      for (CacheEntry entry in entries) {
+        if (entry.match(callStructure, receiver, arguments)) {
+          if (entry.decision) {
+            FunctionDefinition function = copier.copy(entry.function);
+            ParentVisitor.setParents(function);
+            return function;
+          }
+          return NO_INLINE;
+        }
+      }
+    }
+    return ABSENT;
+  }
+}
+
+class Inliner implements Pass {
+  get passName => 'Inline calls';
+
+  final CpsFunctionCompiler functionCompiler;
+
+  final InliningCache cache = new InliningCache();
+
+  final List<StackEntry> stack = <StackEntry>[];
+
+  Inliner(this.functionCompiler);
+
+  bool isCalledOnce(Element element) {
+    return functionCompiler.compiler.typesTask.typesInferrer.isCalledOnce(
+        element);
+  }
+
+  void rewrite(FunctionDefinition node, [CallStructure callStructure]) {
+    Element function = node.element;
+
+    // Inlining in asynchronous or generator functions is disabled.  Inlining
+    // triggers a bug in the async rewriter.
+    // TODO(kmillikin): Fix the bug and eliminate this restriction if it makes
+    // sense.
+    if (function is FunctionElement &&
+        function.asyncMarker != AsyncMarker.SYNC) {
+      return;
+    }
+
+    stack.add(new StackEntry(function, callStructure));
+    new InliningVisitor(this).visit(node);
+    assert(stack.last.match(function, callStructure));
+    stack.removeLast();
+    new ShrinkingReducer().rewrite(node);
+  }
+}
+
+/// Compute an abstract size of an IR function definition.
+///
+/// The size represents the cost of inlining at a call site.
+class SizeVisitor extends TrampolineRecursiveVisitor {
+  int size = 0;
+
+  void countArgument(Reference<Primitive> argument, Parameter parameter) {
+    // If a parameter is unused and the corresponding argument has only the
+    // one use at the invocation, then inlining the call might enable
+    // elimination of the argument.  This 'pays for itself' by decreasing the
+    // cost of inlining at the call site.
+    if (argument != null &&
+        argument.definition.hasExactlyOneUse &&
+        parameter.hasNoUses) {
+      --size;
+    }
+  }
+
+  static int sizeOf(InvocationPrimitive invoke, FunctionDefinition function) {
+    SizeVisitor visitor = new SizeVisitor();
+    visitor.visit(function);
+    visitor.countArgument(invoke.receiver, function.thisParameter);
+    for (int i = 0; i < invoke.arguments.length; ++i) {
+      visitor.countArgument(invoke.arguments[i], function.parameters[i]);
+    }
+    return visitor.size;
+  }
+
+  // Inlining a function incurs a cost equal to the number of primitives and
+  // non-jump tail expressions.
+  // TODO(kmillikin): Tune the size computation and size bound.
+  processLetPrim(LetPrim node) => ++size;
+  processLetMutable(LetMutable node) => ++size;
+  processBranch(Branch node) => ++size;
+  processThrow(Throw nose) => ++size;
+  processRethrow(Rethrow node) => ++size;
+}
+
+class InliningVisitor extends TrampolineRecursiveVisitor {
+  final Inliner _inliner;
+
+  // A successful inlining attempt returns the [Primitive] that represents the
+  // result of the inlined call or null.  If the result is non-null, the body
+  // of the inlined function is available in this field.
+  CpsFragment _fragment;
+
+  InliningVisitor(this._inliner);
+
+  JavaScriptBackend get backend => _inliner.functionCompiler.backend;
+  TypeMaskSystem get typeSystem => _inliner.functionCompiler.typeSystem;
+  World get world => _inliner.functionCompiler.compiler.world;
+
+  FunctionDefinition compileToCpsIr(AstElement element) {
+    return _inliner.functionCompiler.compileToCpsIr(element);
+  }
+
+  void optimizeBeforeInlining(FunctionDefinition function) {
+    _inliner.functionCompiler.optimizeCpsBeforeInlining(function);
+  }
+
+  void applyCpsPass(Pass pass, FunctionDefinition function) {
+    return _inliner.functionCompiler.applyCpsPass(pass, function);
+  }
+
+  bool isRecursive(Element target, CallStructure callStructure) {
+    return _inliner.stack.any((StackEntry s) => s.match(target, callStructure));
+  }
+
+  @override
+  Expression traverseLetPrim(LetPrim node) {
+    // A successful inlining attempt will set the node's body to null, so it is
+    // read before visiting the primitive.
+    Expression next = node.body;
+    Primitive replacement = visit(node.primitive);
+    if (replacement != null) {
+      node.primitive.replaceWithFragment(_fragment, replacement);
+    }
+    return next;
+  }
+
+  TypeMask abstractType(Reference<Primitive> ref) {
+    return ref.definition.type ?? typeSystem.dynamicType;
+  }
+
+  /// Build the IR term for the function that adapts a call site targeting a
+  /// function that takes optional arguments not passed at the call site.
+  FunctionDefinition buildAdapter(InvokeMethod node, FunctionElement target) {
+    Parameter thisParameter = new Parameter(new ThisParameterLocal(target))
+        ..type = node.receiver.definition.type;
+    List<Parameter> parameters = new List<Parameter>.generate(
+        node.arguments.length,
+        (int index) {
+          // TODO(kmillikin): Use a hint for the parameter names.
+          return new Parameter(null)
+              ..type = node.arguments[index].definition.type;
+        });
+    Continuation returnContinuation = new Continuation.retrn();
+    CpsFragment cps = new CpsFragment();
+
+    FunctionSignature signature = target.functionSignature;
+    int requiredParameterCount = signature.requiredParameterCount;
+    if (node.callingConvention == CallingConvention.Intercepted ||
+        node.callingConvention == CallingConvention.DummyIntercepted) {
+      ++requiredParameterCount;
+    }
+    List<Primitive> arguments = new List<Primitive>.generate(
+        requiredParameterCount,
+        (int index) => parameters[index]);
+
+    int parameterIndex = requiredParameterCount;
+    CallStructure newCallStructure;
+    if (signature.optionalParametersAreNamed) {
+      List<String> incomingNames =
+          node.selector.callStructure.getOrderedNamedArguments();
+      List<String> outgoingNames = <String>[];
+      int nameIndex = 0;
+      signature.orderedOptionalParameters.forEach((ParameterElement formal) {
+        if (nameIndex < incomingNames.length &&
+            formal.name == incomingNames[nameIndex]) {
+          arguments.add(parameters[parameterIndex++]);
+          ++nameIndex;
+        } else {
+          Constant defaultValue = cps.makeConstant(
+              backend.constants.getConstantValueForVariable(formal));
+          defaultValue.type = typeSystem.getParameterType(formal);
+          arguments.add(defaultValue);
+        }
+        outgoingNames.add(formal.name);
+      });
+      newCallStructure =
+      new CallStructure(signature.parameterCount, outgoingNames);
+    } else {
+      signature.forEachOptionalParameter((ParameterElement formal) {
+        if (parameterIndex < parameters.length) {
+          arguments.add(parameters[parameterIndex++]);
+        } else {
+          Constant defaultValue = cps.makeConstant(
+              backend.constants.getConstantValueForVariable(formal));
+          defaultValue.type = typeSystem.getParameterType(formal);
+          arguments.add(defaultValue);
+        }
+      });
+      newCallStructure = new CallStructure(signature.parameterCount);
+    }
+
+    Selector newSelector =
+        new Selector(node.selector.kind, node.selector.memberName,
+            newCallStructure);
+    Primitive result = cps.invokeMethod(thisParameter, newSelector, node.mask,
+        arguments, node.callingConvention);
+    result.type = typeSystem.getInvokeReturnType(node.selector, node.mask);
+    cps.invokeContinuation(returnContinuation, <Primitive>[result]);
+    return new FunctionDefinition(target, thisParameter, parameters,
+        returnContinuation,
+        cps.root);
+  }
+
+  // Given an invocation and a known target, possibly perform inlining.
+  //
+  // An optional call structure indicates a dynamic call.  Calls that are
+  // already resolved statically have a null call structure.
+  //
+  // The [Primitive] representing the result of the inlined call is returned
+  // if the call was inlined, and the inlined function body is available in
+  // [_fragment].  If the call was not inlined, null is returned.
+  Primitive tryInlining(InvocationPrimitive invoke, FunctionElement target,
+                        CallStructure callStructure) {
+    // Quick checks: do not inline or even cache calls to targets without an
+    // AST node or targets that are asynchronous or generator functions.
+    if (!target.hasNode) return null;
+    if (target.asyncMarker != AsyncMarker.SYNC) return null;
+
+    Reference<Primitive> dartReceiver = invoke.dartReceiverReference;
+    TypeMask abstractReceiver =
+        dartReceiver == null ? null : abstractType(dartReceiver);
+    List<TypeMask> abstractArguments =
+        invoke.arguments.map(abstractType).toList();
+    var cachedResult = _inliner.cache.get(target, callStructure,
+        abstractReceiver,
+        abstractArguments);
+
+    // Negative inlining result in the cache.
+    if (cachedResult == InliningCache.NO_INLINE) return null;
+
+    // Positive inlining result in the cache.
+    if (cachedResult is FunctionDefinition) {
+      FunctionDefinition function = cachedResult;
+      _fragment = new CpsFragment(invoke.sourceInformation);
+      Primitive receiver = invoke.receiver?.definition;
+      List<Primitive> arguments =
+          invoke.arguments.map((Reference ref) => ref.definition).toList();
+      // Add a null check to the inlined function body if necessary.  The
+      // cached function body does not contain the null check.
+      if (dartReceiver != null && abstractReceiver.isNullable) {
+        Primitive check = nullReceiverGuard(
+            invoke, _fragment, dartReceiver.definition, abstractReceiver);
+        if (invoke.callingConvention == CallingConvention.Intercepted) {
+          arguments[0] = check;
+        } else {
+          receiver = check;
+        }
+      }
+      return _fragment.inlineFunction(function, receiver, arguments,
+          hint: invoke.hint);
+    }
+
+    // We have not seen this combination of target and abstract arguments
+    // before.  Make an inlining decision.
+    assert(cachedResult == InliningCache.ABSENT);
+    Primitive doNotInline() {
+      _inliner.cache.putNegative(target, callStructure, abstractReceiver,
+          abstractArguments);
+      return null;
+    }
+    if (backend.annotations.noInline(target)) return doNotInline();
+    if (isRecursive(target, callStructure)) return doNotInline();
+
+    FunctionDefinition function;
+    if (callStructure != null &&
+        target.functionSignature.parameterCount !=
+            callStructure.argumentCount) {
+      // The argument count at the call site does not match the target's
+      // formal parameter count.  Build the IR term for an adapter function
+      // body.
+      function = buildAdapter(invoke, target);
+    } else {
+      function = _inliner.functionCompiler.compileToCpsIr(target);
+      void setValue(Variable variable, Reference<Primitive> value) {
+        variable.type = value.definition.type;
+      }
+      if (invoke.receiver != null) {
+        setValue(function.thisParameter, invoke.receiver);
+      }
+      for (int i = 0; i < invoke.arguments.length; ++i) {
+        setValue(function.parameters[i], invoke.arguments[i]);
+      }
+      optimizeBeforeInlining(function);
+    }
+
+    // Inline calls in the body.
+    _inliner.rewrite(function, callStructure);
+
+    // Compute the size.
+    // TODO(kmillikin): Tune the size bound.
+    int size = SizeVisitor.sizeOf(invoke, function);
+    if (!_inliner.isCalledOnce(target) && size > 11) return doNotInline();
+
+    _inliner.cache.putPositive(target, callStructure, abstractReceiver,
+        abstractArguments, function);
+    _fragment = new CpsFragment(invoke.sourceInformation);
+    Primitive receiver = invoke.receiver?.definition;
+    List<Primitive> arguments =
+        invoke.arguments.map((Reference ref) => ref.definition).toList();
+    if (dartReceiver != null && abstractReceiver.isNullable) {
+      Primitive check =
+          _fragment.letPrim(new NullCheck(dartReceiver.definition,
+              invoke.sourceInformation));
+      check.type = abstractReceiver.nonNullable();
+      if (invoke.callingConvention == CallingConvention.Intercepted) {
+        arguments[0] = check;
+      } else {
+        receiver = check;
+      }
+    }
+    return _fragment.inlineFunction(function, receiver, arguments,
+        hint: invoke.hint);
+  }
+
+  Primitive nullReceiverGuard(InvocationPrimitive invoke,
+                              CpsFragment fragment,
+                              Primitive dartReceiver,
+                              TypeMask abstractReceiver) {
+    Selector selector = invoke is InvokeMethod ? invoke.selector : null;
+    if (typeSystem.isDefinitelyNum(abstractReceiver, allowNull: true)) {
+      Primitive condition = _fragment.letPrim(
+          new ApplyBuiltinOperator(BuiltinOperator.IsNotNumber,
+                                   <Primitive>[dartReceiver],
+                                   invoke.sourceInformation));
+      condition.type = typeSystem.boolType;
+      Primitive check = _fragment.letPrim(
+          new NullCheck.guarded(
+              condition, dartReceiver, selector, invoke.sourceInformation));
+      check.type = abstractReceiver.nonNullable();
+      return check;
+    }
+
+    Primitive check = _fragment.letPrim(
+        new NullCheck(dartReceiver, invoke.sourceInformation));
+    check.type = abstractReceiver.nonNullable();
+    return check;
+  }
+
+
+  @override
+  Primitive visitInvokeStatic(InvokeStatic node) {
+    return tryInlining(node, node.target, null);
+  }
+
+  @override
+  Primitive visitInvokeMethod(InvokeMethod node) {
+    Primitive receiver = node.dartReceiver;
+    Element element = world.locateSingleElement(node.selector, receiver.type);
+    if (element == null || element is! FunctionElement) return null;
+    if (node.selector.isGetter != element.isGetter) return null;
+    if (node.selector.isSetter != element.isSetter) return null;
+    if (node.selector.name != element.name) return null;
+
+    return tryInlining(node, element.asFunctionElement(),
+        node.selector.callStructure);
+  }
+
+  @override
+  Primitive visitInvokeMethodDirectly(InvokeMethodDirectly node) {
+    if (node.selector.isGetter != node.target.isGetter) return null;
+    if (node.selector.isSetter != node.target.isSetter) return null;
+    return tryInlining(node, node.target, null);
+  }
+
+  @override
+  Primitive visitInvokeConstructor(InvokeConstructor node) {
+    if (node.dartType is GenericType) {
+      // We cannot inline a constructor invocation containing type arguments
+      // because CreateInstance in the body does not know the type arguments.
+      // We would incorrectly instantiate a class like A instead of A<B>.
+      // TODO(kmillikin): try to fix this.
+      GenericType generic = node.dartType;
+      if (generic.typeArguments.any((DartType t) => !t.isDynamic)) return null;
+    }
+    return tryInlining(node, node.target, null);
+  }
+}
diff --git a/pkg/compiler/lib/src/cps_ir/insert_refinements.dart b/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
index 66fe170..99d1807 100644
--- a/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
+++ b/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
@@ -9,7 +9,6 @@
 import '../common/names.dart';
 import '../types/types.dart' show TypeMask;
 import 'type_mask_system.dart';
-import 'cps_fragment.dart';
 
 /// Inserts [Refinement] nodes in the IR to allow for sparse path-sensitive
 /// type analysis in the [TypePropagator] pass.
diff --git a/pkg/compiler/lib/src/cps_ir/loop_effects.dart b/pkg/compiler/lib/src/cps_ir/loop_effects.dart
index 6679336..c7680b0 100644
--- a/pkg/compiler/lib/src/cps_ir/loop_effects.dart
+++ b/pkg/compiler/lib/src/cps_ir/loop_effects.dart
@@ -2,7 +2,6 @@
 
 import 'cps_ir_nodes.dart';
 import 'loop_hierarchy.dart';
-import 'type_mask_system.dart';
 import '../universe/side_effects.dart';
 import '../elements/elements.dart';
 import '../world.dart';
diff --git a/pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart b/pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart
index 9f05e39..19b79d4 100644
--- a/pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart
+++ b/pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart
@@ -14,7 +14,6 @@
 import '../js_backend/js_backend.dart' show JavaScriptBackend;
 import '../types/types.dart' show TypeMask;
 import '../io/source_information.dart' show SourceInformation;
-import '../universe/selector.dart';
 
 /// Replaces `getInterceptor` calls with interceptor constants when possible,
 /// or with "almost constant" expressions like "x && CONST" when the input
diff --git a/pkg/compiler/lib/src/cps_ir/optimizers.dart b/pkg/compiler/lib/src/cps_ir/optimizers.dart
index ccbee6f..0ca2173 100644
--- a/pkg/compiler/lib/src/cps_ir/optimizers.dart
+++ b/pkg/compiler/lib/src/cps_ir/optimizers.dart
@@ -18,7 +18,9 @@
 export 'redundant_refinement.dart' show RedundantRefinementEliminator;
 export 'optimize_interceptors.dart' show OptimizeInterceptors;
 export 'bounds_checker.dart' show BoundsChecker;
+export 'backward_null_check_remover.dart' show BackwardNullCheckRemover;
 export 'gvn.dart' show GVN;
+export 'inline.dart' show Inliner;
 export 'eagerly_load_statics.dart' show EagerlyLoadStatics;
 export 'parent_visitor.dart' show ParentVisitor;
 
diff --git a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
index 422db14..f7365b4 100644
--- a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
+++ b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
@@ -166,6 +166,17 @@
     InvokeContinuation invoke = cont.body;
     Continuation wrappedCont = invoke.continuation.definition;
 
+    // If the invocation of wrappedCont is escaping, then all invocations of
+    // cont will be as well, after the reduction.
+    if (invoke.isEscapingTry) {
+      Reference current = cont.firstRef;
+      while (current != null) {
+        InvokeContinuation owner = current.parent;
+        owner.isEscapingTry = true;
+        current = current.next;
+      }
+    }
+
     // Replace all occurrences with the wrapped continuation.
     cont.replaceUsesWith(wrappedCont);
 
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index 86333da..3b340b2 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -38,9 +38,6 @@
 import 'cps_fragment.dart';
 import 'cps_ir_nodes.dart';
 import 'type_mask_system.dart';
-import '../closure.dart' show
-    ClosureFieldElement,
-    BoxLocal;
 
 class ConstantPropagationLattice {
   final TypeMaskSystem typeSystem;
@@ -49,11 +46,12 @@
   final AbstractConstantValue anything;
   final AbstractConstantValue nullValue;
 
-  ConstantPropagationLattice(TypeMaskSystem typeSystem,
-                             this.constantSystem,
-                             this.dartTypes)
-    : this.typeSystem = typeSystem,
-      anything = new AbstractConstantValue.nonConstant(typeSystem.dynamicType),
+  ConstantPropagationLattice(CpsFunctionCompiler functionCompiler)
+    : typeSystem = functionCompiler.typeSystem,
+      constantSystem = functionCompiler.compiler.backend.constantSystem,
+      dartTypes = functionCompiler.compiler.types,
+      anything = new AbstractConstantValue.nonConstant(
+          functionCompiler.typeSystem.dynamicType),
       nullValue = new AbstractConstantValue.constantValue(
           new NullConstantValue(), new TypeMask.empty());
 
@@ -711,25 +709,18 @@
  * by Wegman, Zadeck.
  */
 class TypePropagator extends Pass {
-  String get passName => 'Sparse constant propagation';
+  String get passName => 'Type propagation';
 
-  final dart2js.Compiler _compiler;
   final CpsFunctionCompiler _functionCompiler;
+  final Map<Variable, ConstantValue> _values= <Variable, ConstantValue>{};
   final ConstantPropagationLattice _lattice;
-  final InternalErrorFunction _internalError;
-  final Map<Variable, ConstantValue> _values = <Variable, ConstantValue>{};
-  final TypeMaskSystem _typeSystem;
 
-  TypePropagator(dart2js.Compiler compiler,
-                 TypeMaskSystem typeSystem,
-                 this._functionCompiler)
-      : _compiler = compiler,
-        _internalError = compiler.reporter.internalError,
-        _typeSystem = typeSystem,
-        _lattice = new ConstantPropagationLattice(
-            typeSystem,
-            compiler.backend.constantSystem,
-            compiler.types);
+  TypePropagator(CpsFunctionCompiler functionCompiler)
+      : _functionCompiler = functionCompiler,
+        _lattice = new ConstantPropagationLattice(functionCompiler);
+
+  dart2js.Compiler get _compiler => _functionCompiler.compiler;
+  InternalErrorFunction get _internalError => _compiler.reporter.internalError;
 
   @override
   void rewrite(FunctionDefinition root) {
@@ -1268,7 +1259,6 @@
           Primitive index = node.dartArgument(0);
           if (lattice.isDefinitelyString(receiverValue) &&
               lattice.isDefinitelyInt(getValue(index))) {
-            SourceInformation sourceInfo = node.sourceInformation;
             CpsFragment cps = new CpsFragment(node.sourceInformation);
             receiver = makeBoundsCheck(cps, receiver, index);
             ApplyBuiltinOperator get =
@@ -1368,7 +1358,6 @@
             allowNull: true)) {
       return null;
     }
-    SourceInformation sourceInfo = node.sourceInformation;
     switch (node.selector.name) {
       case 'length':
         if (!node.selector.isGetter) return null;
@@ -1416,8 +1405,6 @@
     }
     bool isFixedLength =
         lattice.isDefinitelyFixedArray(listValue, allowNull: true);
-    bool isMutable =
-        lattice.isDefinitelyMutableArray(listValue, allowNull: true);
     bool isExtendable =
         lattice.isDefinitelyExtendableArray(listValue, allowNull: true);
     SourceInformation sourceInfo = node.sourceInformation;
@@ -1673,11 +1660,11 @@
   /// Returns the first parent of [node] that is not a pure expression.
   InteriorNode getEffectiveParent(Expression node) {
     while (true) {
-      Node parent = node.parent;
+      InteriorNode parent = node.parent;
       if (parent is LetCont ||
           parent is LetPrim && parent.primitive.isSafeForReordering ||
           parent is LetPrim && parent.primitive is Refinement) {
-        node = parent;
+        node = parent as dynamic; // Make analyzer accept cross cast.
       } else {
         return parent;
       }
@@ -1786,18 +1773,6 @@
     return null;
   }
 
-  void destroyRefinementsOfDeadPrimitive(Primitive prim) {
-    while (prim.firstRef != null) {
-      Refinement refine = prim.firstRef.parent;
-      destroyRefinementsOfDeadPrimitive(refine);
-      LetPrim letPrim = refine.parent;
-      InteriorNode parent = letPrim.parent;
-      parent.body = letPrim.body;
-      letPrim.body.parent = parent;
-      prim.firstRef.unlink();
-    }
-  }
-
   /// Inlines a single-use closure if it leaves the closure object with only
   /// field accesses.  This is optimized later by [ScalarReplacer].
   CpsFragment specializeSingleUseClosureCall(InvokeMethod node) {
@@ -2604,31 +2579,38 @@
   void visit(Node node) { node.accept(this); }
 
   void visitFunctionDefinition(FunctionDefinition node) {
-    int firstActualParameter = 0;
-    if (backend.isInterceptedMethod(node.element)) {
-      if (typeSystem.methodUsesReceiverArgument(node.element)) {
+    bool isIntercepted = backend.isInterceptedMethod(node.element);
+
+    // If the abstract value of the function parameters is Nothing, use the
+    // inferred parameter type.  Otherwise (e.g., when inlining) do not
+    // change the abstract value.
+    if (node.thisParameter != null && getValue(node.thisParameter).isNothing) {
+      if (isIntercepted &&
+          typeSystem.methodUsesReceiverArgument(node.element)) {
         setValue(node.thisParameter, nonConstant(typeSystem.nonNullType));
-        setValue(node.parameters[0],
-                 nonConstant(typeSystem.getReceiverType(node.element)));
       } else {
         setValue(node.thisParameter,
-              nonConstant(typeSystem.getReceiverType(node.element)));
+            nonConstant(typeSystem.getReceiverType(node.element)));
+      }
+    }
+    if (isIntercepted && getValue(node.parameters[0]).isNothing) {
+      if (typeSystem.methodUsesReceiverArgument(node.element)) {
+        setValue(node.parameters[0],
+            nonConstant(typeSystem.getReceiverType(node.element)));
+      } else {
         setValue(node.parameters[0], nonConstant());
       }
-      firstActualParameter = 1;
-    } else if (node.thisParameter != null) {
-      setValue(node.thisParameter,
-               nonConstant(typeSystem.getReceiverType(node.element)));
     }
     bool hasParameterWithoutValue = false;
-    for (Parameter param in node.parameters.skip(firstActualParameter)) {
-      // TODO(karlklose): remove reference to the element model.
-      TypeMask type = param.hint is ParameterElement
-          ? typeSystem.getParameterType(param.hint)
-          : typeSystem.dynamicType;
-      setValue(param, lattice.fromMask(type));
-      if (type.isEmpty && !type.isNullable) {
-        hasParameterWithoutValue = true;
+    for (Parameter param in node.parameters.skip(isIntercepted ? 1 : 0)) {
+      if (getValue(param).isNothing) {
+        TypeMask type = param.hint is ParameterElement
+            ? typeSystem.getParameterType(param.hint)
+            : typeSystem.dynamicType;
+        setValue(param, lattice.fromMask(type));
+        if (type.isEmpty && !type.isNullable) {
+          hasParameterWithoutValue = true;
+        }
       }
     }
     if (!hasParameterWithoutValue) { // Don't analyze unreachable code.
diff --git a/pkg/compiler/lib/src/js/placeholder_safety.dart b/pkg/compiler/lib/src/js/placeholder_safety.dart
index 67ff563..b103489 100644
--- a/pkg/compiler/lib/src/js/placeholder_safety.dart
+++ b/pkg/compiler/lib/src/js/placeholder_safety.dart
@@ -303,6 +303,7 @@
       case 'Array':
       case 'Date':
       case 'Function':
+      case 'Math':
       case 'Number':
       case 'Object':
       case 'RegExp':
diff --git a/pkg/compiler/lib/src/js_backend/codegen/task.dart b/pkg/compiler/lib/src/js_backend/codegen/task.dart
index 78f61cb..33430be 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/task.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/task.dart
@@ -66,18 +66,22 @@
   final GenericTask treeBuilderTask;
   final GenericTask treeOptimizationTask;
 
+  Inliner inliner;
+
   CpsFunctionCompiler(Compiler compiler, JavaScriptBackend backend,
                       SourceInformationStrategy sourceInformationFactory)
       : fallbackCompiler =
             new ssa.SsaFunctionCompiler(backend, sourceInformationFactory),
         cpsBuilderTask = new IrBuilderTask(compiler, sourceInformationFactory),
-        this.sourceInformationFactory = sourceInformationFactory,
+        sourceInformationFactory = sourceInformationFactory,
         constantSystem = backend.constantSystem,
         compiler = compiler,
         glue = new Glue(compiler),
         cpsOptimizationTask = new GenericTask('CPS optimization', compiler),
         treeBuilderTask = new GenericTask('Tree builder', compiler),
-        treeOptimizationTask = new GenericTask('Tree optimization', compiler);
+      treeOptimizationTask = new GenericTask('Tree optimization', compiler) {
+    inliner = new Inliner(this);
+  }
 
   String get name => 'CPS Ir pipeline';
 
@@ -87,9 +91,9 @@
 
   /// Generates JavaScript code for `work.element`.
   js.Fun compile(CodegenWorkItem work) {
+    if (typeSystem == null) typeSystem = new TypeMaskSystem(compiler);
     AstElement element = work.element;
     return reporter.withCurrentElement(element, () {
-      typeSystem = new TypeMaskSystem(compiler);
       try {
         // TODO(karlklose): remove this fallback when we do not need it for
         // testing anymore.
@@ -102,7 +106,9 @@
           tracer.traceCompilation(element.name, null);
         }
         cps.FunctionDefinition cpsFunction = compileToCpsIr(element);
-        cpsFunction = optimizeCpsIr(cpsFunction);
+        optimizeCpsBeforeInlining(cpsFunction);
+        applyCpsPass(inliner, cpsFunction);
+        optimizeCpsAfterInlining(cpsFunction);
         cpsIntegrityChecker = null;
         tree_ir.FunctionDefinition treeFunction = compileToTreeIr(cpsFunction);
         treeFunction = optimizeTreeIr(treeFunction);
@@ -200,14 +206,19 @@
     return true; // So this can be used from assert().
   }
 
-  cps.FunctionDefinition optimizeCpsIr(cps.FunctionDefinition cpsFunction) {
+  void optimizeCpsBeforeInlining(cps.FunctionDefinition cpsFunction) {
     cpsOptimizationTask.measure(() {
       applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
       applyCpsPass(new RedundantPhiEliminator(), cpsFunction);
       applyCpsPass(new InsertRefinements(typeSystem), cpsFunction);
-      applyCpsPass(new TypePropagator(compiler, typeSystem, this), cpsFunction);
+      applyCpsPass(new TypePropagator(this), cpsFunction);
       applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
       applyCpsPass(new ShrinkingReducer(), cpsFunction);
+    });
+  }
+
+  void optimizeCpsAfterInlining(cps.FunctionDefinition cpsFunction) {
+    cpsOptimizationTask.measure(() {
       applyCpsPass(new RedundantRefinementEliminator(typeSystem), cpsFunction);
       applyCpsPass(new EagerlyLoadStatics(), cpsFunction);
       applyCpsPass(new GVN(compiler, typeSystem), cpsFunction);
@@ -220,9 +231,9 @@
       applyCpsPass(new RedundantPhiEliminator(), cpsFunction);
       applyCpsPass(new ShrinkingReducer(), cpsFunction);
       applyCpsPass(new OptimizeInterceptors(backend), cpsFunction);
+      applyCpsPass(new BackwardNullCheckRemover(typeSystem), cpsFunction);
       applyCpsPass(new ShrinkingReducer(), cpsFunction);
     });
-    return cpsFunction;
   }
 
   tree_ir.FunctionDefinition compileToTreeIr(cps.FunctionDefinition cpsNode) {
diff --git a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
index 57b54fd..11a80a4 100644
--- a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
@@ -355,7 +355,7 @@
   static const String DART_STRING_CLASS = "ConstantStringMap";
   static const String DART_PROTO_CLASS = "ConstantProtoMap";
   static const String DART_GENERAL_CLASS = "GeneralConstantMap";
-  static const String LENGTH_NAME = "length";
+  static const String LENGTH_NAME = "_length";
   static const String JS_OBJECT_NAME = "_jsObject";
   static const String KEYS_NAME = "_keys";
   static const String PROTO_VALUE = "_protoValue";
diff --git a/pkg/compiler/lib/src/js_backend/frequency_namer.dart b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
index 6fa2ccf..fa3b79b 100644
--- a/pkg/compiler/lib/src/js_backend/frequency_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
@@ -21,6 +21,9 @@
   final String setterPrefix = 's';
   final String callPrefix = ''; // this will create function names $<n>
 
+  jsAst.Name get staticsPropertyName =>
+      _staticsPropertyName ??= getFreshName(instanceScope, 'static');
+
   FrequencyBasedNamer(Compiler compiler) : super(compiler) {
     fieldRegistry = new _FieldNamingRegistry(this);
   }
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 4cd691e..bd55710 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -356,6 +356,11 @@
   jsAst.Name _literalSetterPrefix;
   jsAst.Name _literalLazyGetterPrefix;
 
+  jsAst.Name _staticsPropertyName;
+
+  jsAst.Name get staticsPropertyName =>
+      _staticsPropertyName ??= new StringBackedName('static');
+
   // Name of property in a class description for the native dispatch metadata.
   final String nativeSpecProperty = '%';
 
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
index f625c8a..06aa189 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
@@ -328,8 +328,9 @@
     }
 
     if (!statics.isEmpty) {
-      classBuilder.addPropertyByName('static',
-                                     new jsAst.ObjectInitializer(statics));
+      classBuilder.addProperty(
+          namer.staticsPropertyName, // 'static' or its minified name.
+          new jsAst.ObjectInitializer(statics, isOneLiner: false));
     }
 
     // TODO(ahe): This method (generateClass) should return a jsAst.Expression.
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
index 9ad63ab..ecd8a4b 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
@@ -102,6 +102,8 @@
      'mangledNames': mangledNamesAccess,
      'mangledGlobalNames': mangledGlobalNamesAccess,
      'statics': staticsAccess,
+     'staticsPropertyName': namer.staticsPropertyName,
+     'staticsPropertyNameString': js.quoteName(namer.staticsPropertyName),
      'typeInformation': typeInformationAccess,
      'globalFunctions': globalFunctionsAccess,
      'enabledInvokeOn': compiler.enabledInvokeOn,
@@ -526,10 +528,10 @@
       for (var i = 0; i < properties.length; i++) {
         var property = properties[i];
         var firstChar = property.charCodeAt(0);
-        if (property === "static") {
-          processStatics(#statics[cls] = descriptor.static,
+        if (property === #staticsPropertyNameString) {
+          processStatics(#statics[cls] = descriptor.#staticsPropertyName,
                          processedClasses);
-          delete descriptor.static;
+          delete descriptor.#staticsPropertyName;
         } else if (firstChar === 43) { // 43 is "+".
           mangledNames[previousProperty] = property.substring(1);
           var flag = descriptor[property];
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
index f38dcf3..32b508f 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
@@ -239,11 +239,16 @@
   /// If the given expression always returns the value of one of its
   /// subexpressions, and that subexpression is a variable use, returns that
   /// variable. Otherwise `null`.
-  Variable getRightHand(Expression e) {
+  Variable getRightHandVariable(Expression e) {
     Expression value = getValueSubexpression(e);
     return value is VariableUse ? value.variable : null;
   }
 
+  Constant getRightHandConstant(Expression e) {
+    Expression value = getValueSubexpression(e);
+    return value is Constant ? value : null;
+  }
+
   /// True if the given expression (taken from [constantEnvironment]) uses a
   /// variable that might have been reassigned since [node] was evaluated.
   bool hasUnsafeVariableUse(Expression node) {
@@ -322,7 +327,7 @@
       //
       //     { E.foo = x; bar(x) } ==> bar(E.foo = x)
       //
-      if (getRightHand(binding) == node.variable) {
+      if (getRightHandVariable(binding) == node.variable) {
         environment.removeLast();
         --node.variable.readCount;
         return visitExpression(binding);
@@ -585,8 +590,15 @@
     return node;
   }
 
+  bool isNullConstant(Expression node) {
+    return node is Constant && node.value.isNull;
+  }
+
   Statement visitReturn(Return node) {
-    node.value = visitExpression(node.value);
+    if (!isNullConstant(node.value)) {
+      // Do not chain assignments into a null return.
+      node.value = visitExpression(node.value);
+    }
     return node;
   }
 
@@ -709,6 +721,12 @@
   }
 
   Expression visitConstant(Constant node) {
+    if (!environment.isEmpty) {
+      Constant constant = getRightHandConstant(environment.last);
+      if (constant != null && constant.value == node.value) {
+        return visitExpression(environment.removeLast());
+      }
+    }
     return node;
   }
 
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
index c36a394..6c4297e 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
@@ -53,6 +53,7 @@
       <cps_ir.Primitive, Variable>{};
   final Map<cps_ir.MutableVariable, Variable> mutable2variable =
       <cps_ir.MutableVariable, Variable>{};
+  final Set<cps_ir.Constant> inlinedConstants = new Set<cps_ir.Constant>();
 
   // Continuations with more than one use are replaced with Tree labels.  This
   // is the mapping from continuations to labels.
@@ -109,6 +110,9 @@
   /// returned expression must be used in the tree.
   Expression getVariableUse(cps_ir.Reference<cps_ir.Primitive> reference) {
     cps_ir.Primitive prim = reference.definition.effectiveDefinition;
+    if (prim is cps_ir.Constant && inlinedConstants.contains(prim)) {
+      return new Constant(prim.value);
+    }
     if (thisParameter != null && prim == thisParameter) {
       return new This();
     }
@@ -279,6 +283,53 @@
     return prim.accept(this);
   }
 
+  /************************ CONSTANT COPYING *****************************/
+
+  /// Estimate of the number of characters needed to emit a use of the given
+  /// constant.
+  int constantSize(PrimitiveConstantValue value) {
+    // TODO(asgerf): We could interface with the emitter to get the exact size.
+    if (value is StringConstantValue) {
+      // Account for the quotes, but ignore the cost of encoding non-ASCII
+      // characters to avoid traversing the string and depending on encoding.
+      return value.length + 2;
+    } else if (value is BoolConstantValue) {
+      return 2; // Printed as !0 and !1 when minified
+    } else {
+      // TODO(asgerf): Get the exact length of numbers using '1e10' notation.
+      return '${value.primitiveValue}'.length;
+    }
+  }
+
+  /// The number of uses [prim] has, or `-1` if it is used in a phi assignment.
+  int countNonPhiUses(cps_ir.Primitive prim) {
+    int count = 0;
+    for (cps_ir.Reference ref = prim.firstRef; ref != null; ref = ref.next) {
+      cps_ir.Node use = ref.parent;
+      if (use is cps_ir.InvokeContinuation) {
+        return -1;
+      }
+      count++;
+    }
+    return count;
+  }
+
+  /// True if the given [constant] should be copied to every use site.
+  bool shouldCopyToUses(cps_ir.Constant constant) {
+    if (!constant.value.isPrimitive) return false;
+    if (constant.hasAtMostOneUse) return true;
+    int uses = countNonPhiUses(constant);
+    if (uses == -1) return false; // Copying might prevent elimination of a phi.
+    int size = constantSize(constant.value);
+    // Compare the expected code size output of copying vs sharing.
+    const int USE = 2; // Minified locals usually have length 2.
+    const int ASSIGN = USE + 2; // Variable and '=' and ';'
+    const int BIAS = 2; // Artificial bias to slightly favor copying.
+    int costOfSharing = USE * uses + size + ASSIGN + BIAS;
+    int costOfCopying = size * uses;
+    return costOfCopying <= costOfSharing;
+  }
+
   /************************ INTERIOR EXPRESSIONS  ************************/
   //
   // Visit methods for interior expressions must return a function:
@@ -287,6 +338,10 @@
   //
 
   NodeCallback visitLetPrim(cps_ir.LetPrim node) {
+    if (node.primitive is cps_ir.Constant && shouldCopyToUses(node.primitive)) {
+      inlinedConstants.add(node.primitive);
+      return (Statement next) => next;
+    }
     Variable variable = getVariable(node.primitive);
     var value = translatePrimitive(node.primitive);
     if (value is Expression) {
diff --git a/pkg/js_ast/lib/src/printer.dart b/pkg/js_ast/lib/src/printer.dart
index d5c1d9b..edd4189 100644
--- a/pkg/js_ast/lib/src/printer.dart
+++ b/pkg/js_ast/lib/src/printer.dart
@@ -1069,22 +1069,31 @@
     // Print all the properties on one line until we see a function-valued
     // property.  Ideally, we would use a proper pretty-printer to make the
     // decision based on layout.
+    bool exitOneLinerMode(Expression value) {
+      return
+          value is Fun ||
+          value is ArrayInitializer && value.elements.any((e) => e is Fun);
+    }
+
+    bool isOneLiner = node.isOneLiner || shouldCompressOutput;
     List<Property> properties = node.properties;
     out("{");
     indentMore();
     for (int i = 0; i < properties.length; i++) {
+      Node value = properties[i].value;
+      if (isOneLiner && exitOneLinerMode(value)) isOneLiner = false;
       if (i != 0) {
         out(",");
-        if (node.isOneLiner) spaceOut();
+        if (isOneLiner) spaceOut();
       }
-      if (!node.isOneLiner) {
+      if (!isOneLiner) {
         forceLine();
         indent();
       }
       visit(properties[i]);
     }
     indentLess();
-    if (!node.isOneLiner && !properties.isEmpty) {
+    if (!isOneLiner && !properties.isEmpty) {
       lineOut();
       indent();
     }
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 0d48659..c821f54 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -65,6 +65,7 @@
 analyzer/test/src/context/cache_test: Pass, Slow # Issue 21628
 analyzer/test/src/context/context_test: Pass, Timeout # dartbug.com/23658
 analyzer/test/src/dart/element/element_test: Pass, Slow # Issue 21628
+analyzer/test/src/summary/resynthesize_test: Pass, Slow
 analyzer/test/src/summary/summary_test: Pass, Slow # Issue 21628
 analyzer/test/src/task/dart_test: Pass, Slow # Issue 21628
 analyzer/test/src/task/dart_work_manager_test: Pass, Slow # Issue 21628
@@ -164,6 +165,11 @@
 [ $use_repository_packages ]
 analyzer/test/*: PubGetError
 
+[ $compiler == dart2js && $cps_ir && $host_checked == false ]
+analyzer/test/dart/element/element_test: Pass, Slow # Times out due to inlining, but see issue 24485
+analyzer/test/src/summary/resynthesize_test: Pass, Slow # Times out due to inlining, but see issue 24485
+analyzer/test/src/task/strong_mode_test: Pass, Slow # Times out due to inlining, but see issue 24485
+
 [ $compiler == dart2js && $cps_ir && $host_checked ]
 analyzer/test/enum_test: Crash # Issue 24485
 analyzer/test/generated/all_the_rest_test: Crash # Issue 24485
diff --git a/runtime/bin/embedded_dart_io.cc b/runtime/bin/embedded_dart_io.cc
index 1b3f40b..9e38f02 100644
--- a/runtime/bin/embedded_dart_io.cc
+++ b/runtime/bin/embedded_dart_io.cc
@@ -5,6 +5,7 @@
 #include "bin/embedded_dart_io.h"
 
 #include "bin/eventhandler.h"
+#include "bin/utils.h"
 #include "bin/thread.h"
 
 namespace dart {
@@ -13,6 +14,7 @@
 void BootstrapDartIo() {
   // Bootstrap 'dart:io' event handler.
   Thread::InitOnce();
+  TimerUtils::InitOnce();
   EventHandler::Start();
 }
 
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 773c0af..93611a4 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -19,6 +19,7 @@
 #include "bin/file.h"
 #include "bin/log.h"
 #include "bin/thread.h"
+#include "bin/utils.h"
 #include "bin/vmservice_impl.h"
 
 #include "platform/globals.h"
@@ -1017,6 +1018,7 @@
   Thread::InitOnce();
   DartUtils::SetOriginalWorkingDirectory();
   // Start event handler.
+  TimerUtils::InitOnce();
   EventHandler::Start();
 
   vm_options.AddArgument("--load_deferred_eagerly");
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 7fc19c4..71a6b65 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -71,6 +71,12 @@
 static bool has_run_precompiled_snapshot = false;
 
 
+// Value of the --gen/run_precompiled_snapshot flag.
+// (This pointer points into an argv buffer and does not need to be
+// free'd.)
+static const char* precompiled_snapshot_directory = NULL;
+
+
 // Global flag that is used to indicate that we want to compile everything in
 // the same way as precompilation before main, then continue running in the
 // same process.
@@ -109,7 +115,7 @@
 
 // Global flag that is used to indicate that the VM should do a clean
 // shutdown.
-static bool do_vm_shutdown = false;
+static bool do_vm_shutdown = true;
 
 static void ErrorExit(int exit_code, const char* format, ...) {
   va_list arguments;
@@ -304,16 +310,18 @@
 static bool ProcessGenPrecompiledSnapshotOption(
     const char* arg,
     CommandLineOptions* vm_options) {
-  ASSERT(arg != NULL);
-  if (*arg != '\0') {
-    return false;
-  }
   // Ensure that we are not already running using a full snapshot.
   if (isolate_snapshot_buffer != NULL) {
     Log::PrintErr("Precompiled snapshots must be generated with"
                   " dart_no_snapshot.\n");
     return false;
   }
+  ASSERT(arg != NULL);
+  if ((arg[0] == '=') || (arg[0] == ':')) {
+    precompiled_snapshot_directory = &arg[1];
+  } else {
+    precompiled_snapshot_directory = arg;
+  }
   has_gen_precompiled_snapshot = true;
   vm_options->AddArgument("--precompilation");
   return true;
@@ -324,8 +332,10 @@
     const char* arg,
     CommandLineOptions* vm_options) {
   ASSERT(arg != NULL);
-  if (*arg != '\0') {
-    return false;
+  precompiled_snapshot_directory = arg;
+  if ((precompiled_snapshot_directory[0] == '=') ||
+      (precompiled_snapshot_directory[0] == ':')) {
+    precompiled_snapshot_directory = &precompiled_snapshot_directory[1];
   }
   has_run_precompiled_snapshot = true;
   vm_options->AddArgument("--precompilation");
@@ -1009,34 +1019,67 @@
 }
 
 
-static void WriteSnapshotFile(const char* filename,
-                              const uint8_t* buffer,
-                              const intptr_t size) {
-  File* file = File::Open(filename, File::kWriteTruncate);
+static void WritePrecompiledSnapshotFile(const char* filename,
+                                         const uint8_t* buffer,
+                                         const intptr_t size) {
+  char* concat = NULL;
+  const char* qualified_filename;
+  if (strlen(precompiled_snapshot_directory) > 0) {
+    intptr_t len = snprintf(NULL, 0, "%s/%s",
+                            precompiled_snapshot_directory, filename);
+    concat = new char[len + 1];
+    snprintf(concat, len + 1, "%s/%s",
+             precompiled_snapshot_directory, filename);
+    qualified_filename = concat;
+  } else {
+    qualified_filename = filename;
+  }
+
+  File* file = File::Open(qualified_filename, File::kWriteTruncate);
   ASSERT(file != NULL);
   if (!file->WriteFully(buffer, size)) {
     ErrorExit(kErrorExitCode,
               "Unable to open file %s for writing snapshot\n",
-              filename);
+              qualified_filename);
   }
   delete file;
+  if (concat != NULL) {
+    delete concat;
+  }
 }
 
 
-static void ReadSnapshotFile(const char* filename,
-                             const uint8_t** buffer) {
-  void* file = DartUtils::OpenFile(filename, false);
+static void ReadPrecompiledSnapshotFile(const char* filename,
+                                        const uint8_t** buffer) {
+  char* concat = NULL;
+  const char* qualified_filename;
+  if (strlen(precompiled_snapshot_directory) > 0) {
+    intptr_t len = snprintf(NULL, 0, "%s/%s",
+                            precompiled_snapshot_directory, filename);
+    concat = new char[len + 1];
+    snprintf(concat, len + 1, "%s/%s",
+             precompiled_snapshot_directory, filename);
+    qualified_filename = concat;
+  } else {
+    qualified_filename = filename;
+  }
+
+  void* file = DartUtils::OpenFile(qualified_filename, false);
   if (file == NULL) {
     ErrorExit(kErrorExitCode,
-              "Error: Unable to open file %s for reading snapshot\n", filename);
+              "Error: Unable to open file %s for reading snapshot\n",
+              qualified_filename);
   }
   intptr_t len = -1;
   DartUtils::ReadFile(buffer, &len, file);
   if (*buffer == NULL || len == -1) {
     ErrorExit(kErrorExitCode,
-              "Error: Unable to read snapshot file %s\n", filename);
+              "Error: Unable to read snapshot file %s\n", qualified_filename);
   }
   DartUtils::CloseFile(file);
+  if (concat != NULL) {
+    delete concat;
+  }
 }
 
 
@@ -1190,7 +1233,6 @@
         { "dart:io", "_ProcessStartStatus", "set:_errorMessage" },
         { "dart:io", "_SecureFilterImpl", "get:ENCRYPTED_SIZE" },
         { "dart:io", "_SecureFilterImpl", "get:SIZE" },
-        { "dart:vmservice_io", "::", "_addResource" },
         { "dart:vmservice_io", "::", "main" },
         { "dart:vmservice_io", "::", "boot" },
         { NULL, NULL, NULL }  // Must be terminated with NULL entries.
@@ -1215,15 +1257,15 @@
                                               &instructions_buffer,
                                               &instructions_size);
       CHECK_RESULT(result);
-      WriteSnapshotFile(kPrecompiledVmIsolateName,
-                        vm_isolate_buffer,
-                        vm_isolate_size);
-      WriteSnapshotFile(kPrecompiledIsolateName,
-                        isolate_buffer,
-                        isolate_size);
-      WriteSnapshotFile(kPrecompiledInstructionsName,
-                        instructions_buffer,
-                        instructions_size);
+      WritePrecompiledSnapshotFile(kPrecompiledVmIsolateName,
+                                   vm_isolate_buffer,
+                                   vm_isolate_size);
+      WritePrecompiledSnapshotFile(kPrecompiledIsolateName,
+                                   isolate_buffer,
+                                   isolate_size);
+      WritePrecompiledSnapshotFile(kPrecompiledInstructionsName,
+                                   instructions_buffer,
+                                   instructions_size);
     } else {
       if (has_compile_all) {
         result = Dart_CompileAll();
@@ -1420,14 +1462,17 @@
   Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
 
   // Start event handler.
+  TimerUtils::InitOnce();
   EventHandler::Start();
 
   const uint8_t* instructions_snapshot = NULL;
   if (has_run_precompiled_snapshot) {
     instructions_snapshot = reinterpret_cast<const uint8_t*>(
         LoadLibrarySymbol(kPrecompiledLibraryName, kPrecompiledSymbolName));
-    ReadSnapshotFile(kPrecompiledVmIsolateName, &vm_isolate_snapshot_buffer);
-    ReadSnapshotFile(kPrecompiledIsolateName, &isolate_snapshot_buffer);
+    ReadPrecompiledSnapshotFile(kPrecompiledVmIsolateName,
+                                &vm_isolate_snapshot_buffer);
+    ReadPrecompiledSnapshotFile(kPrecompiledIsolateName,
+                                &isolate_snapshot_buffer);
   }
 
   // Initialize the Dart VM.
diff --git a/runtime/bin/platform.cc b/runtime/bin/platform.cc
index ec75ee9..f2f16be 100644
--- a/runtime/bin/platform.cc
+++ b/runtime/bin/platform.cc
@@ -45,12 +45,28 @@
 
 void FUNCTION_NAME(Platform_ExecutableName)(Dart_NativeArguments args) {
   ASSERT(Platform::GetExecutableName() != NULL);
+  if (Dart_IsRunningPrecompiledCode()) {
+    // This is a work-around to be able to use most of the existing test suite
+    // for precompilation. Many tests do something like Process.run(
+    // Platform.executable, some_other_script.dart). But with precompilation
+    // the script is already fixed, so the spawned process runs the same script
+    // again and we have a fork-bomb.
+    Dart_ThrowException(Dart_NewStringFromCString(
+        "Platform.executable not supported under precompilation"));
+    UNREACHABLE();
+  }
   Dart_SetReturnValue(
       args, Dart_NewStringFromCString(Platform::GetExecutableName()));
 }
 
 
 void FUNCTION_NAME(Platform_ResolvedExecutableName)(Dart_NativeArguments args) {
+  if (Dart_IsRunningPrecompiledCode()) {
+    Dart_ThrowException(Dart_NewStringFromCString(
+        "Platform.resolvedExecutable not supported under precompilation"));
+    UNREACHABLE();
+  }
+
   if (Platform::GetResolvedExecutableName() != NULL) {
     Dart_SetReturnValue(
         args, Dart_NewStringFromCString(Platform::GetResolvedExecutableName()));
diff --git a/runtime/bin/utils.h b/runtime/bin/utils.h
index a1714c2..cbc2bab 100644
--- a/runtime/bin/utils.h
+++ b/runtime/bin/utils.h
@@ -98,6 +98,7 @@
 
 class TimerUtils {
  public:
+  static void InitOnce();
   static int64_t GetCurrentMonotonicMicros();
   static int64_t GetCurrentMonotonicMillis();
   static void Sleep(int64_t millis);
diff --git a/runtime/bin/utils_android.cc b/runtime/bin/utils_android.cc
index db9eb75..e36ac11 100644
--- a/runtime/bin/utils_android.cc
+++ b/runtime/bin/utils_android.cc
@@ -71,6 +71,9 @@
   return false;
 }
 
+void TimerUtils::InitOnce() {
+}
+
 int64_t TimerUtils::GetCurrentMonotonicMillis() {
   return GetCurrentMonotonicMicros() / 1000;
 }
diff --git a/runtime/bin/utils_linux.cc b/runtime/bin/utils_linux.cc
index 419df95..ea6ef8c 100644
--- a/runtime/bin/utils_linux.cc
+++ b/runtime/bin/utils_linux.cc
@@ -69,6 +69,9 @@
   return false;
 }
 
+void TimerUtils::InitOnce() {
+}
+
 int64_t TimerUtils::GetCurrentMonotonicMillis() {
   return GetCurrentMonotonicMicros() / 1000;
 }
diff --git a/runtime/bin/utils_macos.cc b/runtime/bin/utils_macos.cc
index 80cd038..5ac414f 100644
--- a/runtime/bin/utils_macos.cc
+++ b/runtime/bin/utils_macos.cc
@@ -74,6 +74,13 @@
   return false;
 }
 
+static mach_timebase_info_data_t timebase_info;
+
+void TimerUtils::InitOnce() {
+  kern_return_t kr = mach_timebase_info(&timebase_info);
+  ASSERT(KERN_SUCCESS == kr);
+}
+
 int64_t TimerUtils::GetCurrentMonotonicMillis() {
   return GetCurrentMonotonicMicros() / 1000;
 }
@@ -94,17 +101,7 @@
   origin += boottime.tv_usec;
   return now - origin;
 #else
-  static mach_timebase_info_data_t timebase_info;
-  if (timebase_info.denom == 0) {
-    // Zero-initialization of statics guarantees that denom will be 0 before
-    // calling mach_timebase_info.  mach_timebase_info will never set denom to
-    // 0 as that would be invalid, so the zero-check can be used to determine
-    // whether mach_timebase_info has already been called.  This is
-    // recommended by Apple's QA1398.
-    kern_return_t kr = mach_timebase_info(&timebase_info);
-    ASSERT(KERN_SUCCESS == kr);
-  }
-
+  ASSERT(timebase_info.denom != 0);
   // timebase_info converts absolute time tick units into nanoseconds.  Convert
   // to microseconds.
   int64_t result = mach_absolute_time() / kNanosecondsPerMicrosecond;
diff --git a/runtime/bin/utils_win.cc b/runtime/bin/utils_win.cc
index ae12f4b..116ae56 100644
--- a/runtime/bin/utils_win.cc
+++ b/runtime/bin/utils_win.cc
@@ -187,12 +187,21 @@
   return (time.t_ - kTimeEpoc) / kTimeScaler;
 }
 
+static int64_t qpc_ticks_per_second = 0;
+
+void TimerUtils::InitOnce() {
+  LARGE_INTEGER ticks_per_sec;
+  if (!QueryPerformanceFrequency(&ticks_per_sec)) {
+    qpc_ticks_per_second = 0;
+  } else {
+    qpc_ticks_per_second = static_cast<int64_t>(ticks_per_sec.QuadPart);
+  }
+}
+
 int64_t TimerUtils::GetCurrentMonotonicMillis() {
   return GetCurrentMonotonicMicros() / 1000;
 }
 
-static int64_t qpc_ticks_per_second = 0;
-
 int64_t TimerUtils::GetCurrentMonotonicMicros() {
   if (qpc_ticks_per_second == 0) {
     // QueryPerformanceCounter not supported, fallback.
diff --git a/runtime/bin/vmservice_dartium.cc b/runtime/bin/vmservice_dartium.cc
index aa5a62a..0ff30a7 100644
--- a/runtime/bin/vmservice_dartium.cc
+++ b/runtime/bin/vmservice_dartium.cc
@@ -9,6 +9,7 @@
 #include "bin/eventhandler.h"
 #include "bin/platform.h"
 #include "bin/thread.h"
+#include "bin/utils.h"
 #include "bin/vmservice_impl.h"
 #include "zlib/zlib.h"
 
@@ -34,6 +35,7 @@
   }
   DartUtils::SetOriginalWorkingDirectory();
   Thread::InitOnce();
+  TimerUtils::InitOnce();
   EventHandler::Start();
 }
 
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index f46a66a..2715abc 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -89,14 +89,6 @@
 };
 
 
-void TriggerResourceLoad(Dart_NativeArguments args) {
-  Dart_Handle library = Dart_RootLibrary();
-  ASSERT(!Dart_IsError(library));
-  Dart_Handle result = VmService::LoadResources(library);
-  ASSERT(!Dart_IsError(result));
-}
-
-
 void NotifyServerState(Dart_NativeArguments args) {
   Dart_EnterScope();
   const char* ip_chars;
@@ -131,7 +123,6 @@
 
 
 static VmServiceIONativeEntry _VmServiceIONativeEntries[] = {
-  {"VMServiceIO_TriggerResourceLoad", 0, TriggerResourceLoad},
   {"VMServiceIO_NotifyServerState", 2, NotifyServerState},
 };
 
@@ -327,63 +318,6 @@
 }
 
 
-Dart_Handle VmService::LoadResource(Dart_Handle library,
-                                    const char* resource_name) {
-  // Prepare for invoke call.
-  Dart_Handle name = Dart_NewStringFromCString(resource_name);
-  RETURN_ERROR_HANDLE(name);
-  const char* data_buffer = NULL;
-  int data_buffer_length = Resources::ResourceLookup(resource_name,
-                                                     &data_buffer);
-  if (data_buffer_length == Resources::kNoSuchInstance) {
-    printf("Could not find %s %s\n", resource_name, resource_name);
-  }
-  ASSERT(data_buffer_length != Resources::kNoSuchInstance);
-  Dart_Handle data_list = Dart_NewTypedData(Dart_TypedData_kUint8,
-                                            data_buffer_length);
-  RETURN_ERROR_HANDLE(data_list);
-  Dart_TypedData_Type type = Dart_TypedData_kInvalid;
-  void* data_list_buffer = NULL;
-  intptr_t data_list_buffer_length = 0;
-  Dart_Handle result = Dart_TypedDataAcquireData(data_list, &type,
-                                                 &data_list_buffer,
-                                                 &data_list_buffer_length);
-  RETURN_ERROR_HANDLE(result);
-  ASSERT(data_buffer_length == data_list_buffer_length);
-  ASSERT(data_list_buffer != NULL);
-  ASSERT(type == Dart_TypedData_kUint8);
-  memmove(data_list_buffer, &data_buffer[0], data_buffer_length);
-  result = Dart_TypedDataReleaseData(data_list);
-  RETURN_ERROR_HANDLE(result);
-
-  // Make invoke call.
-  const intptr_t kNumArgs = 3;
-  Dart_Handle compressed = Dart_True();
-  Dart_Handle args[kNumArgs] = { name, data_list, compressed };
-  result = Dart_Invoke(library, Dart_NewStringFromCString("_addResource"),
-                       kNumArgs, args);
-  return result;
-}
-
-
-Dart_Handle VmService::LoadResources(Dart_Handle library) {
-  Dart_Handle result = Dart_Null();
-  intptr_t prefixLen = strlen(kLibrarySourceNamePrefix);
-  for (intptr_t i = 0; Resources::Path(i) != NULL; i++) {
-    const char* path = Resources::Path(i);
-    // If it doesn't begin with kLibrarySourceNamePrefix it is a frontend
-    // resource.
-    if (strncmp(path, kLibrarySourceNamePrefix, prefixLen) != 0) {
-      result = LoadResource(library, path);
-      if (Dart_IsError(result)) {
-        break;
-      }
-    }
-  }
-  return result;
-}
-
-
 Dart_Handle VmService::LibraryTagHandler(Dart_LibraryTag tag,
                                          Dart_Handle library,
                                          Dart_Handle url) {
diff --git a/runtime/bin/vmservice_impl.h b/runtime/bin/vmservice_impl.h
index 590aece..1780013 100644
--- a/runtime/bin/vmservice_impl.h
+++ b/runtime/bin/vmservice_impl.h
@@ -35,7 +35,6 @@
 
  private:
   static const intptr_t kServerIpStringBufferSize = 256;
-  friend void TriggerResourceLoad(Dart_NativeArguments args);
   friend void NotifyServerState(Dart_NativeArguments args);
 
   static void SetServerIPAndPort(const char* ip, intptr_t port);
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 227c84f..222ef79 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -2819,4 +2819,7 @@
     uint8_t** instructions_snapshot_buffer,
     intptr_t* instructions_snapshot_size);
 
+
+DART_EXPORT bool Dart_IsRunningPrecompiledCode();
+
 #endif  /* INCLUDE_DART_API_H_ */  /* NOLINT */
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index d8693a1..72fcc3e 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -155,17 +155,14 @@
 }
 
 
-DEFINE_NATIVE_ENTRY(Object_instanceOf, 5) {
+DEFINE_NATIVE_ENTRY(Object_instanceOf, 4) {
   const Instance& instance =
       Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
-  // Instantiator at position 1 is not used. It is passed along so that the call
-  // can be easily converted to an optimized implementation. Instantiator is
-  // used to populate the subtype cache.
   const TypeArguments& instantiator_type_arguments =
-      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(2));
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(1));
   const AbstractType& type =
-      AbstractType::CheckedHandle(zone, arguments->NativeArgAt(3));
-  const Bool& negate = Bool::CheckedHandle(zone, arguments->NativeArgAt(4));
+      AbstractType::CheckedHandle(zone, arguments->NativeArgAt(2));
+  const Bool& negate = Bool::CheckedHandle(zone, arguments->NativeArgAt(3));
   ASSERT(type.IsFinalized());
   ASSERT(!type.IsMalformed());
   ASSERT(!type.IsMalbounded());
@@ -267,15 +264,12 @@
 }
 
 
-DEFINE_NATIVE_ENTRY(Object_as, 4) {
+DEFINE_NATIVE_ENTRY(Object_as, 3) {
   const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0));
-  // Instantiator at position 1 is not used. It is passed along so that the call
-  // can be easily converted to an optimized implementation. Instantiator is
-  // used to populate the subtype cache.
   const TypeArguments& instantiator_type_arguments =
-      TypeArguments::CheckedHandle(arguments->NativeArgAt(2));
+      TypeArguments::CheckedHandle(arguments->NativeArgAt(1));
   const AbstractType& type =
-      AbstractType::CheckedHandle(arguments->NativeArgAt(3));
+      AbstractType::CheckedHandle(arguments->NativeArgAt(2));
   ASSERT(type.IsFinalized());
   ASSERT(!type.IsMalformed());
   ASSERT(!type.IsMalbounded());
diff --git a/runtime/lib/object_patch.dart b/runtime/lib/object_patch.dart
index be42a57..b61b6a6 100644
--- a/runtime/lib/object_patch.dart
+++ b/runtime/lib/object_patch.dart
@@ -53,10 +53,7 @@
 
   // Call this function instead of inlining instanceof, thus collecting
   // type feedback and reducing code size of unoptimized code.
-  bool _instanceOf(instantiator,
-                   instantiator_type_arguments,
-                   type,
-                   bool negate)
+  bool _instanceOf(instantiator_type_arguments, type, bool negate)
       native "Object_instanceOf";
 
   bool _instanceOfDouble(bool negate) native "Object_instanceOfDouble";
@@ -67,7 +64,7 @@
 
   // Call this function instead of inlining 'as', thus collecting type
   // feedback. Returns receiver.
-  _as(instantiator, instantiator_type_arguments, type) native "Object_as";
+  _as(instantiator_type_arguments, type) native "Object_as";
 
   static _symbolMapToStringMap(Map<Symbol, dynamic> map) {
     var result = new Map<String, dynamic>();
diff --git a/runtime/lib/stopwatch.cc b/runtime/lib/stopwatch.cc
index ce8951de..934aba5 100644
--- a/runtime/lib/stopwatch.cc
+++ b/runtime/lib/stopwatch.cc
@@ -10,14 +10,12 @@
 namespace dart {
 
 DEFINE_NATIVE_ENTRY(Stopwatch_now, 0) {
-  // TODO(iposva): investigate other hi-res time sources such as cycle count.
-  return Integer::New(OS::GetCurrentMonotonicMicros());
+  return Integer::New(OS::GetCurrentMonotonicTicks());
 }
 
 
 DEFINE_NATIVE_ENTRY(Stopwatch_frequency, 0) {
-  // TODO(iposva): investigate other hi-res time sources such as cycle count.
-  return Integer::New(1000000);
+  return Integer::New(OS::GetCurrentMonotonicFrequency());
 }
 
 }  // namespace dart
diff --git a/runtime/lib/timeline.cc b/runtime/lib/timeline.cc
index f0e5982..3d307da 100644
--- a/runtime/lib/timeline.cc
+++ b/runtime/lib/timeline.cc
@@ -49,8 +49,9 @@
     return Object::null();
   }
 
-  if (!isolate->GetDartStream()->Enabled()) {
-    // Dart stream is not enabled for this isolate, do nothing.
+  TimelineEvent* event = isolate->GetDartStream()->StartEvent();
+  if (event == NULL) {
+    // Stream was turned off.
     return Object::null();
   }
 
@@ -58,7 +59,13 @@
   OSThread* os_thread = thread->os_thread();
   ASSERT(os_thread != NULL);
   int64_t tid = OSThread::ThreadIdToIntPtr(os_thread->trace_id());
-
+  // Convert phase to a C string and perform a sanity check.
+  const char* phase_string = phase.ToCString();
+  ASSERT(phase_string != NULL);
+  ASSERT((phase_string[0] == 'n') ||
+         (phase_string[0] == 'b') ||
+         (phase_string[0] == 'e'));
+  ASSERT(phase_string[1] == '\0');
   char* json = OS::SCreate(zone,
       "{\"name\":\"%s\",\"cat\":\"%s\",\"tid\":%" Pd64 ",\"pid\":%" Pd64 ","
       "\"ts\":%" Pd64 ",\"ph\":\"%s\",\"id\":%" Pd64 ", \"args\":%s}",
@@ -67,18 +74,26 @@
       tid,
       pid,
       start.AsInt64Value(),
-      phase.ToCString(),
+      phase_string,
       id.AsInt64Value(),
       args.ToCString());
 
-  TimelineEvent* event = isolate->GetDartStream()->StartEvent();
-  if (event == NULL) {
-    // Stream was turned off.
-    return Object::null();
+  switch (phase_string[0]) {
+    case 'n':
+      event->AsyncInstant("", id.AsInt64Value(), start.AsInt64Value());
+    break;
+    case 'b':
+      event->AsyncBegin("", id.AsInt64Value(), start.AsInt64Value());
+    break;
+    case 'e':
+      event->AsyncEnd("", id.AsInt64Value(), start.AsInt64Value());
+    break;
+    default:
+      UNREACHABLE();
   }
+
   // json was allocated in the zone and a copy will be stored in event.
-  event->SerializedJSON(json);
-  event->Complete();
+  event->CompleteWithPreSerializedJSON(json);
 
   return Object::null();
 }
@@ -96,8 +111,9 @@
     return Object::null();
   }
 
-  if (!isolate->GetDartStream()->Enabled()) {
-    // Dart stream is not enabled for this isolate, do nothing.
+  TimelineEvent* event = isolate->GetDartStream()->StartEvent();
+  if (event == NULL) {
+    // Stream was turned off.
     return Object::null();
   }
 
@@ -118,14 +134,9 @@
       duration,
       args.ToCString());
 
-  TimelineEvent* event = isolate->GetDartStream()->StartEvent();
-  if (event == NULL) {
-    // Stream was turned off.
-    return Object::null();
-  }
+  event->Duration("", start.AsInt64Value(), end.AsInt64Value());
   // json was allocated in the zone and a copy will be stored in event.
-  event->SerializedJSON(json);
-  event->Complete();
+  event->CompleteWithPreSerializedJSON(json);
 
   return Object::null();
 }
@@ -142,8 +153,9 @@
     return Object::null();
   }
 
-  if (!isolate->GetDartStream()->Enabled()) {
-    // Dart stream is not enabled for this isolate, do nothing.
+  TimelineEvent* event = isolate->GetDartStream()->StartEvent();
+  if (event == NULL) {
+    // Stream was turned off.
     return Object::null();
   }
 
@@ -162,14 +174,9 @@
       start.AsInt64Value(),
       args.ToCString());
 
-  TimelineEvent* event = isolate->GetDartStream()->StartEvent();
-  if (event == NULL) {
-    // Stream was turned off.
-    return Object::null();
-  }
+  event->Instant("", start.AsInt64Value());
   // json was allocated in the zone and a copy will be stored in event.
-  event->SerializedJSON(json);
-  event->Complete();
+  event->CompleteWithPreSerializedJSON(json);
 
   return Object::null();
 }
diff --git a/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart b/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart
index 3de30cb..63277b7 100644
--- a/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart
@@ -32,6 +32,35 @@
   return false;
 }
 
+int timeOrigin(List<Map> events) {
+  if (events.length == 0) {
+    return 0;
+  }
+  int smallest = events[0]['ts'];
+  for (var i = 0; i < events.length; i++) {
+    Map event = events[i];
+    if (event['ts'] < smallest) {
+      smallest = event['ts'];
+    }
+  }
+  return smallest;
+}
+
+int timeDuration(List<Map> events, int timeOrigin) {
+  if (events.length == 0) {
+    return 0;
+  }
+  int biggestDuration = events[0]['ts'] - timeOrigin;
+  for (var i = 0; i < events.length; i++) {
+    Map event = events[i];
+    int duration = event['ts'] - timeOrigin;
+    if (duration > biggestDuration) {
+      biggestDuration = duration;
+    }
+  }
+  return biggestDuration;
+}
+
 void allEventsHaveIsolateNumber(List<Map> events) {
   for (Map event in events) {
     if (event['ph'] == 'M') {
@@ -61,6 +90,7 @@
     Map result = await vm.invokeRpcNoUpgrade('_getVMTimeline', {});
     expect(result['type'], equals('_Timeline'));
     expect(result['traceEvents'], new isInstanceOf<List>());
+    final int numEvents = result['traceEvents'].length;
     List<Map> dartEvents = filterForDartEvents(result['traceEvents']);
     expect(dartEvents.length, equals(5));
     allEventsHaveIsolateNumber(dartEvents);
@@ -71,6 +101,19 @@
     expect(eventsContains(dartEvents, 'e', 'TASK1'), isTrue);
     expect(eventsContains(dartEvents, 'n', 'ITASK'), isTrue);
     expect(eventsContains(dartEvents, 'q', 'ITASK'), isFalse);
+    // Calculate the time Window of Dart events.
+    int origin = timeOrigin(dartEvents);
+    int extent = timeDuration(dartEvents, origin);
+    // Query for the timeline with the time window for Dart events.
+    result = await vm.invokeRpcNoUpgrade('_getVMTimeline', {
+      'timeOriginMicros': origin,
+      'timeExtentMicros': extent
+    });
+    // Verify that we received fewer events than before.
+    expect(result['traceEvents'].length, lessThan(numEvents));
+    // Verify that we have the same number of Dart events.
+    List<Map> dartEvents2 = filterForDartEvents(result['traceEvents']);
+    expect(dartEvents2.length, dartEvents.length);
   },
 ];
 
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index 0044c29..7562cf4 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -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.
 
-[ $compiler == none && $runtime == vm ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) ]
 evaluate_activation_test/instance: RuntimeError # http://dartbug.com/20047
 evaluate_activation_test/scope: RuntimeError # http://dartbug.com/20047
 
@@ -21,5 +21,5 @@
 [ $arch == arm ]
 process_service_test: Pass, Fail # Issue 24344
 
-[ $noopt ]
+[ ($noopt || $compiler == precompiler) ]
 *: Skip # Issue 24651
\ No newline at end of file
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 21a91f8..7a914be 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -14,6 +14,8 @@
 
 dart/data_uri_import_test/none: SkipByDesign
 
+dart/spawn_shutdown_test: Skip # Issue 25351
+
 [ $mode == debug ]
 # This is a benchmark that is not informative in debug mode.
 cc/CorelibIsolateStartup: Skip
@@ -57,7 +59,7 @@
 # Data uri's not supported by dart2js or the analyzer.
 dart/data_uri*test: Skip
 
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
 dart/data_uri_import_test/wrongmime: RuntimeError, OK # VM is more restrictive than the browser
 dart/data_uri_import_test/nomime: RuntimeError, OK
 dart/data_uri_import_test/nocharset: RuntimeError, OK
@@ -78,10 +80,16 @@
 dart/spawn_infinite_loop_test: Skip  # VM shutdown test
 dart/spawn_shutdown_test: Skip  # VM Shutdown test
 
-[ $runtime == vm && $mode == debug && $builder_tag == asan ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $mode == debug && $builder_tag == asan ]
 cc/Dart2JSCompileAll: Skip  # Timeout.
 
 [ $noopt ]
-dart/redirection_type_shuffling_test: CompileTimeError # Imports dart:mirrors
 dart/byte_array_test: Crash # Incompatible flag --disable_alloc_stubs_after_gc
+
+[ $noopt || $compiler == precompiler ]
+dart/redirection_type_shuffling_test: CompileTimeError # Imports dart:mirrors
 dart/inline_stack_frame_test: Fail  # Issue 24783 - inlined frames missing
+
+[ $runtime == dart_precompiled ]
+dart/optimized_stacktrace_test: Fail
+dart/data_uri_spawn_test: RuntimeError # Isolate.spawnUri
diff --git a/runtime/tools/bmu_benchmark_gallery.sh b/runtime/tools/bmu_benchmark_gallery.sh
index 18feef0..3c1d76b 100644
--- a/runtime/tools/bmu_benchmark_gallery.sh
+++ b/runtime/tools/bmu_benchmark_gallery.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 #
 # 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
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index c32632d..d31948a 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -1562,6 +1562,7 @@
 
 
 bool Assembler::CanLoadFromObjectPool(const Object& object) const {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   ASSERT(!Thread::CanLoadFromThread(object));
   if (!constant_pool_allowed()) {
     return false;
@@ -1578,6 +1579,7 @@
                                  Condition cond,
                                  bool is_unique,
                                  Register pp) {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   // Load common VM constants from the thread. This works also in places where
   // no constant pool is set up (e.g. intrinsic code).
   if (Thread::CanLoadFromThread(object)) {
@@ -1636,12 +1638,14 @@
 
 
 void Assembler::PushObject(const Object& object) {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   LoadObject(IP, object);
   Push(IP);
 }
 
 
 void Assembler::CompareObject(Register rn, const Object& object) {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   ASSERT(rn != IP);
   if (object.IsSmi()) {
     CompareImmediate(rn, reinterpret_cast<int32_t>(object.raw()));
@@ -1900,6 +1904,7 @@
                                          const Address& dest,
                                          const Object& value,
                                          FieldContent old_content) {
+  ASSERT(!value.IsICData() || ICData::Cast(value).IsOriginal());
   ASSERT(value.IsSmi() || value.InVMHeap() ||
          (value.IsOld() && value.IsNotTemporaryScopedHandle()));
   // No store buffer update.
@@ -1912,6 +1917,7 @@
                                                int32_t offset,
                                                const Object& value,
                                                FieldContent old_content) {
+  ASSERT(!value.IsICData() || ICData::Cast(value).IsOriginal());
   int32_t ignored = 0;
   if (Address::CanHoldStoreOffset(kWord, offset - kHeapObjectTag, &ignored)) {
     StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value,
diff --git a/runtime/vm/assembler_arm64.cc b/runtime/vm/assembler_arm64.cc
index 14a51cd..062ad4b 100644
--- a/runtime/vm/assembler_arm64.cc
+++ b/runtime/vm/assembler_arm64.cc
@@ -367,6 +367,7 @@
 
 
 bool Assembler::CanLoadFromObjectPool(const Object& object) const {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   ASSERT(!Thread::CanLoadFromThread(object));
   if (!constant_pool_allowed()) {
     return false;
@@ -401,6 +402,7 @@
 void Assembler::LoadObjectHelper(Register dst,
                                  const Object& object,
                                  bool is_unique) {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   if (Thread::CanLoadFromThread(object)) {
     ldr(dst, Address(THR, Thread::OffsetFromThread(object)));
   } else if (CanLoadFromObjectPool(object)) {
@@ -439,6 +441,7 @@
 
 
 void Assembler::CompareObject(Register reg, const Object& object) {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   if (Thread::CanLoadFromThread(object)) {
     ldr(TMP, Address(THR, Thread::OffsetFromThread(object)));
     CompareRegisters(reg, TMP);
@@ -933,6 +936,7 @@
 void Assembler::StoreIntoObjectNoBarrier(Register object,
                                          const Address& dest,
                                          const Object& value) {
+  ASSERT(!value.IsICData() || ICData::Cast(value).IsOriginal());
   ASSERT(value.IsSmi() || value.InVMHeap() ||
          (value.IsOld() && value.IsNotTemporaryScopedHandle()));
   // No store buffer update.
diff --git a/runtime/vm/assembler_ia32.cc b/runtime/vm/assembler_ia32.cc
index c4ee937..8d3fb09 100644
--- a/runtime/vm/assembler_ia32.cc
+++ b/runtime/vm/assembler_ia32.cc
@@ -2163,6 +2163,7 @@
 
 
 void Assembler::LoadObject(Register dst, const Object& object) {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   if (object.IsSmi() || object.InVMHeap()) {
     movl(dst, Immediate(reinterpret_cast<int32_t>(object.raw())));
   } else {
@@ -2176,6 +2177,7 @@
 
 
 void Assembler::LoadObjectSafely(Register dst, const Object& object) {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   if (Assembler::IsSafe(object)) {
     LoadObject(dst, object);
   } else {
@@ -2187,6 +2189,7 @@
 
 
 void Assembler::PushObject(const Object& object) {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   if (object.IsSmi() || object.InVMHeap()) {
     pushl(Immediate(reinterpret_cast<int32_t>(object.raw())));
   } else {
@@ -2200,6 +2203,7 @@
 
 
 void Assembler::CompareObject(Register reg, const Object& object) {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   if (object.IsSmi() || object.InVMHeap()) {
     cmpl(reg, Immediate(reinterpret_cast<int32_t>(object.raw())));
   } else {
@@ -2398,6 +2402,7 @@
 
 void Assembler::UnverifiedStoreOldObject(const Address& dest,
                                          const Object& value) {
+  ASSERT(!value.IsICData() || ICData::Cast(value).IsOriginal());
   ASSERT(value.IsOld());
   ASSERT(!value.InVMHeap());
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
@@ -2411,6 +2416,7 @@
                                          const Address& dest,
                                          const Object& value,
                                          FieldContent old_content) {
+  ASSERT(!value.IsICData() || ICData::Cast(value).IsOriginal());
   VerifyHeapWord(dest, old_content);
   if (value.IsSmi() || value.InVMHeap()) {
     Immediate imm_value(reinterpret_cast<int32_t>(value.raw()));
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc
index 9f63660..0f15e3f 100644
--- a/runtime/vm/assembler_mips.cc
+++ b/runtime/vm/assembler_mips.cc
@@ -532,6 +532,7 @@
 
 
 bool Assembler::CanLoadFromObjectPool(const Object& object) const {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   ASSERT(!Thread::CanLoadFromThread(object));
   if (!constant_pool_allowed()) {
     return false;
@@ -546,6 +547,7 @@
 void Assembler::LoadObjectHelper(Register rd,
                                  const Object& object,
                                  bool is_unique) {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   ASSERT(!in_delay_slot_);
   if (Thread::CanLoadFromThread(object)) {
     // Load common VM constants from the thread. This works also in places where
@@ -603,6 +605,7 @@
 
 
 void Assembler::PushObject(const Object& object) {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   ASSERT(!in_delay_slot_);
   LoadObject(TMP, object);
   Push(TMP);
@@ -729,6 +732,7 @@
 void Assembler::StoreIntoObjectNoBarrier(Register object,
                                          const Address& dest,
                                          const Object& value) {
+  ASSERT(!value.IsICData() || ICData::Cast(value).IsOriginal());
   ASSERT(!in_delay_slot_);
   ASSERT(value.IsSmi() || value.InVMHeap() ||
          (value.IsOld() && value.IsNotTemporaryScopedHandle()));
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
index b3a1d09..85b83a9 100644
--- a/runtime/vm/assembler_x64.cc
+++ b/runtime/vm/assembler_x64.cc
@@ -2737,6 +2737,7 @@
 
 
 bool Assembler::CanLoadFromObjectPool(const Object& object) const {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   ASSERT(!Thread::CanLoadFromThread(object));
   if (!constant_pool_allowed()) {
     return false;
@@ -2772,6 +2773,7 @@
 void Assembler::LoadObjectHelper(Register dst,
                                  const Object& object,
                                  bool is_unique) {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   if (Thread::CanLoadFromThread(object)) {
     movq(dst, Address(THR, Thread::OffsetFromThread(object)));
   } else if (CanLoadFromObjectPool(object)) {
@@ -2809,6 +2811,7 @@
 
 
 void Assembler::StoreObject(const Address& dst, const Object& object) {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   if (Thread::CanLoadFromThread(object)) {
     movq(TMP, Address(THR, Thread::OffsetFromThread(object)));
     movq(dst, TMP);
@@ -2823,6 +2826,7 @@
 
 
 void Assembler::PushObject(const Object& object) {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   if (Thread::CanLoadFromThread(object)) {
     pushq(Address(THR, Thread::OffsetFromThread(object)));
   } else if (CanLoadFromObjectPool(object)) {
@@ -2836,6 +2840,7 @@
 
 
 void Assembler::CompareObject(Register reg, const Object& object) {
+  ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
   if (Thread::CanLoadFromThread(object)) {
     cmpq(reg, Address(THR, Thread::OffsetFromThread(object)));
   } else if (CanLoadFromObjectPool(object)) {
@@ -3062,6 +3067,7 @@
                                          const Address& dest,
                                          const Object& value,
                                          FieldContent old_content) {
+  ASSERT(!value.IsICData() || ICData::Cast(value).IsOriginal());
   VerifyHeapWord(dest, old_content);
   if (VerifiedMemory::enabled()) {
     const Register temp = RCX;
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 3d2254f..a3b3952 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -20,13 +20,13 @@
   V(Object_toString, 1)                                                        \
   V(Object_noSuchMethod, 6)                                                    \
   V(Object_runtimeType, 1)                                                     \
-  V(Object_instanceOf, 5)                                                      \
+  V(Object_instanceOf, 4)                                                      \
   V(Object_instanceOfNum, 2)                                                   \
   V(Object_instanceOfInt, 2)                                                   \
   V(Object_instanceOfSmi, 2)                                                   \
   V(Object_instanceOfDouble, 2)                                                \
   V(Object_instanceOfString, 2)                                                \
-  V(Object_as, 4)                                                              \
+  V(Object_as, 3)                                                              \
   V(Function_apply, 2)                                                         \
   V(FunctionImpl_equals, 2)                                                    \
   V(FunctionImpl_hashCode, 1)                                                  \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 1151e2d..8ef3511 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -35,9 +35,12 @@
 // Only methods which owner classes where subclasses can be invalid.
 // TODO(srdjan): Be even more precise by recording the exact CHA optimization.
 static void RemoveCHAOptimizedCode(
+    const Class& subclass,
     const GrowableArray<intptr_t>& added_subclass_to_cids) {
   ASSERT(FLAG_use_cha_deopt);
-  if (added_subclass_to_cids.is_empty()) return;
+  if (added_subclass_to_cids.is_empty()) {
+    return;
+  }
   // Switch all functions' code to unoptimized.
   const ClassTable& class_table = *Isolate::Current()->class_table();
   Class& cls = Class::Handle();
@@ -45,7 +48,7 @@
     intptr_t cid = added_subclass_to_cids[i];
     cls = class_table.At(cid);
     ASSERT(!cls.IsNull());
-    cls.DisableCHAOptimizedCode();
+    cls.DisableCHAOptimizedCode(subclass);
   }
 }
 
@@ -2412,7 +2415,7 @@
     GrowableArray<intptr_t> cids;
     CollectFinalizedSuperClasses(cls, &cids);
     CollectImmediateSuperInterfaces(cls, &cids);
-    RemoveCHAOptimizedCode(cids);
+    RemoveCHAOptimizedCode(cls, cids);
   }
   if (cls.is_enum_class()) {
     AllocateEnumValues(cls);
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index b981608..d7c92d7 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -57,9 +57,10 @@
 DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls");
 DEFINE_FLAG(bool, trace_type_checks, false, "Trace runtime type checks.");
 
-DECLARE_FLAG(int, deoptimization_counter_threshold);
+DECLARE_FLAG(int, max_deoptimization_counter_threshold);
 DECLARE_FLAG(bool, enable_inlining_annotations);
 DECLARE_FLAG(bool, trace_compiler);
+DECLARE_FLAG(bool, trace_optimizing_compiler);
 DECLARE_FLAG(bool, warn_on_javascript_compatibility);
 DECLARE_FLAG(int, max_polymorphic_checks);
 
@@ -338,11 +339,9 @@
 // case it contains just the result of the class subtype test, not including
 // the evaluation of type arguments.
 // This operation is currently very slow (lookup of code is not efficient yet).
-// 'instantiator' can be null, in which case inst_targ
 static void UpdateTypeTestCache(
     const Instance& instance,
     const AbstractType& type,
-    const Instance& instantiator,
     const TypeArguments& instantiator_type_arguments,
     const Bool& result,
     const SubtypeTestCache& new_cache) {
@@ -447,18 +446,16 @@
 // Tested instance may not be null, because the null test is inlined.
 // Arg0: instance being checked.
 // Arg1: type.
-// Arg2: instantiator (or null).
-// Arg3: type arguments of the instantiator of the type.
-// Arg4: SubtypeTestCache.
+// Arg2: type arguments of the instantiator of the type.
+// Arg3: SubtypeTestCache.
 // Return value: true or false, or may throw a type error in checked mode.
-DEFINE_RUNTIME_ENTRY(Instanceof, 5) {
+DEFINE_RUNTIME_ENTRY(Instanceof, 4) {
   const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0));
   const AbstractType& type = AbstractType::CheckedHandle(arguments.ArgAt(1));
-  const Instance& instantiator = Instance::CheckedHandle(arguments.ArgAt(2));
   const TypeArguments& instantiator_type_arguments =
-      TypeArguments::CheckedHandle(arguments.ArgAt(3));
+      TypeArguments::CheckedHandle(arguments.ArgAt(2));
   const SubtypeTestCache& cache =
-      SubtypeTestCache::CheckedHandle(arguments.ArgAt(4));
+      SubtypeTestCache::CheckedHandle(arguments.ArgAt(3));
   ASSERT(type.IsFinalized());
   ASSERT(!type.IsDynamicType());  // No need to check assignment.
   ASSERT(!type.IsMalformed());  // Already checked in code generator.
@@ -482,8 +479,8 @@
         Symbols::Empty(), bound_error_message);
     UNREACHABLE();
   }
-  UpdateTypeTestCache(instance, type, instantiator,
-                      instantiator_type_arguments, result, cache);
+  UpdateTypeTestCache(
+      instance, type, instantiator_type_arguments, result, cache);
   arguments.SetReturn(result);
 }
 
@@ -492,22 +489,19 @@
 // can therefore be assigned.
 // Arg0: instance being assigned.
 // Arg1: type being assigned to.
-// Arg2: instantiator (or null).
-// Arg3: type arguments of the instantiator of the type being assigned to.
-// Arg4: name of variable being assigned to.
-// Arg5: SubtypeTestCache.
+// Arg2: type arguments of the instantiator of the type being assigned to.
+// Arg3: name of variable being assigned to.
+// Arg4: SubtypeTestCache.
 // Return value: instance if a subtype, otherwise throw a TypeError.
-DEFINE_RUNTIME_ENTRY(TypeCheck, 6) {
+DEFINE_RUNTIME_ENTRY(TypeCheck, 5) {
   const Instance& src_instance = Instance::CheckedHandle(arguments.ArgAt(0));
   const AbstractType& dst_type =
       AbstractType::CheckedHandle(arguments.ArgAt(1));
-  const Instance& dst_instantiator =
-      Instance::CheckedHandle(arguments.ArgAt(2));
   const TypeArguments& instantiator_type_arguments =
-      TypeArguments::CheckedHandle(arguments.ArgAt(3));
-  const String& dst_name = String::CheckedHandle(arguments.ArgAt(4));
+      TypeArguments::CheckedHandle(arguments.ArgAt(2));
+  const String& dst_name = String::CheckedHandle(arguments.ArgAt(3));
   const SubtypeTestCache& cache =
-      SubtypeTestCache::CheckedHandle(arguments.ArgAt(5));
+      SubtypeTestCache::CheckedHandle(arguments.ArgAt(4));
   ASSERT(!dst_type.IsDynamicType());  // No need to check assignment.
   ASSERT(!dst_type.IsMalformed());  // Already checked in code generator.
   ASSERT(!dst_type.IsMalbounded());  // Already checked in code generator.
@@ -565,9 +559,8 @@
                                         dst_name, bound_error_message);
     UNREACHABLE();
   }
-  UpdateTypeTestCache(src_instance, dst_type,
-                      dst_instantiator, instantiator_type_arguments,
-                      Bool::True(), cache);
+  UpdateTypeTestCache(
+      src_instance, dst_type, instantiator_type_arguments, Bool::True(), cache);
   arguments.SetReturn(src_instance);
 }
 
@@ -684,7 +677,7 @@
                                  target_code);
   caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code);
   if (FLAG_trace_patching) {
-    OS::PrintErr("PatchStaticCall: patching caller pc %#" Px ""
+    THR_Print("PatchStaticCall: patching caller pc %#" Px ""
         " to '%s' new entry point %#" Px " (%s)\n",
         caller_frame->pc(),
         target_function.ToFullyQualifiedCString(),
@@ -1252,7 +1245,6 @@
 
 
 static bool CanOptimizeFunction(const Function& function, Thread* thread) {
-  const intptr_t kLowInvocationCount = -100000000;
   Isolate* isolate = thread->isolate();
   if (isolate->debugger()->IsStepping() ||
       isolate->debugger()->HasBreakpoint(function, thread->zone())) {
@@ -1262,17 +1254,19 @@
     return false;
   }
   if (function.deoptimization_counter() >=
-      FLAG_deoptimization_counter_threshold) {
+      FLAG_max_deoptimization_counter_threshold) {
     if (FLAG_trace_failed_optimization_attempts ||
         FLAG_stop_on_excessive_deoptimization) {
-      OS::PrintErr("Too Many Deoptimizations: %s\n",
+      THR_Print("Too many deoptimizations: %s\n",
           function.ToFullyQualifiedCString());
       if (FLAG_stop_on_excessive_deoptimization) {
         FATAL("Stop on excessive deoptimization");
       }
     }
-    // TODO(srdjan): Investigate excessive deoptimization.
-    function.set_usage_counter(kLowInvocationCount);
+    // The function will not be optimized any longer. This situation can occur
+    // mostly with small optimization counter thresholds.
+    function.SetIsOptimizable(false);
+    function.set_usage_counter(INT_MIN);
     return false;
   }
   if (FLAG_optimization_filter != NULL) {
@@ -1294,16 +1288,17 @@
     }
     delete[] filter;
     if (!found) {
-      function.set_usage_counter(kLowInvocationCount);
+      function.set_usage_counter(INT_MIN);
       return false;
     }
   }
   if (!function.IsOptimizable()) {
+    // Huge methods (code size above --huge_method_cutoff_in_code_size) become
+    // non-optimizable only after the code has been generated.
     if (FLAG_trace_failed_optimization_attempts) {
-      OS::PrintErr("Not Optimizable: %s\n", function.ToFullyQualifiedCString());
+      THR_Print("Not optimizable: %s\n", function.ToFullyQualifiedCString());
     }
-    // TODO(5442338): Abort as this should not happen.
-    function.set_usage_counter(kLowInvocationCount);
+    function.set_usage_counter(INT_MIN);
     return false;
   }
   return true;
@@ -1506,7 +1501,7 @@
     // Reset usage counter for reoptimization before calling optimizer to
     // prevent recursive triggering of function optimization.
     function.set_usage_counter(0);
-    if (FLAG_trace_compiler) {
+    if (FLAG_trace_compiler || FLAG_trace_optimizing_compiler) {
       if (function.HasOptimizedCode()) {
         THR_Print("ReCompiling function: '%s' \n",
                   function.ToFullyQualifiedCString());
@@ -1714,6 +1709,9 @@
 
 // Copies saved registers and caller's frame into temporary buffers.
 // Returns the stack size of unoptimized frame.
+// The calling code must be optimized, but its function may not have
+// have optimized code if the code is OSR code, or if the code was invalidated
+// through class loading/finalization or field guard.
 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
                           2,
                           uword saved_registers_address,
@@ -1735,6 +1733,16 @@
   ASSERT(caller_frame != NULL);
   const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
   ASSERT(optimized_code.is_optimized());
+  const Function& top_function =
+      Function::Handle(thread->zone(), optimized_code.function());
+  const bool deoptimizing_code = top_function.HasOptimizedCode();
+  if (FLAG_trace_deoptimization) {
+    const Function& function = Function::Handle(optimized_code.function());
+    THR_Print("== Deoptimizing code for '%s', %s, %s\n",
+       function.ToFullyQualifiedCString(),
+       deoptimizing_code ? "code & frame" : "frame",
+       is_lazy_deopt ? "lazy-deopt" : "");
+  }
 
   // Copy the saved registers from the stack.
   fpu_register_t* fpu_registers;
@@ -1748,7 +1756,8 @@
                        DeoptContext::kDestIsOriginalFrame,
                        fpu_registers,
                        cpu_registers,
-                       is_lazy_deopt != 0);
+                       is_lazy_deopt != 0,
+                       deoptimizing_code);
   isolate->set_deopt_context(deopt_context);
 
   // Stack size (FP - SP) in bytes.
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 17edba2..be9c996 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -46,7 +46,7 @@
     "Do common subexpression elimination.");
 DEFINE_FLAG(bool, constant_propagation, true,
     "Do conditional constant propagation/unreachable code elimination.");
-DEFINE_FLAG(int, deoptimization_counter_threshold, 16,
+DEFINE_FLAG(int, max_deoptimization_counter_threshold, 16,
     "How many times we allow deoptimization before we disallow optimization.");
 DEFINE_FLAG(bool, disassemble, false, "Disassemble dart code.");
 DEFINE_FLAG(bool, disassemble_optimized, false, "Disassemble optimized code.");
@@ -60,6 +60,8 @@
 DEFINE_FLAG(bool, range_analysis, true, "Enable range analysis");
 DEFINE_FLAG(bool, reorder_basic_blocks, true, "Enable basic-block reordering.");
 DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations.");
+DEFINE_FLAG(bool, trace_optimizing_compiler, false,
+    "Trace only optimizing compiler operations.");
 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler.");
 DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining");
 DEFINE_FLAG(bool, verify_compiler, false,
@@ -68,6 +70,7 @@
     "Max number of attempts with speculative inlining (precompilation only)");
 
 DECLARE_FLAG(bool, background_compilation);
+DECLARE_FLAG(bool, huge_method_cutoff_in_code_size);
 DECLARE_FLAG(bool, load_deferred_eagerly);
 DECLARE_FLAG(bool, trace_failed_optimization_attempts);
 DECLARE_FLAG(bool, trace_inlining_intervals);
@@ -396,31 +399,216 @@
 }
 
 
+class CompileParsedFunctionHelper : public ValueObject {
+ public:
+  CompileParsedFunctionHelper(ParsedFunction* parsed_function,
+                              bool optimized,
+                              intptr_t osr_id)
+      : parsed_function_(parsed_function),
+        optimized_(optimized),
+        osr_id_(osr_id),
+        thread_(Thread::Current()),
+        cha_invalidation_gen_at_start_(isolate()->cha_invalidation_gen()),
+        field_invalidation_gen_at_start_(isolate()->field_invalidation_gen()),
+        prefix_invalidation_gen_at_start_(
+            isolate()->prefix_invalidation_gen()) {
+  }
+
+  bool Compile(CompilationPipeline* pipeline);
+
+ private:
+  ParsedFunction* parsed_function() const { return parsed_function_; }
+  bool optimized() const { return optimized_; }
+  intptr_t osr_id() const { return osr_id_; }
+  Thread* thread() const { return thread_; }
+  Isolate* isolate() const { return thread_->isolate(); }
+  uint32_t cha_invalidation_gen_at_start() const {
+    return cha_invalidation_gen_at_start_;
+  }
+  uint32_t field_invalidation_gen_at_start() const {
+    return field_invalidation_gen_at_start_;
+  }
+  uint32_t prefix_invalidation_gen_at_start() const {
+    return prefix_invalidation_gen_at_start_;
+  }
+  void FinalizeCompilation(Assembler* assembler,
+                           FlowGraphCompiler* graph_compiler,
+                           FlowGraph* flow_graph);
+
+  ParsedFunction* parsed_function_;
+  const bool optimized_;
+  const intptr_t osr_id_;
+  Thread* const thread_;
+  const uint32_t cha_invalidation_gen_at_start_;
+  const uint32_t field_invalidation_gen_at_start_;
+  const uint32_t prefix_invalidation_gen_at_start_;
+
+  DISALLOW_COPY_AND_ASSIGN(CompileParsedFunctionHelper);
+};
+
+
+void CompileParsedFunctionHelper::FinalizeCompilation(
+    Assembler* assembler,
+    FlowGraphCompiler* graph_compiler,
+    FlowGraph* flow_graph) {
+  const Function& function = parsed_function()->function();
+  Zone* const zone = thread()->zone();
+
+  CSTAT_TIMER_SCOPE(thread(), codefinalizer_timer);
+  // CreateDeoptInfo uses the object pool and needs to be done before
+  // FinalizeCode.
+  const Array& deopt_info_array =
+      Array::Handle(zone, graph_compiler->CreateDeoptInfo(assembler));
+  INC_STAT(thread(), total_code_size,
+           deopt_info_array.Length() * sizeof(uword));
+  // Allocates instruction object. Since this occurs only at safepoint,
+  // there can be no concurrent access to the instruction page.
+  const Code& code = Code::Handle(
+      Code::FinalizeCode(function, assembler, optimized()));
+  code.set_is_optimized(optimized());
+  code.set_owner(function);
+  if (!function.IsOptimizable()) {
+    // A function with huge unoptimized code can become non-optimizable
+    // after generating unoptimized code.
+    function.set_usage_counter(INT_MIN);
+  }
+
+  const Array& intervals = graph_compiler->inlined_code_intervals();
+  INC_STAT(thread(), total_code_size,
+           intervals.Length() * sizeof(uword));
+  code.SetInlinedIntervals(intervals);
+
+  const Array& inlined_id_array =
+      Array::Handle(zone, graph_compiler->InliningIdToFunction());
+  INC_STAT(thread(), total_code_size,
+           inlined_id_array.Length() * sizeof(uword));
+  code.SetInlinedIdToFunction(inlined_id_array);
+
+  const Array& caller_inlining_id_map_array =
+      Array::Handle(zone, graph_compiler->CallerInliningIdMap());
+  INC_STAT(thread(), total_code_size,
+           caller_inlining_id_map_array.Length() * sizeof(uword));
+  code.SetInlinedCallerIdMap(caller_inlining_id_map_array);
+
+  graph_compiler->FinalizePcDescriptors(code);
+  code.set_deopt_info_array(deopt_info_array);
+
+  graph_compiler->FinalizeStackmaps(code);
+  graph_compiler->FinalizeVarDescriptors(code);
+  graph_compiler->FinalizeExceptionHandlers(code);
+  graph_compiler->FinalizeStaticCallTargetsTable(code);
+
+  if (optimized()) {
+    // Installs code while at safepoint.
+    if (thread()->IsMutatorThread()) {
+      const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
+      function.InstallOptimizedCode(code, is_osr);
+    } else {
+      // Background compilation.
+      // Before installing code check generation counts if the code may
+      // have become invalid.
+      const bool trace_compiler =
+          FLAG_trace_compiler || FLAG_trace_optimizing_compiler;
+      bool code_is_valid = true;
+      if (!thread()->cha()->leaf_classes().is_empty()) {
+        if (cha_invalidation_gen_at_start() !=
+            isolate()->cha_invalidation_gen()) {
+          code_is_valid = false;
+          if (trace_compiler) {
+            THR_Print("--> FAIL: CHA invalidation.");
+          }
+        }
+      }
+      if (!flow_graph->guarded_fields()->is_empty()) {
+        if (field_invalidation_gen_at_start() !=
+            isolate()->field_invalidation_gen()) {
+          code_is_valid = false;
+          if (trace_compiler) {
+            THR_Print("--> FAIL: Field invalidation.");
+          }
+        }
+      }
+      if (parsed_function()->HasDeferredPrefixes()) {
+        if (prefix_invalidation_gen_at_start() !=
+            isolate()->prefix_invalidation_gen()) {
+          code_is_valid = false;
+          if (trace_compiler) {
+            THR_Print("--> FAIL: Prefix invalidation.");
+          }
+        }
+      }
+      if (code_is_valid) {
+        const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
+        ASSERT(!is_osr);  // OSR is compiled in background.
+        function.InstallOptimizedCode(code, is_osr);
+      }
+      if (function.usage_counter() < 0) {
+        // Reset to 0 so that it can be recompiled if needed.
+        function.set_usage_counter(0);
+      }
+    }
+
+    // Register code with the classes it depends on because of CHA and
+    // fields it depends on because of store guards, unless we cannot
+    // deopt.
+    if (Compiler::allow_recompilation()) {
+      // Deoptimize field dependent code first, before registering
+      // this yet uninstalled code as dependent on a field.
+      // TODO(srdjan): Debugging dart2js crashes;
+      // FlowGraphOptimizer::VisitStoreInstanceField populates
+      // deoptimize_dependent_code() list, currently disabled.
+      for (intptr_t i = 0;
+           i < flow_graph->deoptimize_dependent_code().length();
+           i++) {
+        const Field* field = flow_graph->deoptimize_dependent_code()[i];
+        field->DeoptimizeDependentCode();
+      }
+      for (intptr_t i = 0;
+           i < thread()->cha()->leaf_classes().length();
+           ++i) {
+        thread()->cha()->leaf_classes()[i]->RegisterCHACode(code);
+      }
+      for (intptr_t i = 0;
+           i < flow_graph->guarded_fields()->length();
+           i++) {
+        const Field* field = (*flow_graph->guarded_fields())[i];
+        field->RegisterDependentCode(code);
+      }
+    }
+  } else {  // not optimized.
+    if (!Compiler::always_optimize() &&
+        (function.ic_data_array() == Array::null())) {
+      function.SaveICDataMap(
+          graph_compiler->deopt_id_to_ic_data(),
+          Array::Handle(zone, graph_compiler->edge_counters_array()));
+    }
+    function.set_unoptimized_code(code);
+    function.AttachCode(code);
+  }
+  if (parsed_function()->HasDeferredPrefixes()) {
+    ASSERT(!FLAG_load_deferred_eagerly);
+    ZoneGrowableArray<const LibraryPrefix*>* prefixes =
+        parsed_function()->deferred_prefixes();
+    for (intptr_t i = 0; i < prefixes->length(); i++) {
+      (*prefixes)[i]->RegisterDependentCode(code);
+    }
+  }
+}
+
+
 // Return false if bailed out.
 // If optimized_result_code is not NULL then it is caller's responsibility
 // to install code.
-static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline,
-                                        ParsedFunction* parsed_function,
-                                        bool optimized,
-                                        intptr_t osr_id) {
-  const Function& function = parsed_function->function();
-  if (optimized && !function.IsOptimizable()) {
+bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
+  const Function& function = parsed_function()->function();
+  if (optimized() && !function.IsOptimizable()) {
     return false;
   }
   bool is_compiled = false;
-  Thread* const thread = Thread::Current();
-  Zone* const zone = thread->zone();
-  Isolate* const isolate = thread->isolate();
-  TimelineStream* compiler_timeline = isolate->GetCompilerStream();
-  CSTAT_TIMER_SCOPE(thread, codegen_timer);
-  HANDLESCOPE(thread);
-
-  // Get current generation count so that we can check and ensure that the code
-  // was not invalidated while we were compiling in the background.
-  uint32_t cha_invalidation_gen_at_start = isolate->cha_invalidation_gen();
-  uint32_t field_invalidation_gen_at_start = isolate->field_invalidation_gen();
-  uint32_t prefix_invalidation_gen_at_start =
-      isolate->prefix_invalidation_gen();
+  Zone* const zone = thread()->zone();
+  TimelineStream* compiler_timeline = isolate()->GetCompilerStream();
+  CSTAT_TIMER_SCOPE(thread(), codegen_timer);
+  HANDLESCOPE(thread());
 
   // We may reattempt compilation if the function needs to be assembled using
   // far branches on ARM and MIPS. In the else branch of the setjmp call,
@@ -436,8 +624,8 @@
   GrowableArray<intptr_t> inlining_black_list;
 
   while (!done) {
-    const intptr_t prev_deopt_id = thread->deopt_id();
-    thread->set_deopt_id(0);
+    const intptr_t prev_deopt_id = thread()->deopt_id();
+    thread()->set_deopt_id(0);
     LongJumpScope jump;
     const intptr_t val = setjmp(*jump.Set());
     if (val == 0) {
@@ -445,19 +633,19 @@
 
       // Class hierarchy analysis is registered with the isolate in the
       // constructor and unregisters itself upon destruction.
-      CHA cha(thread);
+      CHA cha(thread());
 
       // TimerScope needs an isolate to be properly terminated in case of a
       // LongJump.
       {
-        CSTAT_TIMER_SCOPE(thread, graphbuilder_timer);
+        CSTAT_TIMER_SCOPE(thread(), graphbuilder_timer);
         ZoneGrowableArray<const ICData*>* ic_data_array =
             new(zone) ZoneGrowableArray<const ICData*>();
-        if (optimized) {
+        if (optimized()) {
           // Extract type feedback before the graph is built, as the graph
           // builder uses it to attach it to nodes.
           ASSERT(function.deoptimization_counter() <
-                 FLAG_deoptimization_counter_threshold);
+                 FLAG_max_deoptimization_counter_threshold);
 
           // 'Freeze' ICData in background compilation so that it does not
           // change while compiling.
@@ -474,22 +662,22 @@
           }
         }
 
-        TimelineDurationScope tds(thread,
+        TimelineDurationScope tds(thread(),
                                   compiler_timeline,
                                   "BuildFlowGraph");
         flow_graph = pipeline->BuildFlowGraph(zone,
-                                              parsed_function,
+                                              parsed_function(),
                                               *ic_data_array,
-                                              osr_id);
+                                              osr_id());
       }
 
       const bool print_flow_graph =
           (FLAG_print_flow_graph ||
-          (optimized && FLAG_print_flow_graph_optimized)) &&
+           (optimized() && FLAG_print_flow_graph_optimized)) &&
           FlowGraphPrinter::ShouldPrint(function);
 
       if (print_flow_graph) {
-        if (osr_id == Compiler::kNoOSRDeoptId) {
+        if (osr_id() == Compiler::kNoOSRDeoptId) {
           FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph);
         } else {
           FlowGraphPrinter::PrintGraph("For OSR", flow_graph);
@@ -498,19 +686,19 @@
 
       BlockScheduler block_scheduler(flow_graph);
       const bool reorder_blocks =
-          FlowGraph::ShouldReorderBlocks(function, optimized);
+          FlowGraph::ShouldReorderBlocks(function, optimized());
       if (reorder_blocks) {
-        TimelineDurationScope tds(thread,
+        TimelineDurationScope tds(thread(),
                                   compiler_timeline,
                                   "BlockScheduler::AssignEdgeWeights");
         block_scheduler.AssignEdgeWeights();
       }
 
-      if (optimized) {
-        TimelineDurationScope tds(thread,
+      if (optimized()) {
+        TimelineDurationScope tds(thread(),
                                   compiler_timeline,
                                   "ComputeSSA");
-        CSTAT_TIMER_SCOPE(thread, ssa_timer);
+        CSTAT_TIMER_SCOPE(thread(), ssa_timer);
         // Transform to SSA (virtual register 0 and no inlining arguments).
         flow_graph->ComputeSSA(0, NULL);
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
@@ -527,14 +715,14 @@
       // Collect all instance fields that are loaded in the graph and
       // have non-generic type feedback attached to them that can
       // potentially affect optimizations.
-      if (optimized) {
-        TimelineDurationScope tds(thread,
+      if (optimized()) {
+        TimelineDurationScope tds(thread(),
                                   compiler_timeline,
                                   "OptimizationPasses");
         inline_id_to_function.Add(&function);
         // Top scope function has no caller (-1).
         caller_inline_id.Add(-1);
-        CSTAT_TIMER_SCOPE(thread, graphoptimizer_timer);
+        CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer);
 
         FlowGraphOptimizer optimizer(flow_graph,
                                      use_speculative_inlining,
@@ -560,10 +748,10 @@
 
         // Inlining (mutates the flow graph)
         if (FLAG_use_inlining) {
-          TimelineDurationScope tds2(thread,
+          TimelineDurationScope tds2(thread(),
                                      compiler_timeline,
                                      "Inlining");
-          CSTAT_TIMER_SCOPE(thread, graphinliner_timer);
+          CSTAT_TIMER_SCOPE(thread(), graphinliner_timer);
           // Propagate types to create more inlining opportunities.
           FlowGraphTypePropagator::Propagate(flow_graph);
           DEBUG_ASSERT(flow_graph->VerifyUseLists());
@@ -587,7 +775,7 @@
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
 
         {
-          TimelineDurationScope tds2(thread,
+          TimelineDurationScope tds2(thread(),
                                      compiler_timeline,
                                      "ApplyClassIds");
           // Use propagated class-ids to optimize further.
@@ -609,7 +797,7 @@
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
 
         {
-          TimelineDurationScope tds2(thread,
+          TimelineDurationScope tds2(thread(),
                                      compiler_timeline,
                                      "BranchSimplifier");
           BranchSimplifier::Simplify(flow_graph);
@@ -620,7 +808,7 @@
         }
 
         if (FLAG_constant_propagation) {
-          TimelineDurationScope tds2(thread,
+          TimelineDurationScope tds2(thread(),
                                      compiler_timeline,
                                      "ConstantPropagation");
           ConstantPropagator::Optimize(flow_graph);
@@ -649,7 +837,7 @@
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
 
         {
-          TimelineDurationScope tds2(thread,
+          TimelineDurationScope tds2(thread(),
                                      compiler_timeline,
                                      "SelectRepresentations");
           // Where beneficial convert Smi operations into Int32 operations.
@@ -664,7 +852,7 @@
         }
 
         {
-          TimelineDurationScope tds2(thread,
+          TimelineDurationScope tds2(thread(),
                                      compiler_timeline,
                                      "CommonSubexpressionElinination");
           if (FLAG_common_subexpression_elimination ||
@@ -704,14 +892,14 @@
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
 
         {
-          TimelineDurationScope tds2(thread,
+          TimelineDurationScope tds2(thread(),
                                      compiler_timeline,
                                      "DeadStoreElimination");
           DeadStoreElimination::Optimize(flow_graph);
         }
 
         if (FLAG_range_analysis) {
-          TimelineDurationScope tds2(thread,
+          TimelineDurationScope tds2(thread(),
                                      compiler_timeline,
                                      "RangeAnalysis");
           // Propagate types after store-load-forwarding. Some phis may have
@@ -727,7 +915,7 @@
         }
 
         if (FLAG_constant_propagation) {
-          TimelineDurationScope tds2(thread,
+          TimelineDurationScope tds2(thread(),
                                      compiler_timeline,
                                      "ConstantPropagator::OptimizeBranches");
           // Constant propagation can use information from range analysis to
@@ -743,7 +931,7 @@
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
 
         {
-          TimelineDurationScope tds2(thread,
+          TimelineDurationScope tds2(thread(),
                                      compiler_timeline,
                                      "TryCatchAnalyzer::Optimize");
           // Optimize try-blocks.
@@ -756,7 +944,7 @@
         optimizer.EliminateEnvironments();
 
         {
-          TimelineDurationScope tds2(thread,
+          TimelineDurationScope tds2(thread(),
                                      compiler_timeline,
                                      "EliminateDeadPhis");
           DeadCodeElimination::EliminateDeadPhis(flow_graph);
@@ -772,7 +960,7 @@
         AllocationSinking* sinking = NULL;
         if (FLAG_allocation_sinking &&
             (flow_graph->graph_entry()->SuccessorCount()  == 1)) {
-          TimelineDurationScope tds2(thread,
+          TimelineDurationScope tds2(thread(),
                                      compiler_timeline,
                                      "AllocationSinking::Optimize");
           // TODO(fschneider): Support allocation sinking with try-catch.
@@ -788,7 +976,7 @@
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
 
         {
-          TimelineDurationScope tds2(thread,
+          TimelineDurationScope tds2(thread(),
                                      compiler_timeline,
                                      "SelectRepresentations");
           // Ensure that all phis inserted by optimization passes have
@@ -808,7 +996,7 @@
 
         if (sinking != NULL) {
           TimelineDurationScope tds2(
-              thread,
+              thread(),
               compiler_timeline,
               "AllocationSinking::DetachMaterializations");
           // Remove all MaterializeObject instructions inserted by allocation
@@ -823,7 +1011,7 @@
         FlowGraphInliner::CollectGraphInfo(flow_graph, true);
 
         {
-          TimelineDurationScope tds2(thread,
+          TimelineDurationScope tds2(thread(),
                                      compiler_timeline,
                                      "AllocateRegisters");
           // Perform register allocation on the SSA graph.
@@ -832,7 +1020,7 @@
         }
 
         if (reorder_blocks) {
-          TimelineDurationScope tds(thread,
+          TimelineDurationScope tds(thread(),
                                     compiler_timeline,
                                     "BlockScheduler::ReorderBlocks");
           block_scheduler.ReorderBlocks();
@@ -846,168 +1034,48 @@
       ASSERT(inline_id_to_function.length() == caller_inline_id.length());
       Assembler assembler(use_far_branches);
       FlowGraphCompiler graph_compiler(&assembler, flow_graph,
-                                       *parsed_function, optimized,
+                                       *parsed_function(), optimized(),
                                        inline_id_to_function,
                                        caller_inline_id);
       {
-        CSTAT_TIMER_SCOPE(thread, graphcompiler_timer);
-        TimelineDurationScope tds(thread,
+        CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer);
+        TimelineDurationScope tds(thread(),
                                   compiler_timeline,
                                   "CompileGraph");
         graph_compiler.CompileGraph();
         pipeline->FinalizeCompilation();
       }
       {
-        TimelineDurationScope tds(thread,
+        TimelineDurationScope tds(thread(),
                                   compiler_timeline,
                                   "FinalizeCompilation");
         // This part of compilation must be at a safepoint.
-        if (!Thread::Current()->IsMutatorThread()) {
+        if (!thread()->IsMutatorThread()) {
           // Stop mutator thread before creating the instruction object and
           // installing code.
           // Mutator thread may not run code while we are creating the
           // instruction object, since the creation of instruction object
           // changes code page access permissions (makes them temporary not
           // executable).
-          isolate->thread_registry()->SafepointThreads();
+          isolate()->thread_registry()->SafepointThreads();
         }
-        CSTAT_TIMER_SCOPE(thread, codefinalizer_timer);
-        // CreateDeoptInfo uses the object pool and needs to be done before
-        // FinalizeCode.
-        const Array& deopt_info_array =
-            Array::Handle(zone, graph_compiler.CreateDeoptInfo(&assembler));
-        INC_STAT(thread, total_code_size,
-                 deopt_info_array.Length() * sizeof(uword));
-        // Allocates instruction object. Since this occurs only at safepoint,
-        // there can be no concurrent access to the instruction page.
-        const Code& code = Code::Handle(
-            Code::FinalizeCode(function, &assembler, optimized));
-        code.set_is_optimized(optimized);
-        code.set_owner(function);
 
-        const Array& intervals = graph_compiler.inlined_code_intervals();
-        INC_STAT(thread, total_code_size,
-                 intervals.Length() * sizeof(uword));
-        code.SetInlinedIntervals(intervals);
+        FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
 
-        const Array& inlined_id_array =
-            Array::Handle(zone, graph_compiler.InliningIdToFunction());
-        INC_STAT(thread, total_code_size,
-                 inlined_id_array.Length() * sizeof(uword));
-        code.SetInlinedIdToFunction(inlined_id_array);
-
-        const Array& caller_inlining_id_map_array =
-            Array::Handle(zone, graph_compiler.CallerInliningIdMap());
-        INC_STAT(thread, total_code_size,
-                 caller_inlining_id_map_array.Length() * sizeof(uword));
-        code.SetInlinedCallerIdMap(caller_inlining_id_map_array);
-
-        graph_compiler.FinalizePcDescriptors(code);
-        code.set_deopt_info_array(deopt_info_array);
-
-        graph_compiler.FinalizeStackmaps(code);
-        graph_compiler.FinalizeVarDescriptors(code);
-        graph_compiler.FinalizeExceptionHandlers(code);
-        graph_compiler.FinalizeStaticCallTargetsTable(code);
-
-        if (optimized) {
-          // Installs code while at safepoint.
-          if (thread->IsMutatorThread()) {
-            const bool is_osr = osr_id != Compiler::kNoOSRDeoptId;
-            function.InstallOptimizedCode(code, is_osr);
-          } else {
-            // Background compilation.
-            // Before installing code check generation counts if the code may
-            // have become invalid.
-            bool code_is_valid = true;
-            if (!thread->cha()->leaf_classes().is_empty()) {
-              if (cha_invalidation_gen_at_start !=
-                  isolate->cha_invalidation_gen()) {
-                code_is_valid = false;
-              }
-            }
-            if (!flow_graph->guarded_fields()->is_empty()) {
-              if (field_invalidation_gen_at_start !=
-                  isolate->field_invalidation_gen()) {
-                code_is_valid = false;
-              }
-            }
-            if (parsed_function->HasDeferredPrefixes()) {
-              if (prefix_invalidation_gen_at_start !=
-                  isolate->prefix_invalidation_gen()) {
-                code_is_valid = false;
-              }
-            }
-            if (code_is_valid) {
-              const bool is_osr = osr_id != Compiler::kNoOSRDeoptId;
-              ASSERT(!is_osr);  // OSR is compiled in background.
-              function.InstallOptimizedCode(code, is_osr);
-            }
-            if (function.usage_counter() < 0) {
-              // Reset to 0 so that it can be recompiled if needed.
-              function.set_usage_counter(0);
-            }
-          }
-
-          // Register code with the classes it depends on because of CHA and
-          // fields it depends on because of store guards, unless we cannot
-          // deopt.
-          if (Compiler::allow_recompilation()) {
-            // Deoptimize field dependent code first, before registering
-            // this yet uninstalled code as dependent on a field.
-            // TODO(srdjan): Debugging dart2js crashes;
-            // FlowGraphOptimizer::VisitStoreInstanceField populates
-            // deoptimize_dependent_code() list, currently disabled.
-            for (intptr_t i = 0;
-                 i < flow_graph->deoptimize_dependent_code().length();
-                 i++) {
-              const Field* field = flow_graph->deoptimize_dependent_code()[i];
-              field->DeoptimizeDependentCode();
-            }
-            for (intptr_t i = 0;
-                 i < thread->cha()->leaf_classes().length();
-                 ++i) {
-              thread->cha()->leaf_classes()[i]->RegisterCHACode(code);
-            }
-            for (intptr_t i = 0;
-                 i < flow_graph->guarded_fields()->length();
-                 i++) {
-              const Field* field = (*flow_graph->guarded_fields())[i];
-              field->RegisterDependentCode(code);
-            }
-          }
-        } else {  // not optimized.
-          if (!Compiler::always_optimize() &&
-              (function.ic_data_array() == Array::null())) {
-            function.SaveICDataMap(
-                graph_compiler.deopt_id_to_ic_data(),
-                Array::Handle(zone, graph_compiler.edge_counters_array()));
-          }
-          function.set_unoptimized_code(code);
-          function.AttachCode(code);
-        }
-        if (parsed_function->HasDeferredPrefixes()) {
-          ASSERT(!FLAG_load_deferred_eagerly);
-          ZoneGrowableArray<const LibraryPrefix*>* prefixes =
-              parsed_function->deferred_prefixes();
-          for (intptr_t i = 0; i < prefixes->length(); i++) {
-            (*prefixes)[i]->RegisterDependentCode(code);
-          }
-        }
-        if (!Thread::Current()->IsMutatorThread()) {
+        if (!thread()->IsMutatorThread()) {
           // Background compilation.
-          isolate->thread_registry()->ResumeAllThreads();
+          isolate()->thread_registry()->ResumeAllThreads();
         }
       }
       // Mark that this isolate now has compiled code.
-      isolate->set_has_compiled_code(true);
+      isolate()->set_has_compiled_code(true);
       // Exit the loop and the function with the correct result value.
       is_compiled = true;
       done = true;
     } else {
       // We bailed out or we encountered an error.
       const Error& error = Error::Handle(
-          isolate->object_store()->sticky_error());
+          isolate()->object_store()->sticky_error());
 
       if (error.raw() == Object::branch_offset_error().raw()) {
         // Compilation failed due to an out of range branch offset in the
@@ -1030,7 +1098,7 @@
         const intptr_t max_attempts = FLAG_max_speculative_inlining_attempts;
         if (inlining_black_list.length() >= max_attempts) {
           use_speculative_inlining = false;
-          if (FLAG_trace_compiler) {
+          if (FLAG_trace_compiler || FLAG_trace_optimizing_compiler) {
             THR_Print("Disabled speculative inlining after %" Pd " attempts.\n",
                       inlining_black_list.length());
           }
@@ -1048,12 +1116,12 @@
       // Clear the error if it was not a real error, but just a bailout.
       if (error.IsLanguageError() &&
           (LanguageError::Cast(error).kind() == Report::kBailout)) {
-        isolate->object_store()->clear_sticky_error();
+        isolate()->object_store()->clear_sticky_error();
       }
       is_compiled = false;
     }
     // Reset global isolate state.
-    thread->set_deopt_id(prev_deopt_id);
+    thread()->set_deopt_id(prev_deopt_id);
   }
   return is_compiled;
 }
@@ -1235,12 +1303,15 @@
     Isolate* const isolate = thread->isolate();
     StackZone stack_zone(thread);
     Zone* const zone = stack_zone.GetZone();
-    Timer per_compile_timer(FLAG_trace_compiler, "Compilation time");
+    const bool trace_compiler =
+        FLAG_trace_compiler ||
+        (FLAG_trace_optimizing_compiler && optimized);
+    Timer per_compile_timer(trace_compiler, "Compilation time");
     per_compile_timer.Start();
 
     ParsedFunction* parsed_function = new(zone) ParsedFunction(
         thread, Function::ZoneHandle(zone, function.raw()));
-    if (FLAG_trace_compiler) {
+    if (trace_compiler) {
       THR_Print("Compiling %s%sfunction: '%s' @ token %" Pd ", size %" Pd "\n",
                 (osr_id == Compiler::kNoOSRDeoptId ? "" : "osr "),
                 (optimized ? "optimized " : ""),
@@ -1262,15 +1333,13 @@
                num_tokens_after - num_tokens_before);
     }
 
-    const bool success = CompileParsedFunctionHelper(pipeline,
-                                                     parsed_function,
-                                                     optimized,
-                                                     osr_id);
+    CompileParsedFunctionHelper helper(parsed_function, optimized, osr_id);
+    const bool success = helper.Compile(pipeline);
     if (!success) {
       if (optimized) {
         ASSERT(!Compiler::always_optimize());  // Optimized is the only code.
         // Optimizer bailed out. Disable optimizations and never try again.
-        if (FLAG_trace_compiler) {
+        if (trace_compiler) {
           THR_Print("--> disabling optimizations for '%s'\n",
                     function.ToFullyQualifiedCString());
         } else if (FLAG_trace_failed_optimization_attempts) {
@@ -1291,7 +1360,7 @@
 
     per_compile_timer.Stop();
 
-    if (FLAG_trace_compiler) {
+    if (trace_compiler && success) {
       THR_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n",
                 function.ToFullyQualifiedCString(),
                 Code::Handle(function.CurrentCode()).EntryPoint(),
@@ -1421,10 +1490,8 @@
   if (setjmp(*jump.Set()) == 0) {
     // Non-optimized code generator.
     DartCompilationPipeline pipeline;
-    CompileParsedFunctionHelper(&pipeline,
-                                parsed_function,
-                                false,
-                                kNoOSRDeoptId);
+    CompileParsedFunctionHelper helper(parsed_function, false, kNoOSRDeoptId);
+    helper.Compile(&pipeline);
     if (FLAG_disassemble) {
       DisassembleCode(parsed_function->function(), false);
     }
@@ -1509,11 +1576,8 @@
   parsed_function->AllocateVariables();
   // Non-optimized code generator.
   DartCompilationPipeline pipeline;
-  CompileParsedFunctionHelper(&pipeline,
-                              parsed_function,
-                              false,  // optimized
-                              kNoOSRDeoptId);
-
+  CompileParsedFunctionHelper helper(parsed_function, false, kNoOSRDeoptId);
+  helper.Compile(&pipeline);
   const Function& initializer = parsed_function->function();
   field.SetPrecompiledInitializer(initializer);
 }
@@ -1540,10 +1604,8 @@
       parsed_function->AllocateVariables();
       // Non-optimized code generator.
       DartCompilationPipeline pipeline;
-      CompileParsedFunctionHelper(&pipeline,
-                                  parsed_function,
-                                  false,  // optimized
-                                  kNoOSRDeoptId);
+      CompileParsedFunctionHelper helper(parsed_function, false, kNoOSRDeoptId);
+      helper.Compile(&pipeline);
       initializer = parsed_function->function().raw();
       Code::Handle(initializer.unoptimized_code()).set_var_descriptors(
           Object::empty_var_descriptors());
@@ -1610,10 +1672,8 @@
 
     // Non-optimized code generator.
     DartCompilationPipeline pipeline;
-    CompileParsedFunctionHelper(&pipeline,
-                                parsed_function,
-                                false,
-                                kNoOSRDeoptId);
+    CompileParsedFunctionHelper helper(parsed_function, false, kNoOSRDeoptId);
+    helper.Compile(&pipeline);
     Code::Handle(func.unoptimized_code()).set_var_descriptors(
         Object::empty_var_descriptors());
 
@@ -1754,7 +1814,8 @@
   while (running_) {
     // Maybe something is already in the queue, check first before waiting
     // to be notified.
-    Thread::EnterIsolateAsHelper(isolate_);
+    bool result = Thread::EnterIsolateAsHelper(isolate_);
+    ASSERT(result);
     {
       Thread* thread = Thread::Current();
       StackZone stack_zone(thread);
diff --git a/runtime/vm/constant_propagator.cc b/runtime/vm/constant_propagator.cc
index 1b70c96..8792cf5 100644
--- a/runtime/vm/constant_propagator.cc
+++ b/runtime/vm/constant_propagator.cc
@@ -764,8 +764,7 @@
     if (value.IsInstance()) {
       const Instance& instance = Instance::Cast(value);
       const AbstractType& checked_type = instr->type();
-      if (instr->instantiator()->BindsToConstantNull() &&
-          instr->instantiator_type_arguments()->BindsToConstantNull()) {
+      if (instr->instantiator_type_arguments()->BindsToConstantNull()) {
         const TypeArguments& checked_type_arguments = TypeArguments::Handle();
         Error& bound_error = Error::Handle();
         bool is_instance = instance.IsInstanceOf(checked_type,
diff --git a/runtime/vm/coverage.cc b/runtime/vm/coverage.cc
index 8fede58..42dff5e 100644
--- a/runtime/vm/coverage.cc
+++ b/runtime/vm/coverage.cc
@@ -191,6 +191,7 @@
     }
   }
 
+  // TODO(turnidge): This looks like it prints closures many, many times.
   const GrowableObjectArray& closures = GrowableObjectArray::Handle(
       thread->isolate()->object_store()->closure_functions());
   pos_to_line.Clear();
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 7568924..a9ddae5 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -38,7 +38,7 @@
 DECLARE_FLAG(bool, trace_time_all);
 DEFINE_FLAG(bool, keep_code, false,
             "Keep deoptimized code for profiling.");
-DEFINE_FLAG(bool, shutdown, false, "Do a clean shutdown of the VM");
+DEFINE_FLAG(bool, shutdown, true, "Do a clean shutdown of the VM");
 
 Isolate* Dart::vm_isolate_ = NULL;
 ThreadPool* Dart::thread_pool_ = NULL;
@@ -228,7 +228,8 @@
   {
     // Set the VM isolate as current isolate when shutting down
     // Metrics so that we can use a StackZone.
-    Thread::EnterIsolate(vm_isolate_);
+    bool result = Thread::EnterIsolate(vm_isolate_);
+    ASSERT(result);
     Metric::Cleanup();
     Thread::ExitIsolate();
   }
@@ -251,8 +252,17 @@
     delete thread_pool_;
     thread_pool_ = NULL;
 
+    // Disable creation of any new OSThread structures which means no more new
+    // threads can do an EnterIsolate. This must come after isolate shutdown
+    // because new threads may need to be spawned to shutdown the isolates.
+    // This must come after deletion of the thread pool to avoid a race in which
+    // a thread spawned by the thread pool does not exit through the thread
+    // pool, messing up its bookkeeping.
+    OSThread::DisableOSThreadCreation();
+
     // Set the VM isolate as current isolate.
-    Thread::EnterIsolate(vm_isolate_);
+    bool result = Thread::EnterIsolate(vm_isolate_);
+    ASSERT(result);
 
     ShutdownIsolate();
     vm_isolate_ = NULL;
@@ -270,6 +280,9 @@
   } else {
     // Shutdown the service isolate.
     ServiceIsolate::Shutdown();
+
+    // Disable thread creation.
+    OSThread::DisableOSThreadCreation();
   }
 
   CodeObservers::DeleteAll();
@@ -407,7 +420,8 @@
 void Dart::ShutdownIsolate(Isolate* isolate) {
   ASSERT(Isolate::Current() == NULL);
   // We need to enter the isolate in order to shut it down.
-  Thread::EnterIsolate(isolate);
+  bool result = Thread::EnterIsolate(isolate);
+  ASSERT(result);
   ShutdownIsolate();
   // Since the isolate is shutdown and deleted, there is no need to
   // exit the isolate here.
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index a61715b..fdb1d53 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1311,7 +1311,9 @@
   if (iso->HasMutatorThread()) {
     FATAL("Multiple mutators within one isolate is not supported.");
   }
-  Thread::EnterIsolate(iso);
+  if (!Thread::EnterIsolate(iso)) {
+    FATAL("Unable to Enter Isolate as Dart VM is shutting down");
+  }
 }
 
 
@@ -1527,7 +1529,9 @@
     while (!data.done) {
       ml.Wait();
     }
-    Thread::EnterIsolate(I);
+    if (!Thread::EnterIsolate(I)) {
+      FATAL("Inconsistent state, VM shutting down while in run loop.");
+    }
   }
   if (I->object_store()->sticky_error() != Object::null()) {
     Dart_Handle error = Api::NewHandle(T, I->object_store()->sticky_error());
@@ -5970,4 +5974,9 @@
   return Api::Success();
 }
 
+
+DART_EXPORT bool Dart_IsRunningPrecompiledCode() {
+  return Dart::IsRunningPrecompiledCode();
+}
+
 }  // namespace dart
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index a9efd83..9ba75da 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -1444,7 +1444,8 @@
                        DeoptContext::kDestIsAllocated,
                        NULL,
                        NULL,
-                       true);
+                       true,
+                       false /* deoptimizing_code */);
   isolate->set_deopt_context(deopt_context);
 
   deopt_context->FillDestFrame();
diff --git a/runtime/vm/deferred_objects.cc b/runtime/vm/deferred_objects.cc
index 3d86592..71a734a 100644
--- a/runtime/vm/deferred_objects.cc
+++ b/runtime/vm/deferred_objects.cc
@@ -173,16 +173,18 @@
   *reinterpret_cast<RawObject**>(dest_addr) = code.raw();
 
   if (FLAG_trace_deoptimization_verbose) {
-    OS::PrintErr("materializing pc marker at 0x%" Px ": %s, %s\n",
-                 reinterpret_cast<uword>(slot()), code.ToCString(),
-                 function.ToCString());
+    THR_Print("materializing pc marker at 0x%" Px ": %s, %s\n",
+        reinterpret_cast<uword>(slot()), code.ToCString(),
+        function.ToCString());
   }
 
   // Increment the deoptimization counter. This effectively increments each
   // function occurring in the optimized frame.
-  function.set_deoptimization_counter(function.deoptimization_counter() + 1);
+  if (deopt_context->deoptimizing_code()) {
+    function.set_deoptimization_counter(function.deoptimization_counter() + 1);
+  }
   if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
-    OS::PrintErr("Deoptimizing %s (count %d)\n",
+    THR_Print("Deoptimizing '%s' (count %d)\n",
         function.ToFullyQualifiedCString(),
         function.deoptimization_counter());
   }
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 658e973..4970e59 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -27,7 +27,8 @@
                            DestFrameOptions dest_options,
                            fpu_register_t* fpu_registers,
                            intptr_t* cpu_registers,
-                           bool is_lazy_deopt)
+                           bool is_lazy_deopt,
+                           bool deoptimizing_code)
     : code_(code.raw()),
       object_pool_(code.GetObjectPool()),
       deopt_info_(TypedData::null()),
@@ -47,7 +48,8 @@
       deferred_slots_(NULL),
       deferred_objects_count_(0),
       deferred_objects_(NULL),
-      is_lazy_deopt_(is_lazy_deopt) {
+      is_lazy_deopt_(is_lazy_deopt),
+      deoptimizing_code_(deoptimizing_code) {
   const TypedData& deopt_info = TypedData::Handle(
       code.GetDeoptInfoAtPc(frame->pc(), &deopt_reason_, &deopt_flags_));
   ASSERT(!deopt_info.IsNull());
@@ -103,7 +105,7 @@
   }
 
   if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
-    OS::PrintErr(
+    THR_Print(
         "Deoptimizing (reason %d '%s') at pc %#" Px " '%s' (count %d)\n",
         deopt_reason(),
         DeoptReasonToCString(deopt_reason()),
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index 79c206e..acbf92b 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -23,6 +23,7 @@
 class TimelineEvent;
 
 // Holds all data relevant for execution of deoptimization instructions.
+// Structure is allocated in C-heap.
 class DeoptContext {
  public:
   enum DestFrameOptions {
@@ -30,12 +31,14 @@
     kDestIsAllocated        // Write deopt frame to a buffer.
   };
 
+  // If 'deoptimizing_code' is false, only frame is being deoptimized.
   DeoptContext(const StackFrame* frame,
                const Code& code,
                DestFrameOptions dest_options,
                fpu_register_t* fpu_registers,
                intptr_t* cpu_registers,
-               bool is_lazy_deopt);
+               bool is_lazy_deopt,
+               bool deoptimizing_code);
   virtual ~DeoptContext();
 
   // Returns the offset of the dest fp from the dest sp.  Used in
@@ -97,6 +100,8 @@
 
   bool is_lazy_deopt() const { return is_lazy_deopt_; }
 
+  bool deoptimizing_code() const { return deoptimizing_code_; }
+
   ICData::DeoptReasonId deopt_reason() const { return deopt_reason_; }
   bool HasDeoptFlag(ICData::DeoptFlags flag) {
     return (deopt_flags_ & flag) != 0;
@@ -232,6 +237,7 @@
   DeferredObject** deferred_objects_;
 
   const bool is_lazy_deopt_;
+  const bool deoptimizing_code_;
 
   DISALLOW_COPY_AND_ASSIGN(DeoptContext);
 };
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 82bc544..99563bb 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -624,10 +624,6 @@
       library = Library::IsolateLibrary();
       class_name = &Symbols::IsolateSpawnException();
       break;
-    case kIsolateUnhandledException:
-      library = Library::IsolateLibrary();
-      class_name = &Symbols::IsolateUnhandledException();
-      break;
     case kJavascriptIntegerOverflowError:
       library = Library::CoreLibrary();
       class_name = &Symbols::JavascriptIntegerOverflowError();
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index 0bd97f8..4282bb5 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -60,7 +60,6 @@
     kOutOfMemory,
     kNullThrown,
     kIsolateSpawn,
-    kIsolateUnhandledException,
     kJavascriptIntegerOverflowError,
     kJavascriptCompatibilityError,
     kAssertion,
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 57b5d65..fc3264f 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -1469,7 +1469,6 @@
 
 void EffectGraphVisitor::BuildTypecheckPushArguments(
     intptr_t token_pos,
-    PushArgumentInstr** push_instantiator_result,
     PushArgumentInstr** push_instantiator_type_arguments_result) {
   const Class& instantiator_class = Class::Handle(
       Z, owner()->function().Owner());
@@ -1479,15 +1478,11 @@
   Value* instantiator = BuildInstantiator(instantiator_class);
   if (instantiator == NULL) {
     // No instantiator when inside factory.
-    *push_instantiator_result = PushArgument(BuildNullValue());
     instantiator_type_arguments =
         BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL);
   } else {
-    instantiator = Bind(BuildStoreExprTemp(instantiator));
-    *push_instantiator_result = PushArgument(instantiator);
-    Value* loaded = Bind(BuildLoadExprTemp());
-    instantiator_type_arguments =
-        BuildInstantiatorTypeArguments(token_pos, instantiator_class, loaded);
+    instantiator_type_arguments = BuildInstantiatorTypeArguments(
+        token_pos, instantiator_class, instantiator);
   }
   *push_instantiator_type_arguments_result =
       PushArgument(instantiator_type_arguments);
@@ -1497,7 +1492,6 @@
 
 void EffectGraphVisitor::BuildTypecheckArguments(
     intptr_t token_pos,
-    Value** instantiator_result,
     Value** instantiator_type_arguments_result) {
   Value* instantiator = NULL;
   Value* instantiator_type_arguments = NULL;
@@ -1508,17 +1502,12 @@
   instantiator = BuildInstantiator(instantiator_class);
   if (instantiator == NULL) {
     // No instantiator when inside factory.
-    instantiator = BuildNullValue();
     instantiator_type_arguments =
         BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL);
   } else {
-    // Preserve instantiator.
-    instantiator = Bind(BuildStoreExprTemp(instantiator));
-    Value* loaded = Bind(BuildLoadExprTemp());
-    instantiator_type_arguments =
-        BuildInstantiatorTypeArguments(token_pos, instantiator_class, loaded);
+    instantiator_type_arguments = BuildInstantiatorTypeArguments(
+        token_pos, instantiator_class, instantiator);
   }
-  *instantiator_result = instantiator;
   *instantiator_type_arguments_result = instantiator_type_arguments;
 }
 
@@ -1535,21 +1524,16 @@
     const AbstractType& dst_type,
     const String& dst_name) {
   // Build the type check computation.
-  Value* instantiator = NULL;
   Value* instantiator_type_arguments = NULL;
   if (dst_type.IsInstantiated()) {
-    instantiator = BuildNullValue();
     instantiator_type_arguments = BuildNullValue();
   } else {
-    BuildTypecheckArguments(token_pos,
-                            &instantiator,
-                            &instantiator_type_arguments);
+    BuildTypecheckArguments(token_pos, &instantiator_type_arguments);
   }
 
   const intptr_t deopt_id = Thread::Current()->GetNextDeoptId();
   return new(Z) AssertAssignableInstr(token_pos,
                                       value,
-                                      instantiator,
                                       instantiator_type_arguments,
                                       dst_type,
                                       dst_name,
@@ -1651,20 +1635,15 @@
   }
 
   PushArgumentInstr* push_left = PushArgument(for_left_value.value());
-  PushArgumentInstr* push_instantiator = NULL;
   PushArgumentInstr* push_type_args = NULL;
   if (type.IsInstantiated()) {
-    push_instantiator = PushArgument(BuildNullValue());
     push_type_args = PushArgument(BuildNullValue());
   } else {
-    BuildTypecheckPushArguments(node->token_pos(),
-                                &push_instantiator,
-                                &push_type_args);
+    BuildTypecheckPushArguments(node->token_pos(), &push_type_args);
   }
   ZoneGrowableArray<PushArgumentInstr*>* arguments =
-      new(Z) ZoneGrowableArray<PushArgumentInstr*>(5);
+      new(Z) ZoneGrowableArray<PushArgumentInstr*>(4);
   arguments->Add(push_left);
-  arguments->Add(push_instantiator);
   arguments->Add(push_type_args);
   ASSERT(!node->right()->AsTypeNode()->type().IsNull());
   Value* type_const = Bind(new(Z) ConstantInstr(type));
@@ -1708,20 +1687,15 @@
     }
   }
   PushArgumentInstr* push_left = PushArgument(for_value.value());
-  PushArgumentInstr* push_instantiator = NULL;
   PushArgumentInstr* push_type_args = NULL;
   if (type.IsInstantiated()) {
-    push_instantiator = PushArgument(BuildNullValue());
     push_type_args = PushArgument(BuildNullValue());
   } else {
-    BuildTypecheckPushArguments(node->token_pos(),
-                                &push_instantiator,
-                                &push_type_args);
+    BuildTypecheckPushArguments(node->token_pos(), &push_type_args);
   }
   ZoneGrowableArray<PushArgumentInstr*>* arguments =
-      new(Z) ZoneGrowableArray<PushArgumentInstr*>(4);
+      new(Z) ZoneGrowableArray<PushArgumentInstr*>(3);
   arguments->Add(push_left);
-  arguments->Add(push_instantiator);
   arguments->Add(push_type_args);
   Value* type_arg = Bind(new(Z) ConstantInstr(type));
   arguments->Add(PushArgument(type_arg));
@@ -1749,10 +1723,10 @@
   right->Visit(&for_right_value);
   Append(for_right_value);
   StrictCompareInstr* comp = new(Z) StrictCompareInstr(token_pos,
-                                                    kind,
-                                                    for_left_value.value(),
-                                                    for_right_value.value(),
-                                                    true);  // Number check.
+                                                       kind,
+                                                       for_left_value.value(),
+                                                       for_right_value.value(),
+                                                       true);  // Number check.
   return comp;
 }
 
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index bae0a52..5511db4 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -332,10 +332,8 @@
 
   void BuildTypecheckPushArguments(
       intptr_t token_pos,
-      PushArgumentInstr** push_instantiator,
       PushArgumentInstr** push_instantiator_type_arguments);
   void BuildTypecheckArguments(intptr_t token_pos,
-                               Value** instantiator,
                                Value** instantiator_type_arguments);
   Value* BuildInstantiator(const Class& instantiator_class);
   Value* BuildInstantiatorTypeArguments(intptr_t token_pos,
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 8c6fa8e..da0639c 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -49,6 +49,7 @@
 
 DECLARE_FLAG(bool, background_compilation);
 DECLARE_FLAG(bool, code_comments);
+DECLARE_FLAG(bool, collect_dynamic_function_names);
 DECLARE_FLAG(bool, deoptimize_alot);
 DECLARE_FLAG(int, deoptimize_every);
 DECLARE_FLAG(charp, deoptimize_filter);
@@ -77,6 +78,12 @@
 DECLARE_FLAG(bool, enable_mirrors);
 DECLARE_FLAG(bool, link_natives_lazily);
 DECLARE_FLAG(bool, trace_compiler);
+DECLARE_FLAG(int, inlining_hotness);
+DECLARE_FLAG(int, inlining_size_threshold);
+DECLARE_FLAG(int, inlining_callee_size_threshold);
+DECLARE_FLAG(int, inline_getters_setters_smaller_than);
+DECLARE_FLAG(int, inlining_depth_threshold);
+DECLARE_FLAG(int, inlining_caller_size_threshold);
 
 bool FLAG_precompilation = false;
 static void PrecompilationModeHandler(bool value) {
@@ -117,9 +124,21 @@
     FLAG_fields_may_be_reset = true;
     FLAG_allow_absolute_addresses = false;
 
+    // There is no counter feedback in precompilation, so ignore the counter
+    // when making inlining decisions.
+    FLAG_inlining_hotness = 0;
+    // Use smaller thresholds in precompilation as we are compiling everything
+    // with the optimizing compiler instead of only hot functions.
+    FLAG_inlining_size_threshold = 5;
+    FLAG_inline_getters_setters_smaller_than = 5;
+    FLAG_inlining_callee_size_threshold = 20;
+    FLAG_inlining_depth_threshold = 2;
+    FLAG_inlining_caller_size_threshold = 1000;
+
     // Background compilation relies on two-stage compilation pipeline,
     // while precompilation has only one.
     FLAG_background_compilation = false;
+    FLAG_collect_dynamic_function_names = true;
   }
 }
 
@@ -1118,7 +1137,8 @@
     intptr_t token_pos,
     intptr_t argument_count,
     LocationSummary* locs,
-    const ICData& ic_data) {
+    const ICData& ic_data_in) {
+  const ICData& ic_data = ICData::ZoneHandle(ic_data_in.Original());
   if (Compiler::always_optimize()) {
     EmitSwitchableInstanceCall(ic_data, argument_count,
                                deopt_id, token_pos, locs);
@@ -1185,7 +1205,8 @@
                                            intptr_t argument_count,
                                            const Array& argument_names,
                                            LocationSummary* locs,
-                                           const ICData& ic_data) {
+                                           const ICData& ic_data_in) {
+  const ICData& ic_data = ICData::ZoneHandle(ic_data_in.Original());
   const Array& arguments_descriptor = Array::ZoneHandle(
       ic_data.IsNull() ? ArgumentsDescriptor::New(argument_count,
                                                   argument_names)
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 1d18f03..0254855 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -462,7 +462,7 @@
   // Skip check if destination is a dynamic type.
   if (type.IsTypeParameter()) {
     const TypeParameter& type_param = TypeParameter::Cast(type);
-    // Load instantiator (or null) and instantiator type arguments on stack.
+    // Load instantiator type arguments on stack.
     __ ldr(R1, Address(SP, 0));  // Get instantiator type arguments.
     // R1: instantiator type arguments.
     // Check if type arguments are null, i.e. equivalent to vector of dynamic.
@@ -587,7 +587,6 @@
 // Inputs:
 // - R0: object.
 // - R1: instantiator type arguments or raw_null.
-// - R2: instantiator or raw_null.
 // Returns:
 // - true or false in R0.
 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
@@ -597,8 +596,8 @@
                                            LocationSummary* locs) {
   ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded());
 
-  // Preserve instantiator (R2) and its type arguments (R1).
-  __ PushList((1 << R1) | (1 << R2));
+  // Preserve instantiator type arguments (R1).
+  __ Push(R1);
 
   Label is_instance, is_not_instance;
   // If type is instantiated and non-parameterized, we can inline code
@@ -624,19 +623,18 @@
   Label done;
   if (!test_cache.IsNull()) {
     // Generate runtime call.
-    // Load instantiator (R2) and its type arguments (R1).
-    __ ldm(IA, SP,  (1 << R1) | (1 << R2));
+    // Load instantiator type arguments (R1).
+    __ ldr(R1, Address(SP, 0 * kWordSize));
     __ PushObject(Object::null_object());  // Make room for the result.
     __ Push(R0);  // Push the instance.
     __ PushObject(type);  // Push the type.
-    // Push instantiator (R2) and its type arguments (R1).
-    __ PushList((1 << R1) | (1 << R2));
+    __ Push(R1);  // Push instantiator type arguments (R1).
     __ LoadUniqueObject(R0, test_cache);
     __ Push(R0);
-    GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
+    GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 4, locs);
     // Pop the parameters supplied to the runtime entry. The result of the
     // instanceof runtime call will be left as the result of the operation.
-    __ Drop(5);
+    __ Drop(4);
     if (negate_result) {
       __ Pop(R1);
       __ LoadObject(R0, Bool::True());
@@ -655,8 +653,8 @@
   __ Bind(&is_instance);
   __ LoadObject(R0, Bool::Get(!negate_result));
   __ Bind(&done);
-  // Remove instantiator (R2) and its type arguments (R1).
-  __ Drop(2);
+  // Remove instantiator type arguments (R1).
+  __ Drop(1);
 }
 
 
@@ -667,7 +665,6 @@
 // Inputs:
 // - R0: instance being type checked.
 // - R1: instantiator type arguments or raw_null.
-// - R2: instantiator or raw_null.
 // Returns:
 // - object in R0 for successful assignable check (or throws TypeError).
 // Performance notes: positive checks must be quick, negative checks can be slow
@@ -683,8 +680,8 @@
   // Assignable check is skipped in FlowGraphBuilder, not here.
   ASSERT(dst_type.IsMalformedOrMalbounded() ||
          (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
-  // Preserve instantiator (R2) and its type arguments (R1).
-  __ PushList((1 << R1) | (1 << R2));
+  // Preserve instantiator type arguments (R1).
+  __ Push(R1);
   // A null object is always assignable and is returned as result.
   Label is_assignable, runtime_call;
   __ CompareObject(R0, Object::null_object());
@@ -705,8 +702,8 @@
     __ bkpt(0);
 
     __ Bind(&is_assignable);  // For a null object.
-    // Restore instantiator (R2) and its type arguments (R1).
-    __ PopList((1 << R1) | (1 << R2));
+    // Restore instantiator type arguments (R1).
+    __ Pop(R1);
     return;
   }
 
@@ -716,25 +713,24 @@
                                         &is_assignable, &runtime_call);
 
   __ Bind(&runtime_call);
-  // Load instantiator (R2) and its type arguments (R1).
-  __ ldm(IA, SP,  (1 << R1) | (1 << R2));
+  // Load instantiator type arguments (R1).
+  __ ldr(R1, Address(SP, 0 * kWordSize));
   __ PushObject(Object::null_object());  // Make room for the result.
   __ Push(R0);  // Push the source object.
   __ PushObject(dst_type);  // Push the type of the destination.
-  // Push instantiator (R2) and its type arguments (R1).
-  __ PushList((1 << R1) | (1 << R2));
+  __ Push(R1);  // Push instantiator type arguments (R1).
   __ PushObject(dst_name);  // Push the name of the destination.
   __ LoadUniqueObject(R0, test_cache);
   __ Push(R0);
-  GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
+  GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 5, locs);
   // Pop the parameters supplied to the runtime entry. The result of the
   // type check runtime call is the checked value.
-  __ Drop(6);
+  __ Drop(5);
   __ Pop(R0);
 
   __ Bind(&is_assignable);
-  // Restore instantiator (R2) and its type arguments (R1).
-  __ PopList((1 << R1) | (1 << R2));
+  // Restore instantiator type arguments (R1).
+  __ Pop(R1);
 }
 
 
@@ -987,8 +983,8 @@
   if (CanOptimizeFunction() &&
       function.IsOptimizable() &&
       (!is_optimizing() || may_reoptimize())) {
+    __ Comment("Invocation Count Check");
     const Register function_reg = R8;
-
     // The pool pointer is not setup before entering the Dart frame.
     // Temporarily setup pool pointer for this dart function.
     __ LoadPoolPointer(new_pp);
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index 44f1463..d8283b1 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -454,7 +454,7 @@
   // Skip check if destination is a dynamic type.
   if (type.IsTypeParameter()) {
     const TypeParameter& type_param = TypeParameter::Cast(type);
-    // Load instantiator (or null) and instantiator type arguments on stack.
+    // Load instantiator type arguments on stack.
     __ ldr(R1, Address(SP));  // Get instantiator type arguments.
     // R1: instantiator type arguments.
     // Check if type arguments are null, i.e. equivalent to vector of dynamic.
@@ -579,7 +579,6 @@
 // Inputs:
 // - R0: object.
 // - R1: instantiator type arguments or raw_null.
-// - R2: instantiator or raw_null.
 // Returns:
 // - true or false in R0.
 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
@@ -589,8 +588,7 @@
                                            LocationSummary* locs) {
   ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded());
 
-  // Preserve instantiator (R2) and its type arguments (R1).
-  __ Push(R2);
+  // Preserve instantiator type arguments (R1).
   __ Push(R1);
 
   Label is_instance, is_not_instance;
@@ -619,19 +617,16 @@
     // Generate runtime call.
     // Load instantiator (R2) and its type arguments (R1).
     __ ldr(R1, Address(SP, 0 * kWordSize));
-    __ ldr(R2, Address(SP, 1 * kWordSize));
     __ PushObject(Object::null_object());  // Make room for the result.
     __ Push(R0);  // Push the instance.
     __ PushObject(type);  // Push the type.
-    // Push instantiator (R2) and its type arguments (R1).
-    __ Push(R2);
-    __ Push(R1);
+    __ Push(R1);  // Push instantiator type arguments (R1).
     __ LoadUniqueObject(R0, test_cache);
     __ Push(R0);
-    GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
+    GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 4, locs);
     // Pop the parameters supplied to the runtime entry. The result of the
     // instanceof runtime call will be left as the result of the operation.
-    __ Drop(5);
+    __ Drop(4);
     if (negate_result) {
       __ Pop(R1);
       __ LoadObject(R0, Bool::True());
@@ -650,8 +645,8 @@
   __ Bind(&is_instance);
   __ LoadObject(R0, Bool::Get(!negate_result));
   __ Bind(&done);
-  // Remove instantiator (R2) and its type arguments (R1).
-  __ Drop(2);
+  // Remove instantiator type arguments (R1).
+  __ Drop(1);
 }
 
 
@@ -662,7 +657,6 @@
 // Inputs:
 // - R0: instance being type checked.
 // - R1: instantiator type arguments or raw_null.
-// - R2: instantiator or raw_null.
 // Returns:
 // - object in R0 for successful assignable check (or throws TypeError).
 // Performance notes: positive checks must be quick, negative checks can be slow
@@ -678,8 +672,7 @@
   // Assignable check is skipped in FlowGraphBuilder, not here.
   ASSERT(dst_type.IsMalformedOrMalbounded() ||
          (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
-  // Preserve instantiator (R2) and its type arguments (R1).
-  __ Push(R2);
+  // Preserve instantiator type arguments (R1).
   __ Push(R1);
   // A null object is always assignable and is returned as result.
   Label is_assignable, runtime_call;
@@ -701,9 +694,8 @@
     __ brk(0);
 
     __ Bind(&is_assignable);  // For a null object.
-    // Restore instantiator (R2) and its type arguments (R1).
+    // Restore instantiator type arguments (R1).
     __ Pop(R1);
-    __ Pop(R2);
     return;
   }
 
@@ -713,28 +705,23 @@
                                         &is_assignable, &runtime_call);
 
   __ Bind(&runtime_call);
-  // Load instantiator (R2) and its type arguments (R1).
-  __ ldr(R1, Address(SP));
-  __ ldr(R2, Address(SP, 1 * kWordSize));
+  __ ldr(R1, Address(SP));  // Load instantiator type arguments (R1).
   __ PushObject(Object::null_object());  // Make room for the result.
   __ Push(R0);  // Push the source object.
   __ PushObject(dst_type);  // Push the type of the destination.
-  // Push instantiator (R2) and its type arguments (R1).
-  __ Push(R2);
-  __ Push(R1);
+  __ Push(R1);  // Push instantiator type arguments (R1).
   __ PushObject(dst_name);  // Push the name of the destination.
   __ LoadUniqueObject(R0, test_cache);
   __ Push(R0);
-  GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
+  GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 5, locs);
   // Pop the parameters supplied to the runtime entry. The result of the
   // type check runtime call is the checked value.
-  __ Drop(6);
+  __ Drop(5);
   __ Pop(R0);
 
   __ Bind(&is_assignable);
-  // Restore instantiator (R2) and its type arguments (R1).
+  // Restore instantiator type arguments (R1).
   __ Pop(R1);
-  __ Pop(R2);
 }
 
 
@@ -985,6 +972,7 @@
   if (CanOptimizeFunction() &&
       function.IsOptimizable() &&
       (!is_optimizing() || may_reoptimize())) {
+    __ Comment("Invocation Count Check");
     const Register function_reg = R6;
     new_pp = R13;
     // The pool pointer is not setup before entering the Dart frame.
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index af8e5b7..53a26cc 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -470,7 +470,7 @@
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
   if (type.IsTypeParameter()) {
     const TypeParameter& type_param = TypeParameter::Cast(type);
-    // Load instantiator (or null) and instantiator type arguments on stack.
+    // Load instantiator type arguments on stack.
     __ movl(EDX, Address(ESP, 0));  // Get instantiator type arguments.
     // EDX: instantiator type arguments.
     // Check if type arguments are null, i.e. equivalent to vector of dynamic.
@@ -595,8 +595,7 @@
 // Inputs:
 // - EAX: object.
 // - EDX: instantiator type arguments or raw_null.
-// - ECX: instantiator or raw_null.
-// Clobbers ECX and EDX.
+// Clobbers EDX.
 // Returns:
 // - true or false in EAX.
 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
@@ -609,7 +608,6 @@
   const Immediate& raw_null =
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
   Label is_instance, is_not_instance;
-  __ pushl(ECX);  // Store instantiator on stack.
   __ pushl(EDX);  // Store instantiator type arguments.
   // If type is instantiated and non-parameterized, we can inline code
   // checking whether the tested instance is a Smi.
@@ -635,22 +633,20 @@
   if (!test_cache.IsNull()) {
     // Generate runtime call.
     __ movl(EDX, Address(ESP, 0));  // Get instantiator type arguments.
-    __ movl(ECX, Address(ESP, kWordSize));  // Get instantiator.
     __ PushObject(Object::null_object());  // Make room for the result.
     __ pushl(EAX);  // Push the instance.
     __ PushObject(type);  // Push the type.
-    __ pushl(ECX);  // Instantiator.
     __ pushl(EDX);  // Instantiator type arguments.
     __ LoadObject(EAX, test_cache);
     __ pushl(EAX);
     GenerateRuntimeCall(token_pos,
                         deopt_id,
                         kInstanceofRuntimeEntry,
-                        5,
+                        4,
                         locs);
     // Pop the parameters supplied to the runtime entry. The result of the
     // instanceof runtime call will be left as the result of the operation.
-    __ Drop(5);
+    __ Drop(4);
     if (negate_result) {
       __ popl(EDX);
       __ LoadObject(EAX, Bool::True());
@@ -670,7 +666,6 @@
   __ LoadObject(EAX, Bool::Get(!negate_result));
   __ Bind(&done);
   __ popl(EDX);  // Remove pushed instantiator type arguments.
-  __ popl(ECX);  // Remove pushed instantiator.
 }
 
 
@@ -681,7 +676,6 @@
 // Inputs:
 // - EAX: object.
 // - EDX: instantiator type arguments or raw_null.
-// - ECX: instantiator or raw_null.
 // Returns:
 // - object in EAX for successful assignable check (or throws TypeError).
 // Performance notes: positive checks must be quick, negative checks can be slow
@@ -697,7 +691,6 @@
   // Assignable check is skipped in FlowGraphBuilder, not here.
   ASSERT(dst_type.IsMalformedOrMalbounded() ||
          (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
-  __ pushl(ECX);  // Store instantiator.
   __ pushl(EDX);  // Store instantiator type arguments.
   // A null object is always assignable and is returned as result.
   const Immediate& raw_null =
@@ -722,7 +715,6 @@
 
     __ Bind(&is_assignable);  // For a null object.
     __ popl(EDX);  // Remove pushed instantiator type arguments.
-    __ popl(ECX);  // Remove pushed instantiator.
     return;
   }
 
@@ -733,24 +725,21 @@
 
   __ Bind(&runtime_call);
   __ movl(EDX, Address(ESP, 0));  // Get instantiator type arguments.
-  __ movl(ECX, Address(ESP, kWordSize));  // Get instantiator.
   __ PushObject(Object::null_object());  // Make room for the result.
   __ pushl(EAX);  // Push the source object.
   __ PushObject(dst_type);  // Push the type of the destination.
-  __ pushl(ECX);  // Instantiator.
   __ pushl(EDX);  // Instantiator type arguments.
   __ PushObject(dst_name);  // Push the name of the destination.
   __ LoadObject(EAX, test_cache);
   __ pushl(EAX);
-  GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
+  GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 5, locs);
   // Pop the parameters supplied to the runtime entry. The result of the
   // type check runtime call is the checked value.
-  __ Drop(6);
+  __ Drop(5);
   __ popl(EAX);
 
   __ Bind(&is_assignable);
   __ popl(EDX);  // Remove pushed instantiator type arguments.
-  __ popl(ECX);  // Remove pushed instantiator.
 }
 
 
@@ -1012,6 +1001,7 @@
   if (CanOptimizeFunction() &&
       function.IsOptimizable() &&
       (!is_optimizing() || may_reoptimize())) {
+    __ Comment("Invocation Count Check");
     const Register function_reg = EBX;
     __ LoadObject(function_reg, function);
 
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index b569456..55a3dfc 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -450,7 +450,7 @@
   // Skip check if destination is a dynamic type.
   if (type.IsTypeParameter()) {
     const TypeParameter& type_param = TypeParameter::Cast(type);
-    // Load instantiator (or null) and instantiator type arguments on stack.
+    // Load instantiator type arguments on stack.
     __ lw(A1, Address(SP, 0));  // Get instantiator type arguments.
     // A1: instantiator type arguments.
     // Check if type arguments are null, i.e. equivalent to vector of dynamic.
@@ -575,7 +575,6 @@
 // Inputs:
 // - A0: object.
 // - A1: instantiator type arguments or raw_null.
-// - A2: instantiator or raw_null.
 // Returns:
 // - true or false in V0.
 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
@@ -585,9 +584,8 @@
                                            LocationSummary* locs) {
   ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded());
 
-  // Preserve instantiator (A2) and its type arguments (A1).
-  __ addiu(SP, SP, Immediate(-2 * kWordSize));
-  __ sw(A2, Address(SP, 1 * kWordSize));
+  // Preserve instantiator type arguments (A1).
+  __ addiu(SP, SP, Immediate(-1 * kWordSize));
   __ sw(A1, Address(SP, 0 * kWordSize));
 
   Label is_instance, is_not_instance;
@@ -614,25 +612,23 @@
   Label done;
   if (!test_cache.IsNull()) {
     // Generate runtime call.
-    // Load instantiator (A2) and its type arguments (A1).
+    // Load instantiator type arguments (A1).
     __ lw(A1, Address(SP, 0 * kWordSize));
-    __ lw(A2, Address(SP, 1 * kWordSize));
 
-    __ addiu(SP, SP, Immediate(-6 * kWordSize));
+    __ addiu(SP, SP, Immediate(-5 * kWordSize));
     __ LoadObject(TMP, Object::null_object());
-    __ sw(TMP, Address(SP, 5 * kWordSize));  // Make room for the result.
-    __ sw(A0, Address(SP, 4 * kWordSize));  // Push the instance.
+    __ sw(TMP, Address(SP, 4 * kWordSize));  // Make room for the result.
+    __ sw(A0, Address(SP, 3 * kWordSize));  // Push the instance.
     __ LoadObject(TMP, type);
-    __ sw(TMP, Address(SP, 3 * kWordSize));  // Push the type.
-    __ sw(A2, Address(SP, 2 * kWordSize));  // Push instantiator.
+    __ sw(TMP, Address(SP, 2 * kWordSize));  // Push the type.
     __ sw(A1, Address(SP, 1 * kWordSize));  // Push type arguments.
     __ LoadUniqueObject(A0, test_cache);
     __ sw(A0, Address(SP, 0 * kWordSize));
-    GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
+    GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 4, locs);
     // Pop the parameters supplied to the runtime entry. The result of the
     // instanceof runtime call will be left as the result of the operation.
-    __ lw(T0, Address(SP, 5 * kWordSize));
-    __ addiu(SP, SP, Immediate(6 * kWordSize));
+    __ lw(T0, Address(SP, 4 * kWordSize));
+    __ addiu(SP, SP, Immediate(5 * kWordSize));
     if (negate_result) {
       __ LoadObject(V0, Bool::True());
       __ bne(T0, V0, &done);
@@ -649,8 +645,8 @@
   __ Bind(&is_instance);
   __ LoadObject(V0, Bool::Get(!negate_result));
   __ Bind(&done);
-  // Remove instantiator (A2) and its type arguments (A1).
-  __ Drop(2);
+  // Remove instantiator type arguments (A1).
+  __ Drop(1);
 }
 
 
@@ -661,7 +657,6 @@
 // Inputs:
 // - A0: instance being type checked.
 // - A1: instantiator type arguments or raw_null.
-// - A2: instantiator or raw_null.
 // Returns:
 // - object in A0 for successful assignable check (or throws TypeError).
 // Clobbers: T0, T1, T2
@@ -679,9 +674,9 @@
   // Assignable check is skipped in FlowGraphBuilder, not here.
   ASSERT(dst_type.IsMalformedOrMalbounded() ||
          (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
-  // Preserve instantiator and its type arguments.
-  __ addiu(SP, SP, Immediate(-2 * kWordSize));
-  __ sw(A2, Address(SP, 1 * kWordSize));
+  // Preserve instantiator type arguments.
+  __ addiu(SP, SP, Immediate(-1 * kWordSize));
+  __ sw(A1, Address(SP, 0 * kWordSize));
 
   // A null object is always assignable and is returned as result.
   Label is_assignable, runtime_call;
@@ -709,10 +704,9 @@
     __ break_(0);
 
     __ Bind(&is_assignable);  // For a null object.
-    // Restore instantiator and its type arguments.
+    // Restore instantiator type arguments.
     __ lw(A1, Address(SP, 0 * kWordSize));
-    __ lw(A2, Address(SP, 1 * kWordSize));
-    __ addiu(SP, SP, Immediate(2 * kWordSize));
+    __ addiu(SP, SP, Immediate(1 * kWordSize));
     return;
   }
 
@@ -722,34 +716,31 @@
                                         &is_assignable, &runtime_call);
 
   __ Bind(&runtime_call);
-  // Load instantiator (A2) and its type arguments (A1).
+  // Load instantiator type arguments (A1).
   __ lw(A1, Address(SP, 0 * kWordSize));
-  __ lw(A2, Address(SP, 1 * kWordSize));
 
-  __ addiu(SP, SP, Immediate(-7 * kWordSize));
+  __ addiu(SP, SP, Immediate(-6 * kWordSize));
   __ LoadObject(TMP, Object::null_object());
-  __ sw(TMP, Address(SP, 6 * kWordSize));  // Make room for the result.
-  __ sw(A0, Address(SP, 5 * kWordSize));  // Push the source object.
+  __ sw(TMP, Address(SP, 5 * kWordSize));  // Make room for the result.
+  __ sw(A0, Address(SP, 4 * kWordSize));  // Push the source object.
   __ LoadObject(TMP, dst_type);
-  __ sw(TMP, Address(SP, 4 * kWordSize));  // Push the type of the destination.
-  __ sw(A2, Address(SP, 3 * kWordSize));  // Push instantiator.
+  __ sw(TMP, Address(SP, 3 * kWordSize));  // Push the type of the destination.
   __ sw(A1, Address(SP, 2 * kWordSize));  // Push type arguments.
   __ LoadObject(TMP, dst_name);
   __ sw(TMP, Address(SP, 1 * kWordSize));  // Push the name of the destination.
   __ LoadUniqueObject(T0, test_cache);
   __ sw(T0, Address(SP, 0 * kWordSize));
 
-  GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
+  GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 5, locs);
   // Pop the parameters supplied to the runtime entry. The result of the
   // type check runtime call is the checked value.
-  __ lw(A0, Address(SP, 6 * kWordSize));
-  __ addiu(SP, SP, Immediate(7 * kWordSize));
+  __ lw(A0, Address(SP, 5 * kWordSize));
+  __ addiu(SP, SP, Immediate(6 * kWordSize));
 
   __ Bind(&is_assignable);
-  // Restore instantiator and its type arguments.
+  // Restore instantiator type arguments.
   __ lw(A1, Address(SP, 0 * kWordSize));
-  __ lw(A2, Address(SP, 1 * kWordSize));
-  __ addiu(SP, SP, Immediate(2 * kWordSize));
+  __ addiu(SP, SP, Immediate(1 * kWordSize));
 }
 
 
@@ -1003,6 +994,7 @@
   if (CanOptimizeFunction() &&
       function.IsOptimizable() &&
       (!is_optimizing() || may_reoptimize())) {
+    __ Comment("Invocation Count Check");
     const Register function_reg = T0;
 
     // Temporarily setup pool pointer for this dart function.
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 5f38396..fc3d951 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -463,7 +463,7 @@
   // Skip check if destination is a dynamic type.
   if (type.IsTypeParameter()) {
     const TypeParameter& type_param = TypeParameter::Cast(type);
-    // Load instantiator (or null) and instantiator type arguments on stack.
+    // Load instantiator type arguments on stack.
     __ movq(RDX, Address(RSP, 0));  // Get instantiator type arguments.
     // RDX: instantiator type arguments.
     // Check if type arguments are null, i.e. equivalent to vector of dynamic.
@@ -589,8 +589,7 @@
 // Inputs:
 // - RAX: object.
 // - RDX: instantiator type arguments or raw_null.
-// - RCX: instantiator or raw_null.
-// Clobbers RCX and RDX.
+// Clobbers RDX.
 // Returns:
 // - true or false in RAX.
 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
@@ -601,7 +600,6 @@
   ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded());
 
   Label is_instance, is_not_instance;
-  __ pushq(RCX);  // Store instantiator on stack.
   __ pushq(RDX);  // Store instantiator type arguments.
   // If type is instantiated and non-parameterized, we can inline code
   // checking whether the tested instance is a Smi.
@@ -627,22 +625,20 @@
   if (!test_cache.IsNull()) {
     // Generate runtime call.
     __ movq(RDX, Address(RSP, 0));  // Get instantiator type arguments.
-    __ movq(RCX, Address(RSP, kWordSize));  // Get instantiator.
     __ PushObject(Object::null_object());  // Make room for the result.
     __ pushq(RAX);  // Push the instance.
     __ PushObject(type);  // Push the type.
-    __ pushq(RCX);  // TODO(srdjan): Pass instantiator instead of null.
     __ pushq(RDX);  // Instantiator type arguments.
     __ LoadUniqueObject(RAX, test_cache);
     __ pushq(RAX);
     GenerateRuntimeCall(token_pos,
                         deopt_id,
                         kInstanceofRuntimeEntry,
-                        5,
+                        4,
                         locs);
     // Pop the parameters supplied to the runtime entry. The result of the
     // instanceof runtime call will be left as the result of the operation.
-    __ Drop(5);
+    __ Drop(4);
     if (negate_result) {
       __ popq(RDX);
       __ LoadObject(RAX, Bool::True());
@@ -662,7 +658,6 @@
   __ LoadObject(RAX, Bool::Get(!negate_result));
   __ Bind(&done);
   __ popq(RDX);  // Remove pushed instantiator type arguments.
-  __ popq(RCX);  // Remove pushed instantiator.
 }
 
 
@@ -673,7 +668,6 @@
 // Inputs:
 // - RAX: object.
 // - RDX: instantiator type arguments or raw_null.
-// - RCX: instantiator or raw_null.
 // Returns:
 // - object in RAX for successful assignable check (or throws TypeError).
 // Performance notes: positive checks must be quick, negative checks can be slow
@@ -689,7 +683,6 @@
   // Assignable check is skipped in FlowGraphBuilder, not here.
   ASSERT(dst_type.IsMalformedOrMalbounded() ||
          (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
-  __ pushq(RCX);  // Store instantiator.
   __ pushq(RDX);  // Store instantiator type arguments.
   // A null object is always assignable and is returned as result.
   Label is_assignable, runtime_call;
@@ -712,7 +705,6 @@
 
     __ Bind(&is_assignable);  // For a null object.
     __ popq(RDX);  // Remove pushed instantiator type arguments.
-    __ popq(RCX);  // Remove pushed instantiator.
     return;
   }
 
@@ -723,24 +715,21 @@
 
   __ Bind(&runtime_call);
   __ movq(RDX, Address(RSP, 0));  // Get instantiator type arguments.
-  __ movq(RCX, Address(RSP, kWordSize));  // Get instantiator.
   __ PushObject(Object::null_object());  // Make room for the result.
   __ pushq(RAX);  // Push the source object.
   __ PushObject(dst_type);  // Push the type of the destination.
-  __ pushq(RCX);  // Instantiator.
   __ pushq(RDX);  // Instantiator type arguments.
   __ PushObject(dst_name);  // Push the name of the destination.
   __ LoadUniqueObject(RAX, test_cache);
   __ pushq(RAX);
-  GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
+  GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 5, locs);
   // Pop the parameters supplied to the runtime entry. The result of the
   // type check runtime call is the checked value.
-  __ Drop(6);
+  __ Drop(5);
   __ popq(RAX);
 
   __ Bind(&is_assignable);
   __ popq(RDX);  // Remove pushed instantiator type arguments.
-  __ popq(RCX);  // Remove pushed instantiator.
 }
 
 
@@ -1015,6 +1004,7 @@
     if (CanOptimizeFunction() &&
         function.IsOptimizable() &&
         (!is_optimizing() || may_reoptimize())) {
+      __ Comment("Invocation Count Check");
       const Register function_reg = RDI;
       // Load function object using the callee's pool pointer.
       __ LoadFunctionFromCalleePool(function_reg, function, new_pp);
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 7cd46a0..bc5d7bc 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -59,7 +59,7 @@
             "Enable inlining annotations");
 
 DECLARE_FLAG(bool, compiler_stats);
-DECLARE_FLAG(int, deoptimization_counter_threshold);
+DECLARE_FLAG(int, max_deoptimization_counter_threshold);
 DECLARE_FLAG(bool, polymorphic_with_deopt);
 DECLARE_FLAG(bool, print_flow_graph);
 DECLARE_FLAG(bool, print_flow_graph_optimized);
@@ -639,7 +639,7 @@
 
     // Abort if this function has deoptimized too much.
     if (function.deoptimization_counter() >=
-        FLAG_deoptimization_counter_threshold) {
+        FLAG_max_deoptimization_counter_threshold) {
       function.set_is_inlinable(false);
       TRACE_INLINING(THR_Print("     Bailout: deoptimization threshold\n"));
       PRINT_INLINING_TREE("Deoptimization threshold exceeded",
@@ -1692,7 +1692,7 @@
     }
     const ICData& old_checks = call_->ic_data();
     const ICData& new_checks = ICData::ZoneHandle(
-        ICData::New(Function::Handle(old_checks.owner()),
+        ICData::New(Function::Handle(old_checks.Owner()),
                     String::Handle(old_checks.target_name()),
                     Array::Handle(old_checks.arguments_descriptor()),
                     old_checks.deopt_id(),
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 8a20b88..f10e60c 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -276,7 +276,12 @@
   }
 
   // Check if getter or setter in function's class and class is currently leaf.
-  if (FLAG_guess_icdata_cid &&
+  // Do not run the optimization below if in background compilation since
+  // resolution of getter functions may create new signature classes.
+  // TODO(regis): Remove test for background compilation once signature classes
+  // are not generated any longer.
+  if (thread()->IsMutatorThread() &&
+      FLAG_guess_icdata_cid &&
       ((call->token_kind() == Token::kGET) ||
           (call->token_kind() == Token::kSET))) {
     const Class& owner_class = Class::Handle(Z, function().Owner());
@@ -319,7 +324,7 @@
   // not found in the ICData.
   if (!function.IsNull()) {
     const ICData& new_ic_data = ICData::ZoneHandle(Z, ICData::New(
-        Function::Handle(Z, ic_data.owner()),
+        Function::Handle(Z, ic_data.Owner()),
         String::Handle(Z, ic_data.target_name()),
         Object::empty_array(),  // Dummy argument descriptor.
         ic_data.deopt_id(),
@@ -1303,7 +1308,6 @@
     // the index is not a smi.
     const AbstractType& value_type =
         AbstractType::ZoneHandle(Z, target.ParameterTypeAt(2));
-    Definition* instantiator = NULL;
     Definition* type_args = NULL;
     switch (array_cid) {
       case kArrayCid:
@@ -1321,7 +1325,6 @@
                                         NULL,
                                         FlowGraph::kValue);
 
-        instantiator = array;
         type_args = load_type_args;
         break;
       }
@@ -1339,7 +1342,7 @@
         // Fall through.
       case kTypedDataFloat32ArrayCid:
       case kTypedDataFloat64ArrayCid: {
-        type_args = instantiator = flow_graph_->constant_null();
+        type_args = flow_graph_->constant_null();
         ASSERT((array_cid != kTypedDataFloat32ArrayCid &&
                 array_cid != kTypedDataFloat64ArrayCid) ||
                value_type.IsDoubleType());
@@ -1347,14 +1350,14 @@
         break;
       }
       case kTypedDataFloat32x4ArrayCid: {
-        type_args = instantiator = flow_graph_->constant_null();
+        type_args = flow_graph_->constant_null();
         ASSERT((array_cid != kTypedDataFloat32x4ArrayCid) ||
                value_type.IsFloat32x4Type());
         ASSERT(value_type.IsInstantiated());
         break;
       }
       case kTypedDataFloat64x2ArrayCid: {
-        type_args = instantiator = flow_graph_->constant_null();
+        type_args = flow_graph_->constant_null();
         ASSERT((array_cid != kTypedDataFloat64x2ArrayCid) ||
                value_type.IsFloat64x2Type());
         ASSERT(value_type.IsInstantiated());
@@ -1367,7 +1370,6 @@
     AssertAssignableInstr* assert_value =
         new(Z) AssertAssignableInstr(token_pos,
                                      new(Z) Value(stored_value),
-                                     new(Z) Value(instantiator),
                                      new(Z) Value(type_args),
                                      value_type,
                                      Symbols::Value(),
@@ -4051,12 +4053,10 @@
 void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
   ASSERT(Token::IsTypeTestOperator(call->token_kind()));
   Definition* left = call->ArgumentAt(0);
-  Definition* instantiator = NULL;
   Definition* type_args = NULL;
   AbstractType& type = AbstractType::ZoneHandle(Z);
   bool negate = false;
   if (call->ArgumentCount() == 2) {
-    instantiator = flow_graph()->constant_null();
     type_args = flow_graph()->constant_null();
     if (call->function_name().raw() ==
         Library::PrivateCoreLibName(Symbols::_instanceOfNum()).raw()) {
@@ -4079,10 +4079,9 @@
     negate = Bool::Cast(call->ArgumentAt(1)->OriginalDefinition()
         ->AsConstant()->value()).value();
   } else {
-    instantiator = call->ArgumentAt(1);
-    type_args = call->ArgumentAt(2);
-    type = AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()).raw();
-    negate = Bool::Cast(call->ArgumentAt(4)->OriginalDefinition()
+    type_args = call->ArgumentAt(1);
+    type = AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()).raw();
+    negate = Bool::Cast(call->ArgumentAt(3)->OriginalDefinition()
         ->AsConstant()->value()).value();
   }
   const ICData& unary_checks =
@@ -4159,7 +4158,6 @@
   InstanceOfInstr* instance_of =
       new(Z) InstanceOfInstr(call->token_pos(),
                              new(Z) Value(left),
-                             new(Z) Value(instantiator),
                              new(Z) Value(type_args),
                              type,
                              negate,
@@ -4172,10 +4170,9 @@
 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
   ASSERT(Token::IsTypeCastOperator(call->token_kind()));
   Definition* left = call->ArgumentAt(0);
-  Definition* instantiator = call->ArgumentAt(1);
-  Definition* type_args = call->ArgumentAt(2);
+  Definition* type_args = call->ArgumentAt(1);
   const AbstractType& type =
-      AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value());
+      AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value());
   ASSERT(!type.IsMalformedOrMalbounded());
   const ICData& unary_checks =
       ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
@@ -4214,7 +4211,6 @@
   AssertAssignableInstr* assert_as =
       new(Z) AssertAssignableInstr(call->token_pos(),
                                    new(Z) Value(left),
-                                   new(Z) Value(instantiator),
                                    new(Z) Value(type_args),
                                    type,
                                    dst_name,
diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc
index 6b2a946..1638b3d 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -596,7 +596,8 @@
   }
 
   virtual void Run() {
-    Thread::EnterIsolateAsHelper(isolate_, true);
+    bool result = Thread::EnterIsolateAsHelper(isolate_, true);
+    ASSERT(result);
     {
       StackZone stack_zone(Thread::Current());
       Zone* zone = stack_zone.GetZone();
diff --git a/runtime/vm/gc_sweeper.cc b/runtime/vm/gc_sweeper.cc
index 6332dee..a192138 100644
--- a/runtime/vm/gc_sweeper.cc
+++ b/runtime/vm/gc_sweeper.cc
@@ -114,7 +114,8 @@
   }
 
   virtual void Run() {
-    Thread::EnterIsolateAsHelper(task_isolate_);
+    bool result = Thread::EnterIsolateAsHelper(task_isolate_);
+    ASSERT(result);
     GCSweeper sweeper;
 
     HeapPage* page = first_;
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index 30c4a6f..97de0b1 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -405,9 +405,6 @@
   f->Print(", %s, '%s'",
            dst_type().ToCString(),
            dst_name().ToCString());
-  f->Print(" instantiator(");
-  instantiator()->PrintTo(f);
-  f->Print(")");
   f->Print(" instantiator_type_arguments(");
   instantiator_type_arguments()->PrintTo(f);
   f->Print(")");
@@ -551,9 +548,6 @@
   f->Print(" %s %s",
             negate_result() ? "ISNOT" : "IS",
             String::Handle(type().Name()).ToCString());
-  f->Print(" instantiator(");
-  instantiator()->PrintTo(f);
-  f->Print(")");
   f->Print(" type-arg(");
   instantiator_type_arguments()->PrintTo(f);
   f->Print(")");
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 852efd4..c73a48f 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -1735,6 +1735,19 @@
 }
 
 
+Definition* BinaryIntegerOpInstr::CreateConstantResult(FlowGraph* flow_graph,
+                                                       const Integer& result) {
+  Definition* result_defn = flow_graph->GetConstant(result);
+  if (representation() != kTagged) {
+    result_defn = UnboxInstr::Create(representation(),
+                                     new Value(result_defn),
+                                     GetDeoptId());
+    flow_graph->InsertBefore(this, result_defn, env(), FlowGraph::kValue);
+  }
+  return result_defn;
+}
+
+
 Definition* BinaryIntegerOpInstr::Canonicalize(FlowGraph* flow_graph) {
   // If both operands are constants evaluate this expression. Might
   // occur due to load forwarding after constant propagation pass
@@ -1747,7 +1760,7 @@
         Evaluate(Integer::Cast(left()->BoundConstant()),
                  Integer::Cast(right()->BoundConstant())));
     if (!result.IsNull()) {
-      return flow_graph->GetConstant(result);
+      return CreateConstantResult(flow_graph, result);
     }
   }
 
@@ -1872,7 +1885,7 @@
         DeoptimizeInstr* deopt =
             new DeoptimizeInstr(ICData::kDeoptBinarySmiOp, GetDeoptId());
         flow_graph->InsertBefore(this, deopt, env(), FlowGraph::kEffect);
-        return flow_graph->GetConstant(Smi::Handle(Smi::New(0)));
+        return CreateConstantResult(flow_graph, Integer::Handle(Smi::New(0)));
       }
       break;
 
@@ -1886,7 +1899,7 @@
               new DeoptimizeInstr(ICData::kDeoptBinarySmiOp, GetDeoptId());
           flow_graph->InsertBefore(this, deopt, env(), FlowGraph::kEffect);
         }
-        return flow_graph->GetConstant(Smi::Handle(Smi::New(0)));
+        return CreateConstantResult(flow_graph, Integer::Handle(Smi::New(0)));
       }
       break;
     }
@@ -2202,11 +2215,13 @@
   // Fold away UnboxInteger<rep_to>(BoxInteger<rep_from>(v)).
   BoxIntegerInstr* box_defn = value()->definition()->AsBoxInteger();
   if (box_defn != NULL) {
-    if (box_defn->value()->definition()->representation() == representation()) {
+    Representation from_representation =
+        box_defn->value()->definition()->representation();
+    if (from_representation == representation()) {
       return box_defn->value()->definition();
     } else {
       UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr(
-          box_defn->value()->definition()->representation(),
+          from_representation,
           representation(),
           box_defn->value()->CopyWithType(),
           (representation() == kUnboxedInt32) ?
@@ -2522,6 +2537,7 @@
 
 
 Definition* StrictCompareInstr::Canonicalize(FlowGraph* flow_graph) {
+  if (!HasUses()) return NULL;
   bool negated = false;
   Definition* replacement = CanonicalizeStrictCompare(this, &negated);
   if (negated && replacement->IsComparison()) {
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 897ee3f..76840bb 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -2590,11 +2590,10 @@
 };
 
 
-class AssertAssignableInstr : public TemplateDefinition<3, Throws, Pure> {
+class AssertAssignableInstr : public TemplateDefinition<2, Throws, Pure> {
  public:
   AssertAssignableInstr(intptr_t token_pos,
                         Value* value,
-                        Value* instantiator,
                         Value* instantiator_type_arguments,
                         const AbstractType& dst_type,
                         const String& dst_name,
@@ -2606,8 +2605,7 @@
     ASSERT(!dst_type.IsNull());
     ASSERT(!dst_name.IsNull());
     SetInputAt(0, value);
-    SetInputAt(1, instantiator);
-    SetInputAt(2, instantiator_type_arguments);
+    SetInputAt(1, instantiator_type_arguments);
   }
 
   DECLARE_INSTRUCTION(AssertAssignable)
@@ -2615,8 +2613,7 @@
   virtual bool RecomputeType();
 
   Value* value() const { return inputs_[0]; }
-  Value* instantiator() const { return inputs_[1]; }
-  Value* instantiator_type_arguments() const { return inputs_[2]; }
+  Value* instantiator_type_arguments() const { return inputs_[1]; }
 
   virtual intptr_t token_pos() const { return token_pos_; }
   const AbstractType& dst_type() const { return dst_type_; }
@@ -4010,11 +4007,10 @@
 };
 
 
-class InstanceOfInstr : public TemplateDefinition<3, Throws> {
+class InstanceOfInstr : public TemplateDefinition<2, Throws> {
  public:
   InstanceOfInstr(intptr_t token_pos,
                   Value* value,
-                  Value* instantiator,
                   Value* instantiator_type_arguments,
                   const AbstractType& type,
                   bool negate_result,
@@ -4025,16 +4021,14 @@
         negate_result_(negate_result) {
     ASSERT(!type.IsNull());
     SetInputAt(0, value);
-    SetInputAt(1, instantiator);
-    SetInputAt(2, instantiator_type_arguments);
+    SetInputAt(1, instantiator_type_arguments);
   }
 
   DECLARE_INSTRUCTION(InstanceOf)
   virtual CompileType ComputeType() const;
 
   Value* value() const { return inputs_[0]; }
-  Value* instantiator() const { return inputs_[1]; }
-  Value* instantiator_type_arguments() const { return inputs_[2]; }
+  Value* instantiator_type_arguments() const { return inputs_[1]; }
 
   bool negate_result() const { return negate_result_; }
   const AbstractType& type() const { return type_; }
@@ -4049,7 +4043,6 @@
  private:
   const intptr_t token_pos_;
   Value* value_;
-  Value* instantiator_;
   Value* type_arguments_;
   const AbstractType& type_;
   const bool negate_result_;
@@ -6849,6 +6842,8 @@
                         Range* range);
 
  private:
+  Definition* CreateConstantResult(FlowGraph* graph, const Integer& result);
+
   const Token::Kind op_kind_;
 
   bool can_overflow_;
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 8d6e6c1..9120195 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -345,13 +345,12 @@
 
 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
                                                             bool opt) const {
-  const intptr_t kNumInputs = 3;
+  const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps, LocationSummary::kCall);
   summary->set_in(0, Location::RegisterLocation(R0));  // Value.
-  summary->set_in(1, Location::RegisterLocation(R2));  // Instantiator.
-  summary->set_in(2, Location::RegisterLocation(R1));  // Type arguments.
+  summary->set_in(1, Location::RegisterLocation(R1));  // Type arguments.
   summary->set_out(0, Location::RegisterLocation(R0));
   return summary;
 }
@@ -2275,13 +2274,12 @@
 
 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone,
                                                       bool opt) const {
-  const intptr_t kNumInputs = 3;
+  const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps, LocationSummary::kCall);
   summary->set_in(0, Location::RegisterLocation(R0));
-  summary->set_in(1, Location::RegisterLocation(R2));
-  summary->set_in(2, Location::RegisterLocation(R1));
+  summary->set_in(1, Location::RegisterLocation(R1));
   summary->set_out(0, Location::RegisterLocation(R0));
   return summary;
 }
@@ -2289,8 +2287,7 @@
 
 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(locs()->in(0).reg() == R0);  // Value.
-  ASSERT(locs()->in(1).reg() == R2);  // Instantiator.
-  ASSERT(locs()->in(2).reg() == R1);  // Instantiator type arguments.
+  ASSERT(locs()->in(1).reg() == R1);  // Instantiator type arguments.
 
   compiler->GenerateInstanceOf(token_pos(),
                                deopt_id(),
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index 7f85d09..05ce132 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -333,13 +333,12 @@
 
 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
                                                             bool opt) const {
-  const intptr_t kNumInputs = 3;
+  const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps, LocationSummary::kCall);
   summary->set_in(0, Location::RegisterLocation(R0));  // Value.
-  summary->set_in(1, Location::RegisterLocation(R2));  // Instantiator.
-  summary->set_in(2, Location::RegisterLocation(R1));  // Type arguments.
+  summary->set_in(1, Location::RegisterLocation(R1));  // Type arguments.
   summary->set_out(0, Location::RegisterLocation(R0));
   return summary;
 }
@@ -1995,13 +1994,12 @@
 
 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone,
                                                       bool opt) const {
-  const intptr_t kNumInputs = 3;
+  const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps, LocationSummary::kCall);
   summary->set_in(0, Location::RegisterLocation(R0));
-  summary->set_in(1, Location::RegisterLocation(R2));
-  summary->set_in(2, Location::RegisterLocation(R1));
+  summary->set_in(1, Location::RegisterLocation(R1));
   summary->set_out(0, Location::RegisterLocation(R0));
   return summary;
 }
@@ -2009,8 +2007,7 @@
 
 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(locs()->in(0).reg() == R0);  // Value.
-  ASSERT(locs()->in(1).reg() == R2);  // Instantiator.
-  ASSERT(locs()->in(2).reg() == R1);  // Instantiator type arguments.
+  ASSERT(locs()->in(1).reg() == R1);  // Instantiator type arguments.
 
   compiler->GenerateInstanceOf(token_pos(),
                                deopt_id(),
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index b5a851f..0c2f782 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -218,13 +218,12 @@
 
 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
                                                             bool opt) const {
-  const intptr_t kNumInputs = 3;
+  const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps, LocationSummary::kCall);
   summary->set_in(0, Location::RegisterLocation(EAX));  // Value.
-  summary->set_in(1, Location::RegisterLocation(ECX));  // Instantiator.
-  summary->set_in(2, Location::RegisterLocation(EDX));  // Type arguments.
+  summary->set_in(1, Location::RegisterLocation(EDX));  // Type arguments.
   summary->set_out(0, Location::RegisterLocation(EAX));
   return summary;
 }
@@ -2010,13 +2009,12 @@
 
 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone,
                                                       bool opt) const {
-  const intptr_t kNumInputs = 3;
+  const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps, LocationSummary::kCall);
   summary->set_in(0, Location::RegisterLocation(EAX));
-  summary->set_in(1, Location::RegisterLocation(ECX));
-  summary->set_in(2, Location::RegisterLocation(EDX));
+  summary->set_in(1, Location::RegisterLocation(EDX));
   summary->set_out(0, Location::RegisterLocation(EAX));
   return summary;
 }
@@ -2024,8 +2022,7 @@
 
 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(locs()->in(0).reg() == EAX);  // Value.
-  ASSERT(locs()->in(1).reg() == ECX);  // Instantiator.
-  ASSERT(locs()->in(2).reg() == EDX);  // Instantiator type arguments.
+  ASSERT(locs()->in(1).reg() == EDX);  // Instantiator type arguments.
 
   compiler->GenerateInstanceOf(token_pos(),
                                deopt_id(),
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 16c4367..e403445 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -394,13 +394,12 @@
 
 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
                                                             bool opt) const {
-  const intptr_t kNumInputs = 3;
+  const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps, LocationSummary::kCall);
   summary->set_in(0, Location::RegisterLocation(A0));  // Value.
-  summary->set_in(1, Location::RegisterLocation(A2));  // Instantiator.
-  summary->set_in(2, Location::RegisterLocation(A1));  // Type arguments.
+  summary->set_in(1, Location::RegisterLocation(A1));  // Type arguments.
   summary->set_out(0, Location::RegisterLocation(A0));
   return summary;
 }
@@ -2128,13 +2127,12 @@
 
 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone,
                                                       bool opt) const {
-  const intptr_t kNumInputs = 3;
+  const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps, LocationSummary::kCall);
   summary->set_in(0, Location::RegisterLocation(A0));
-  summary->set_in(1, Location::RegisterLocation(A2));
-  summary->set_in(2, Location::RegisterLocation(A1));
+  summary->set_in(1, Location::RegisterLocation(A1));
   summary->set_out(0, Location::RegisterLocation(V0));
   return summary;
 }
@@ -2142,8 +2140,7 @@
 
 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(locs()->in(0).reg() == A0);  // Value.
-  ASSERT(locs()->in(1).reg() == A2);  // Instantiator.
-  ASSERT(locs()->in(2).reg() == A1);  // Instantiator type arguments.
+  ASSERT(locs()->in(1).reg() == A1);  // Instantiator type arguments.
 
   __ Comment("InstanceOfInstr");
   compiler->GenerateInstanceOf(token_pos(),
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 07f30fb..7ca52de 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -305,13 +305,12 @@
 
 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
                                                             bool opt) const {
-  const intptr_t kNumInputs = 3;
+  const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps, LocationSummary::kCall);
   summary->set_in(0, Location::RegisterLocation(RAX));  // Value.
-  summary->set_in(1, Location::RegisterLocation(RCX));  // Instantiator.
-  summary->set_in(2, Location::RegisterLocation(RDX));  // Type arguments.
+  summary->set_in(1, Location::RegisterLocation(RDX));  // Type arguments.
   summary->set_out(0, Location::RegisterLocation(RAX));
   return summary;
 }
@@ -2013,13 +2012,12 @@
 
 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone,
                                                       bool opt) const {
-  const intptr_t kNumInputs = 3;
+  const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps, LocationSummary::kCall);
   summary->set_in(0, Location::RegisterLocation(RAX));
-  summary->set_in(1, Location::RegisterLocation(RCX));
-  summary->set_in(2, Location::RegisterLocation(RDX));
+  summary->set_in(1, Location::RegisterLocation(RDX));
   summary->set_out(0, Location::RegisterLocation(RAX));
   return summary;
 }
@@ -2027,8 +2025,7 @@
 
 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(locs()->in(0).reg() == RAX);  // Value.
-  ASSERT(locs()->in(1).reg() == RCX);  // Instantiator.
-  ASSERT(locs()->in(2).reg() == RDX);  // Instantiator type arguments.
+  ASSERT(locs()->in(1).reg() == RDX);  // Instantiator type arguments.
 
   compiler->GenerateInstanceOf(token_pos(),
                                deopt_id(),
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 0199af5..1635611 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -876,7 +876,12 @@
 
   // TODO(5411455): For now just set the recently created isolate as
   // the current isolate.
-  Thread::EnterIsolate(result);
+  if (!Thread::EnterIsolate(result)) {
+    // We failed to enter the isolate, it is possible the VM is shutting down,
+    // return back a NULL so that CreateIsolate reports back an error.
+    delete result;
+    return NULL;
+  }
 
   // Setup the isolate message handler.
   MessageHandler* handler = new IsolateMessageHandler(result);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index f44c365..4e8e2ddf 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -68,7 +68,6 @@
 DECLARE_FLAG(charp, coverage_dir);
 DECLARE_FLAG(bool, load_deferred_eagerly);
 DECLARE_FLAG(bool, show_invisible_frames);
-DECLARE_FLAG(bool, trace_compiler);
 DECLARE_FLAG(bool, trace_deoptimization);
 DECLARE_FLAG(bool, trace_deoptimization_verbose);
 DECLARE_FLAG(bool, write_protect_code);
@@ -2347,6 +2346,12 @@
     ClassFinalizer::ApplyMixinType(*this);
   }
   if (type_parameters() == TypeArguments::null()) {
+    const intptr_t cid = id();
+    if ((cid == kArrayCid) ||
+        (cid == kImmutableArrayCid) ||
+        (cid == kGrowableObjectArrayCid)) {
+      return 1;  // List's type parameter may not have been parsed yet.
+    }
     return 0;
   }
   REUSABLE_TYPE_ARGUMENTS_HANDLESCOPE(thread);
@@ -2797,9 +2802,10 @@
 }
 #endif
 
+
 void Class::RegisterCHACode(const Code& code) {
   if (FLAG_trace_cha) {
-    THR_Print("RegisterCHACode %s class %s\n",
+    THR_Print("RegisterCHACode '%s' depends on class '%s'\n",
         Function::Handle(code.function()).ToQualifiedCString(), ToCString());
   }
   DEBUG_ASSERT(IsMutatorOrAtSafepoint());
@@ -2809,9 +2815,12 @@
 }
 
 
-void Class::DisableCHAOptimizedCode() {
+void Class::DisableCHAOptimizedCode(const Class& subclass) {
   ASSERT(Thread::Current()->IsMutatorThread());
   CHACodeArray a(*this);
+  if (FLAG_trace_deoptimization && a.HasCodes()) {
+    THR_Print("Adding subclass %s\n", subclass.ToCString());
+  }
   a.DisableCode();
 }
 
@@ -3630,7 +3639,7 @@
 
 
 RawType* Class::CanonicalType() const {
-  if (NumTypeArguments() == 0) {
+  if (!IsGeneric()) {
     return reinterpret_cast<RawType*>(raw_ptr()->canonical_types_);
   }
   Array& types = Array::Handle();
@@ -3644,7 +3653,7 @@
 
 void Class::SetCanonicalType(const Type& type) const {
   ASSERT(type.IsCanonical());
-  if (NumTypeArguments() == 0) {
+  if (!IsGeneric()) {
     ASSERT((canonical_types() == Object::null()) ||
            (canonical_types() == type.raw()));  // Set during own finalization.
     set_canonical_types(type);
@@ -5820,7 +5829,7 @@
       ((end_token_pos() - token_pos()) < FLAG_huge_method_cutoff_in_tokens)) {
     // Additional check needed for implicit getters.
     return (unoptimized_code() == Object::null()) ||
-           (Code::Handle(unoptimized_code()).Size() <
+        (Code::Handle(unoptimized_code()).Size() <
             FLAG_huge_method_cutoff_in_code_size);
   }
   return false;
@@ -5837,6 +5846,7 @@
   set_is_optimizable(value);
   if (!value) {
     set_is_inlinable(false);
+    set_usage_counter(INT_MIN);
   }
 }
 
@@ -7033,7 +7043,9 @@
       ICData& ic_data = ICData::ZoneHandle(zone);
       ic_data ^= saved_ic_data.At(i);
       if (clone_descriptors) {
+        ICData& original_ic_data = ICData::Handle(zone, ic_data.raw());
         ic_data = ICData::CloneDescriptor(ic_data);
+        ic_data.SetOriginal(original_ic_data);
       }
       (*deopt_id_to_ic_data)[ic_data.deopt_id()] = &ic_data;
     }
@@ -7723,8 +7735,8 @@
   virtual void ReportSwitchingCode(const Code& code) {
     if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
       Function& function = Function::Handle(code.function());
-      THR_Print("Switching %s to unoptimized code because guard"
-                " on field %s was violated.\n",
+      THR_Print("Switching '%s' to unoptimized code because guard"
+                " on field '%s' was violated.\n",
                 function.ToFullyQualifiedCString(),
                 field_.ToCString());
     }
@@ -9589,7 +9601,10 @@
   ResolvedNamesMap cache(resolved_names());
   bool present = false;
   *obj = cache.GetOrNull(name, &present);
-  ASSERT(cache.Release().raw() == resolved_names());
+  // Mutator compiler thread may add entries and therefore
+  // change 'resolved_names()' while running a background compilation;
+  // do not ASSERT that 'resolved_names()' has not changed.
+  cache.Release();
   return present;
 }
 
@@ -12176,9 +12191,41 @@
 }
 
 
+RawFunction* ICData::Owner() const {
+  Object& obj = Object::Handle(raw_ptr()->owner_);
+  if (obj.IsFunction()) {
+    return Function::Cast(obj).raw();
+  } else {
+    ICData& original = ICData::Handle();
+    original ^= obj.raw();
+    return original.Owner();
+  }
+}
+
+
+RawICData* ICData::Original() const {
+  if (IsNull()) {
+    return ICData::null();
+  }
+  Object& obj = Object::Handle(raw_ptr()->owner_);
+  if (obj.IsFunction()) {
+    return this->raw();
+  } else {
+    return ICData::RawCast(obj.raw());
+  }
+}
+
+
+void ICData::SetOriginal(const ICData& value) const {
+  ASSERT(value.IsOriginal());
+  ASSERT(!value.IsNull());
+  StorePointer(&raw_ptr()->owner_, reinterpret_cast<RawObject*>(value.raw()));
+}
+
+
 void ICData::set_owner(const Function& value) const {
   ASSERT(!value.IsNull());
-  StorePointer(&raw_ptr()->owner_, value.raw());
+  StorePointer(&raw_ptr()->owner_, reinterpret_cast<RawObject*>(value.raw()));
 }
 
 
@@ -12817,7 +12864,7 @@
 
 RawICData* ICData::NewFrom(const ICData& from, intptr_t num_args_tested) {
   const ICData& result = ICData::Handle(ICData::New(
-      Function::Handle(from.owner()),
+      Function::Handle(from.Owner()),
       String::Handle(from.target_name()),
       Array::Handle(from.arguments_descriptor()),
       from.deopt_id(),
@@ -12832,7 +12879,7 @@
   Zone* zone = Thread::Current()->zone();
   const ICData& result = ICData::Handle(ICData::NewDescriptor(
       zone,
-      Function::Handle(zone, from.owner()),
+      Function::Handle(zone, from.Owner()),
       String::Handle(zone, from.target_name()),
       Array::Handle(zone, from.arguments_descriptor()),
       from.deopt_id(),
@@ -12849,7 +12896,7 @@
   JSONObject jsobj(stream);
   AddCommonObjectProperties(&jsobj, "Object", ref);
   jsobj.AddServiceId(*this);
-  jsobj.AddProperty("_owner", Object::Handle(owner()));
+  jsobj.AddProperty("_owner", Object::Handle(Owner()));
   jsobj.AddProperty("_selector", String::Handle(target_name()).ToCString());
   if (ref) {
     return;
@@ -12869,7 +12916,6 @@
 
   JSONObject jsobj(&jsarray);
   jsobj.AddProperty("name", String::Handle(target_name()).ToCString());
-  // TODO(turnidge): Use AddLocation instead.
   jsobj.AddProperty("tokenPos", token_pos);
   // TODO(rmacnak): Figure out how to stringify DeoptReasons().
   // jsobj.AddProperty("deoptReasons", ...);
@@ -12897,6 +12943,35 @@
 }
 
 
+void ICData::PrintToJSONArrayNew(const JSONArray& jsarray,
+                                 intptr_t token_pos,
+                                 bool is_static_call) const {
+  Isolate* isolate = Isolate::Current();
+  Class& cls = Class::Handle();
+  Function& func = Function::Handle();
+
+  JSONObject jsobj(&jsarray);
+  jsobj.AddProperty("name", String::Handle(target_name()).ToCString());
+  jsobj.AddProperty("tokenPos", token_pos);
+  // TODO(rmacnak): Figure out how to stringify DeoptReasons().
+  // jsobj.AddProperty("deoptReasons", ...);
+
+  JSONArray cache_entries(&jsobj, "cacheEntries");
+  for (intptr_t i = 0; i < NumberOfChecks(); i++) {
+    JSONObject cache_entry(&cache_entries);
+    func = GetTargetAt(i);
+    intptr_t count = GetCountAt(i);
+    if (!is_static_call) {
+      intptr_t cid = GetReceiverClassIdAt(i);
+      cls ^= isolate->class_table()->At(cid);
+      cache_entry.AddProperty("receiver", cls);
+    }
+    cache_entry.AddProperty("target", func);
+    cache_entry.AddProperty("count", count);
+  }
+}
+
+
 static Token::Kind RecognizeArithmeticOp(const String& name) {
   ASSERT(name.IsSymbol());
   if (name.raw() == Symbols::Plus().raw()) {
@@ -14888,7 +14963,7 @@
   }
   const Class& cls = Class::Handle(clazz());
   Type& type = Type::Handle();
-  if (cls.NumTypeArguments() == 0) {
+  if (!cls.IsGeneric()) {
     type = cls.CanonicalType();
   }
   if (type.IsNull()) {
@@ -16149,13 +16224,20 @@
     return Object::dynamic_type().raw();
   }
   // Fast canonical lookup/registry for simple types.
-  if (cls.NumTypeArguments() == 0) {
+  if (!cls.IsGeneric()) {
     type = cls.CanonicalType();
     if (type.IsNull()) {
       ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate()));
-      cls.set_canonical_types(*this);
-      SetCanonical();
-      return this->raw();
+      // Canonicalize the type arguments of the supertype, if any.
+      TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+      type_args = type_args.Canonicalize(trail);
+      set_arguments(type_args);
+      type = cls.CanonicalType();  // May be set while canonicalizing type args.
+      if (type.IsNull()) {
+        cls.set_canonical_types(*this);
+        SetCanonical();
+        return this->raw();
+      }
     }
     ASSERT(this->Equals(type));
     ASSERT(type.IsCanonical());
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 4bf0896..b223be2 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1354,7 +1354,7 @@
   // leaf method, ...).
   void RegisterCHACode(const Code& code);
 
-  void DisableCHAOptimizedCode();
+  void DisableCHAOptimizedCode(const Class& subclass);
 
   RawArray* cha_codes() const { return raw_ptr()->cha_codes_; }
   void set_cha_codes(const Array& value) const;
@@ -1748,11 +1748,20 @@
 
 
 // Object holding information about an IC: test classes and their
-// corresponding targets.
+// corresponding targets. The owner of the ICData can be either the function
+// or the original ICData object. In case of background compilation we
+// copy the ICData in a child object, thus freezing it during background
+// compilation. Code may contain only original ICData objects.
 class ICData : public Object {
  public:
-  RawFunction* owner() const {
-    return raw_ptr()->owner_;
+  RawFunction* Owner() const;
+
+  RawICData* Original() const;
+
+  void SetOriginal(const ICData& value) const;
+
+  bool IsOriginal() const {
+    return Original() == this->raw();
   }
 
   RawString* target_name() const {
@@ -2017,6 +2026,9 @@
   void PrintToJSONArray(const JSONArray& jsarray,
                         intptr_t token_pos,
                         bool is_static_call) const;
+  void PrintToJSONArrayNew(const JSONArray& jsarray,
+                           intptr_t token_pos,
+                           bool is_static_call) const;
 
   // Initialize the preallocated empty ICData entry arrays.
   static void InitOnce();
@@ -6817,7 +6829,11 @@
     // An Array is raw or takes one type argument. However, its type argument
     // vector may be longer than 1 due to a type optimization reusing the type
     // argument vector of the instantiator.
-    ASSERT(value.IsNull() || ((value.Length() >= 1) && value.IsInstantiated()));
+    ASSERT(value.IsNull() ||
+           ((value.Length() >= 1) &&
+            value.IsInstantiated() /*&& value.IsCanonical()*/));
+    // TODO(asiva): Values read from a message snapshot are not properly marked
+    // as canonical. See for example tests/isolate/mandel_isolate_test.dart.
     StorePointer(&raw_ptr()->type_arguments_, value.raw());
   }
 
@@ -6980,7 +6996,10 @@
     // A GrowableObjectArray is raw or takes one type argument. However, its
     // type argument vector may be longer than 1 due to a type optimization
     // reusing the type argument vector of the instantiator.
-    ASSERT(value.IsNull() || ((value.Length() >= 1) && value.IsInstantiated()));
+    ASSERT(value.IsNull() ||
+           ((value.Length() >= 1) &&
+            value.IsInstantiated() &&
+            value.IsCanonical()));
     const Array& contents = Array::Handle(data());
     contents.SetTypeArguments(value);
     StorePointer(&raw_ptr()->type_arguments_, value.raw());
@@ -7528,7 +7547,11 @@
     return raw_ptr()->type_arguments_;
   }
   virtual void SetTypeArguments(const TypeArguments& value) const {
-    ASSERT(value.IsNull() || ((value.Length() >= 2) && value.IsInstantiated()));
+    ASSERT(value.IsNull() ||
+           ((value.Length() >= 2) &&
+            value.IsInstantiated() /*&& value.IsCanonical()*/));
+    // TODO(asiva): Values read from a message snapshot are not properly marked
+    // as canonical. See for example tests/isolate/message3_test.dart.
     StorePointer(&raw_ptr()->type_arguments_, value.raw());
   }
   static intptr_t type_arguments_offset() {
@@ -7669,6 +7692,7 @@
   }
   static void SetTypeArguments(const Instance& closure,
                                const TypeArguments& value) {
+    ASSERT(value.IsNull() || value.IsCanonical());
     closure.StorePointer(TypeArgumentsAddr(closure), value.raw());
   }
   static intptr_t type_arguments_offset() {
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 15a0021..422121e 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -3023,7 +3023,7 @@
   o1 = ICData::New(function, target_name, args_descriptor, id, num_args_tested);
   EXPECT_EQ(1, o1.NumArgsTested());
   EXPECT_EQ(id, o1.deopt_id());
-  EXPECT_EQ(function.raw(), o1.owner());
+  EXPECT_EQ(function.raw(), o1.Owner());
   EXPECT_EQ(0, o1.NumberOfChecks());
   EXPECT_EQ(target_name.raw(), o1.target_name());
   EXPECT_EQ(args_descriptor.raw(), o1.arguments_descriptor());
@@ -3062,7 +3062,7 @@
   o2 = ICData::New(function, target_name, args_descriptor, 57, 2);
   EXPECT_EQ(2, o2.NumArgsTested());
   EXPECT_EQ(57, o2.deopt_id());
-  EXPECT_EQ(function.raw(), o2.owner());
+  EXPECT_EQ(function.raw(), o2.Owner());
   EXPECT_EQ(0, o2.NumberOfChecks());
   GrowableArray<intptr_t> classes;
   classes.Add(kSmiCid);
diff --git a/runtime/vm/os.h b/runtime/vm/os.h
index a403df2..cd570c4 100644
--- a/runtime/vm/os.h
+++ b/runtime/vm/os.h
@@ -50,6 +50,12 @@
   // Returns the current time used by the tracing infrastructure.
   static int64_t GetCurrentMonotonicMicros();
 
+  // Returns the raw clock value from the monotonic clock.
+  static int64_t GetCurrentMonotonicTicks();
+
+  // Returns the frequency of the monotonic clock.
+  static int64_t GetCurrentMonotonicFrequency();
+
   // Returns a cleared aligned array of type T with n entries.
   // Alignment must be >= 16 and a power of two.
   template<typename T>
diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc
index 5c09baf..9dcd09e 100644
--- a/runtime/vm/os_android.cc
+++ b/runtime/vm/os_android.cc
@@ -179,20 +179,32 @@
 }
 
 
-int64_t OS::GetCurrentMonotonicMicros() {
+int64_t OS::GetCurrentMonotonicTicks() {
   struct timespec ts;
   if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
     UNREACHABLE();
     return 0;
   }
-  // Convert to microseconds.
+  // Convert to nanoseconds.
   int64_t result = ts.tv_sec;
-  result *= kMicrosecondsPerSecond;
-  result += (ts.tv_nsec / kNanosecondsPerMicrosecond);
+  result *= kNanosecondsPerSecond;
+  result += ts.tv_nsec;
   return result;
 }
 
 
+int64_t OS::GetCurrentMonotonicFrequency() {
+  return kNanosecondsPerSecond;
+}
+
+
+int64_t OS::GetCurrentMonotonicMicros() {
+  int64_t ticks = GetCurrentMonotonicTicks();
+  ASSERT(GetCurrentMonotonicFrequency() == kNanosecondsPerSecond);
+  return ticks / kNanosecondsPerMicrosecond;
+}
+
+
 void* OS::AlignedAllocate(intptr_t size, intptr_t alignment) {
   const int kMinimumAlignment = 16;
   ASSERT(Utils::IsPowerOfTwo(alignment));
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index 7924be1..244e9b7 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -396,20 +396,32 @@
 }
 
 
-int64_t OS::GetCurrentMonotonicMicros() {
+int64_t OS::GetCurrentMonotonicTicks() {
   struct timespec ts;
   if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
     UNREACHABLE();
     return 0;
   }
-  // Convert to microseconds.
+  // Convert to nanoseconds.
   int64_t result = ts.tv_sec;
-  result *= kMicrosecondsPerSecond;
-  result += (ts.tv_nsec / kNanosecondsPerMicrosecond);
+  result *= kNanosecondsPerSecond;
+  result += ts.tv_nsec;
   return result;
 }
 
 
+int64_t OS::GetCurrentMonotonicFrequency() {
+  return kNanosecondsPerSecond;
+}
+
+
+int64_t OS::GetCurrentMonotonicMicros() {
+  int64_t ticks = GetCurrentMonotonicTicks();
+  ASSERT(GetCurrentMonotonicFrequency() == kNanosecondsPerSecond);
+  return ticks / kNanosecondsPerMicrosecond;
+}
+
+
 void* OS::AlignedAllocate(intptr_t size, intptr_t alignment) {
   const int kMinimumAlignment = 16;
   ASSERT(Utils::IsPowerOfTwo(alignment));
diff --git a/runtime/vm/os_macos.cc b/runtime/vm/os_macos.cc
index d2db92d..3393cb0 100644
--- a/runtime/vm/os_macos.cc
+++ b/runtime/vm/os_macos.cc
@@ -90,7 +90,10 @@
 }
 
 
-int64_t OS::GetCurrentMonotonicMicros() {
+static mach_timebase_info_data_t timebase_info;
+
+
+int64_t OS::GetCurrentMonotonicTicks() {
 #if TARGET_OS_IOS
   // On iOS mach_absolute_time stops while the device is sleeping. Instead use
   // now - KERN_BOOTTIME to get a time difference that is not impacted by clock
@@ -106,20 +109,9 @@
   origin += boottime.tv_usec;
   return now - origin;
 #else
-  static mach_timebase_info_data_t timebase_info;
-  if (timebase_info.denom == 0) {
-    // Zero-initialization of statics guarantees that denom will be 0 before
-    // calling mach_timebase_info.  mach_timebase_info will never set denom to
-    // 0 as that would be invalid, so the zero-check can be used to determine
-    // whether mach_timebase_info has already been called.  This is
-    // recommended by Apple's QA1398.
-    kern_return_t kr = mach_timebase_info(&timebase_info);
-    ASSERT(KERN_SUCCESS == kr);
-  }
-
-  // timebase_info converts absolute time tick units into nanoseconds.  Convert
-  // to microseconds.
-  int64_t result = mach_absolute_time() / kNanosecondsPerMicrosecond;
+  ASSERT(timebase_info.denom != 0);
+  // timebase_info converts absolute time tick units into nanoseconds.
+  int64_t result = mach_absolute_time();
   result *= timebase_info.numer;
   result /= timebase_info.denom;
   return result;
@@ -127,6 +119,26 @@
 }
 
 
+int64_t OS::GetCurrentMonotonicFrequency() {
+#if TARGET_OS_IOS
+  return kMicrosecondsPerSecond;
+#else
+  return kNanosecondsPerSecond;
+#endif  // TARGET_OS_IOS
+}
+
+
+int64_t OS::GetCurrentMonotonicMicros() {
+#if TARGET_OS_IOS
+  ASSERT(GetCurrentMonotonicFrequency() == kMicrosecondsPerSecond);
+  return GetCurrentMonotonicTicks();
+#else
+  ASSERT(GetCurrentMonotonicFrequency() == kNanosecondsPerSecond);
+  return GetCurrentMonotonicTicks() / kNanosecondsPerMicrosecond;
+#endif  // TARGET_OS_IOS
+}
+
+
 void* OS::AlignedAllocate(intptr_t size, intptr_t alignment) {
   const int kMinimumAlignment = 16;
   ASSERT(Utils::IsPowerOfTwo(alignment));
@@ -361,6 +373,8 @@
   static bool init_once_called = false;
   ASSERT(init_once_called == false);
   init_once_called = true;
+  kern_return_t kr = mach_timebase_info(&timebase_info);
+  ASSERT(KERN_SUCCESS == kr);
 }
 
 
diff --git a/runtime/vm/os_thread.cc b/runtime/vm/os_thread.cc
index 3789a60..0dcd506 100644
--- a/runtime/vm/os_thread.cc
+++ b/runtime/vm/os_thread.cc
@@ -16,6 +16,7 @@
 ThreadLocalKey OSThread::thread_key_ = kUnsetThreadLocalKey;
 OSThread* OSThread::thread_list_head_ = NULL;
 Mutex* OSThread::thread_list_lock_ = NULL;
+bool OSThread::creation_enabled_ = false;
 
 
 OSThread::OSThread() :
@@ -31,7 +32,18 @@
     log_(new class Log()),
     stack_base_(0),
     thread_(NULL) {
-  AddThreadToList(this);
+}
+
+
+OSThread* OSThread::CreateOSThread() {
+  ASSERT(thread_list_lock_ != NULL);
+  MutexLocker ml(thread_list_lock_);
+  if (!creation_enabled_) {
+    return NULL;
+  }
+  OSThread* os_thread = new OSThread();
+  AddThreadToListLocked(os_thread);
+  return os_thread;
 }
 
 
@@ -92,14 +104,21 @@
   thread_key_ = CreateThreadLocal(DeleteThread);
   ASSERT(thread_key_ != kUnsetThreadLocalKey);
 
+  // Enable creation of OSThread structures in the VM.
+  EnableOSThreadCreation();
+
   // Create a new OSThread strcture and set it as the TLS.
-  OSThread* os_thread = new OSThread();
+  OSThread* os_thread = CreateOSThread();
+  ASSERT(os_thread != NULL);
   OSThread::SetCurrent(os_thread);
   os_thread->set_name("Dart_Initialize");
 }
 
 
 void OSThread::Cleanup() {
+  // We cannot delete the thread local key and thread list lock,  yet.
+  // See the note on thread_list_lock_ in os_thread.h.
+#if 0
   if (thread_list_lock_ != NULL) {
     // Delete the thread local key.
     ASSERT(thread_key_ != kUnsetThreadLocalKey);
@@ -111,14 +130,17 @@
     delete thread_list_lock_;
     thread_list_lock_ = NULL;
   }
+#endif
 }
 
 
 OSThread* OSThread::CreateAndSetUnknownThread() {
-  ASSERT(OSThread::Current() == NULL);
-  OSThread* os_thread = new OSThread();
-  OSThread::SetCurrent(os_thread);
-  os_thread->set_name("Unknown");
+  ASSERT(OSThread::GetCurrentTLS() == NULL);
+  OSThread* os_thread = CreateOSThread();
+  if (os_thread != NULL) {
+    OSThread::SetCurrent(os_thread);
+    os_thread->set_name("Unknown");
+  }
   return os_thread;
 }
 
@@ -141,17 +163,29 @@
 }
 
 
+void OSThread::DisableOSThreadCreation() {
+  MutexLocker ml(thread_list_lock_);
+  creation_enabled_ = false;
+}
+
+
+void OSThread::EnableOSThreadCreation() {
+  MutexLocker ml(thread_list_lock_);
+  creation_enabled_ = true;
+}
+
+
 OSThread* OSThread::GetOSThreadFromThread(Thread* thread) {
   ASSERT(thread->os_thread() != NULL);
   return thread->os_thread();
 }
 
 
-void OSThread::AddThreadToList(OSThread* thread) {
+void OSThread::AddThreadToListLocked(OSThread* thread) {
   ASSERT(thread != NULL);
   ASSERT(thread_list_lock_ != NULL);
-  MutexLocker ml(thread_list_lock_);
-
+  ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread());
+  ASSERT(creation_enabled_);
   ASSERT(thread->thread_list_next_ == NULL);
 
 #if defined(DEBUG)
@@ -172,6 +206,7 @@
 
 
 void OSThread::RemoveThreadFromList(OSThread* thread) {
+  bool final_thread = false;
   {
     ASSERT(thread != NULL);
     ASSERT(thread_list_lock_ != NULL);
@@ -189,6 +224,7 @@
           previous->thread_list_next_ = current->thread_list_next_;
         }
         thread->thread_list_next_ = NULL;
+        final_thread = !creation_enabled_  && (thread_list_head_ == NULL);
         break;
       }
       previous = current;
@@ -197,7 +233,7 @@
   }
   // Check if this is the last thread. The last thread does a cleanup
   // which removes the thread local key and the associated mutex.
-  if (thread_list_head_ == NULL) {
+  if (final_thread) {
     Cleanup();
   }
 }
diff --git a/runtime/vm/os_thread.h b/runtime/vm/os_thread.h
index 9371b45..84f11b6a 100644
--- a/runtime/vm/os_thread.h
+++ b/runtime/vm/os_thread.h
@@ -50,7 +50,10 @@
 // Low-level operations on OS platform threads.
 class OSThread : public BaseThread {
  public:
-  OSThread();
+  // The constructor of OSThread is never called directly, instead we call
+  // this factory style method 'CreateOSThread' to create OSThread structures.
+  // The method can return a NULL if the Dart VM is in shutdown mode.
+  static OSThread* CreateOSThread();
   ~OSThread();
 
   ThreadId id() const {
@@ -175,12 +178,19 @@
 
   static bool IsThreadInList(ThreadJoinId join_id);
 
+  static void DisableOSThreadCreation();
+  static void EnableOSThreadCreation();
+
   static const intptr_t kStackSizeBuffer = (4 * KB * kWordSize);
 
   static const ThreadId kInvalidThreadId;
   static const ThreadJoinId kInvalidThreadJoinId;
 
  private:
+  // The constructor is private as CreateOSThread should be used
+  // to create a new OSThread structure.
+  OSThread();
+
   // These methods should not be used in a generic way and hence
   // are private, they have been added to solve the problem of
   // accessing the VM thread structure from an OSThread object
@@ -196,7 +206,7 @@
   static ThreadId GetCurrentThreadTraceId();
   static ThreadJoinId GetCurrentThreadJoinId();
   static OSThread* GetOSThreadFromThread(Thread* thread);
-  static void AddThreadToList(OSThread* thread);
+  static void AddThreadToListLocked(OSThread* thread);
   static void RemoveThreadFromList(OSThread* thread);
   static OSThread* CreateAndSetUnknownThread();
 
@@ -218,8 +228,14 @@
   uword stack_base_;
   Thread* thread_;
 
-  static OSThread* thread_list_head_;
+  // thread_list_lock_ cannot have a static lifetime because the order in which
+  // destructors run is undefined. At the moment this lock cannot be deleted
+  // either since otherwise, if a thread only begins to run after we have
+  // started to run TLS destructors for a call to exit(), there will be a race
+  // on its deletion in CreateOSThread().
   static Mutex* thread_list_lock_;
+  static OSThread* thread_list_head_;
+  static bool creation_enabled_;
 
   friend class OSThreadIterator;
   friend class ThreadInterrupterWin;
diff --git a/runtime/vm/os_thread_android.cc b/runtime/vm/os_thread_android.cc
index 6f7ff34..c02fd9a 100644
--- a/runtime/vm/os_thread_android.cc
+++ b/runtime/vm/os_thread_android.cc
@@ -95,12 +95,14 @@
   delete data;
 
   // Create new OSThread object and set as TLS for new thread.
-  OSThread* thread = new OSThread();
-  OSThread::SetCurrent(thread);
-  thread->set_name(name);
+  OSThread* thread = OSThread::CreateOSThread();
+  if (thread != NULL) {
+    OSThread::SetCurrent(thread);
+    thread->set_name(name);
 
-  // Call the supplied thread start function handing it its parameters.
-  function(parameter);
+    // Call the supplied thread start function handing it its parameters.
+    function(parameter);
+  }
 
   return NULL;
 }
diff --git a/runtime/vm/os_thread_linux.cc b/runtime/vm/os_thread_linux.cc
index 4a08b84..f821233 100644
--- a/runtime/vm/os_thread_linux.cc
+++ b/runtime/vm/os_thread_linux.cc
@@ -97,12 +97,14 @@
   delete data;
 
   // Create new OSThread object and set as TLS for new thread.
-  OSThread* thread = new OSThread();
-  OSThread::SetCurrent(thread);
-  thread->set_name(name);
+  OSThread* thread = OSThread::CreateOSThread();
+  if (thread != NULL) {
+    OSThread::SetCurrent(thread);
+    thread->set_name(name);
 
-  // Call the supplied thread start function handing it its parameters.
-  function(parameter);
+    // Call the supplied thread start function handing it its parameters.
+    function(parameter);
+  }
 
   return NULL;
 }
diff --git a/runtime/vm/os_thread_macos.cc b/runtime/vm/os_thread_macos.cc
index 2fa58d8..1964f64 100644
--- a/runtime/vm/os_thread_macos.cc
+++ b/runtime/vm/os_thread_macos.cc
@@ -88,12 +88,14 @@
   delete data;
 
   // Create new OSThread object and set as TLS for new thread.
-  OSThread* thread = new OSThread();
-  OSThread::SetCurrent(thread);
-  thread->set_name(name);
+  OSThread* thread = OSThread::CreateOSThread();
+  if (thread != NULL) {
+    OSThread::SetCurrent(thread);
+    thread->set_name(name);
 
-  // Call the supplied thread start function handing it its parameters.
-  function(parameter);
+    // Call the supplied thread start function handing it its parameters.
+    function(parameter);
+  }
 
   return NULL;
 }
diff --git a/runtime/vm/os_thread_win.cc b/runtime/vm/os_thread_win.cc
index 52fbd98..7a29d0d 100644
--- a/runtime/vm/os_thread_win.cc
+++ b/runtime/vm/os_thread_win.cc
@@ -52,12 +52,14 @@
   MonitorData::GetMonitorWaitDataForThread();
 
   // Create new OSThread object and set as TLS for new thread.
-  OSThread* thread = new OSThread();
-  OSThread::SetCurrent(thread);
-  thread->set_name(name);
+  OSThread* thread = OSThread::CreateOSThread();
+  if (thread != NULL) {
+    OSThread::SetCurrent(thread);
+    thread->set_name(name);
 
-  // Call the supplied thread start function handing it its parameters.
-  function(parameter);
+    // Call the supplied thread start function handing it its parameters.
+    function(parameter);
+  }
 
   // Clean up the monitor wait data for this thread.
   MonitorWaitData::ThreadExit();
diff --git a/runtime/vm/os_win.cc b/runtime/vm/os_win.cc
index 917ee6f..1e055f4 100644
--- a/runtime/vm/os_win.cc
+++ b/runtime/vm/os_win.cc
@@ -123,7 +123,8 @@
 
 static int64_t qpc_ticks_per_second = 0;
 
-int64_t OS::GetCurrentMonotonicMicros() {
+
+int64_t OS::GetCurrentMonotonicTicks() {
   if (qpc_ticks_per_second == 0) {
     // QueryPerformanceCounter not supported, fallback.
     return GetCurrentTimeMicros();
@@ -131,12 +132,28 @@
   // Grab performance counter value.
   LARGE_INTEGER now;
   QueryPerformanceCounter(&now);
-  int64_t qpc_value = static_cast<int64_t>(now.QuadPart);
+  return static_cast<int64_t>(now.QuadPart);
+}
+
+
+int64_t OS::GetCurrentMonotonicFrequency() {
+  if (qpc_ticks_per_second == 0) {
+    // QueryPerformanceCounter not supported, fallback.
+    return kMicrosecondsPerSecond;
+  }
+  return qpc_ticks_per_second;
+}
+
+
+int64_t OS::GetCurrentMonotonicMicros() {
+  int64_t ticks = GetCurrentMonotonicTicks();
+  int64_t frequency = GetCurrentMonotonicFrequency();
+
   // Convert to microseconds.
-  int64_t seconds = qpc_value / qpc_ticks_per_second;
-  int64_t leftover_ticks = qpc_value - (seconds * qpc_ticks_per_second);
+  int64_t seconds = ticks / frequency;
+  int64_t leftover_ticks = ticks - (seconds * frequency);
   int64_t result = seconds * kMicrosecondsPerSecond;
-  result += ((leftover_ticks * kMicrosecondsPerSecond) / qpc_ticks_per_second);
+  result += ((leftover_ticks * kMicrosecondsPerSecond) / frequency);
   return result;
 }
 
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index 6dc7e93..5d5df0e 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -361,10 +361,10 @@
 
 
 uword PageSpace::TryAllocateInternal(intptr_t size,
-                            HeapPage::PageType type,
-                            GrowthPolicy growth_policy,
-                            bool is_protected,
-                            bool is_locked) {
+                                     HeapPage::PageType type,
+                                     GrowthPolicy growth_policy,
+                                     bool is_protected,
+                                     bool is_locked) {
   ASSERT(size >= kObjectAlignment);
   ASSERT(Utils::IsAligned(size, kObjectAlignment));
 #ifdef DEBUG
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 217354a..a0a0aec 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -48,7 +48,9 @@
 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations.");
 DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef.");
 DEFINE_FLAG(bool, link_natives_lazily, false, "Link native calls lazily");
-DEFINE_FLAG(bool, move_super, false, "Move super initializer to end of list");
+DEFINE_FLAG(bool, move_super, true, "Move super initializer to end of list.");
+DEFINE_FLAG(bool, warn_super, false,
+    "Warning if super initializer not last in initializer list.");
 
 DECLARE_FLAG(bool, lazy_dispatchers);
 DECLARE_FLAG(bool, load_deferred_eagerly);
@@ -821,10 +823,7 @@
                             "ParseClass");
   if (tds.enabled()) {
     tds.SetNumArguments(1);
-    tds.CopyArgument(
-        0,
-        "class",
-        const_cast<char*>(String::Handle(cls.Name()).ToCString()));
+    tds.CopyArgument(0, "class", String::Handle(cls.Name()).ToCString());
   }
   if (!cls.is_synthesized_class()) {
     ASSERT(thread->long_jump_base()->IsSafeToJump());
@@ -945,10 +944,7 @@
   Parser parser(script, parsed_function, func.token_pos());
   if (tds.enabled()) {
     tds.SetNumArguments(1);
-    tds.CopyArgument(
-        0,
-        "function",
-        const_cast<char*>(String::Handle(func.name()).ToCString()));
+    tds.CopyArgument(0, "function", String::Handle(func.name()).ToCString());
   }
   SequenceNode* node_sequence = NULL;
   switch (func.kind()) {
@@ -2816,7 +2812,9 @@
     // A(x) : super(x), f = x++ { ... }
     // is transformed to:
     // A(x) : temp = x, f = x++, super(temp) { ... }
-    ReportWarning("Super initizlizer not at end");
+    if (FLAG_warn_super) {
+      ReportWarning("Super initializer not at end");
+    }
     ASSERT(super_init_index >= 0);
     ArgumentListNode* ctor_args = super_init_call->arguments();
     LetNode* saved_args = new(Z) LetNode(super_init_call->token_pos());
@@ -3125,7 +3123,10 @@
   }
 
   SequenceNode* init_statements = CloseBlock();
-  if (is_redirecting_constructor) {
+  if (FLAG_move_super) {
+    // Ignore the phase parameter.
+    current_block_->statements->Add(init_statements);
+  } else if (is_redirecting_constructor) {
     // A redirecting super constructor simply passes the phase parameter on to
     // the target which executes the corresponding phase.
     current_block_->statements->Add(init_statements);
@@ -3272,24 +3273,29 @@
 
   SequenceNode* ctor_block = CloseBlock();
   if (ctor_block->length() > 0) {
-    // Generate guard around the constructor body code.
-    LocalVariable* phase_param = LookupPhaseParameter();
-    AstNode* phase_value =
-        new LoadLocalNode(Scanner::kNoSourcePos, phase_param);
-    AstNode* phase_check =
-        new BinaryOpNode(Scanner::kNoSourcePos, Token::kBIT_AND,
-            phase_value,
-            new LiteralNode(Scanner::kNoSourcePos,
-                Smi::ZoneHandle(Smi::New(Function::kCtorPhaseBody))));
-    AstNode* comparison =
-        new ComparisonNode(Scanner::kNoSourcePos,
-                           Token::kNE_STRICT,
-                           phase_check,
-                           new LiteralNode(body_pos,
-                                           Smi::ZoneHandle(Smi::New(0))));
-    AstNode* guarded_block_statements =
-        new IfNode(Scanner::kNoSourcePos, comparison, ctor_block, NULL);
-    current_block_->statements->Add(guarded_block_statements);
+    if (FLAG_move_super) {
+      // Ignore the phase parameter.
+      current_block_->statements->Add(ctor_block);
+    } else {
+      // Generate guard around the constructor body code.
+      LocalVariable* phase_param = LookupPhaseParameter();
+      AstNode* phase_value =
+          new LoadLocalNode(Scanner::kNoSourcePos, phase_param);
+      AstNode* phase_check =
+          new BinaryOpNode(Scanner::kNoSourcePos, Token::kBIT_AND,
+              phase_value,
+              new LiteralNode(Scanner::kNoSourcePos,
+                  Smi::ZoneHandle(Smi::New(Function::kCtorPhaseBody))));
+      AstNode* comparison =
+          new ComparisonNode(Scanner::kNoSourcePos,
+                             Token::kNE_STRICT,
+                             phase_check,
+                             new LiteralNode(body_pos,
+                                             Smi::ZoneHandle(Smi::New(0))));
+      AstNode* guarded_block_statements =
+          new IfNode(Scanner::kNoSourcePos, comparison, ctor_block, NULL);
+      current_block_->statements->Add(guarded_block_statements);
+    }
   }
   current_block_->statements->Add(new ReturnNode(func.end_token_pos()));
   SequenceNode* statements = CloseBlock();
@@ -11196,6 +11202,26 @@
     // source.
     if (!FLAG_warn_on_javascript_compatibility || is_patch_source()) {
       ASSERT(num_arguments == 2);
+
+      // If both arguments are constant expressions of type string,
+      // evaluate and canonicalize them.
+      // This guarantees that identical("ab", "a"+"b") is true.
+      // An alternative way to guarantee this would be to introduce
+      // an AST node that canonicalizes a value.
+      AstNode* arg0 = arguments->NodeAt(0);
+      const Instance* val0 = arg0->EvalConstExpr();
+      if ((val0 != NULL) && (val0->IsString())) {
+        AstNode* arg1 = arguments->NodeAt(1);
+        const Instance* val1 = arg1->EvalConstExpr();
+        if ((val1 != NULL) && (val1->IsString())) {
+          arguments->SetNodeAt(0,
+              new(Z) LiteralNode(arg0->token_pos(),
+                                 EvaluateConstExpr(arg0->token_pos(), arg0)));
+          arguments->SetNodeAt(1,
+              new(Z) LiteralNode(arg1->token_pos(),
+                                 EvaluateConstExpr(arg1->token_pos(), arg1)));
+        }
+      }
       return new(Z) ComparisonNode(ident_pos,
                                    Token::kEQ_STRICT,
                                    arguments->NodeAt(0),
@@ -12052,8 +12078,10 @@
   ConstantsMap constants(isolate()->object_store()->compile_time_constants());
   bool is_present = false;
   *value ^= constants.GetOrNull(key, &is_present);
-  ASSERT(constants.Release().raw() ==
-      isolate()->object_store()->compile_time_constants());
+  // Mutator compiler thread may add constants while background compiler
+  // is running , and thus change the value of 'compile_time_constants';
+  // do not assert that 'compile_time_constants' has not changed.
+  constants.Release();
   if (FLAG_compiler_stats && is_present) {
     isolate_->compiler_stats()->num_const_cache_hits++;
   }
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index 0b533f0..93d2107 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -250,8 +250,6 @@
                    "_JavascriptIntegerOverflowError." },
     { "dart:core", "_TypeError", "_TypeError._create" },
     { "dart:isolate", "IsolateSpawnException", "IsolateSpawnException." },
-    { "dart:isolate", "_IsolateUnhandledException",
-                      "_IsolateUnhandledException." },
     { "dart:isolate", "::", "_getIsolateScheduleImmediateClosure" },
     { "dart:isolate", "::", "_setupHooks" },
     { "dart:isolate", "::", "_startMainIsolate" },
@@ -1087,6 +1085,7 @@
   for (intptr_t j = 0; j < closures.Length(); j++) {
     function ^= closures.At(j);
     visitor->VisitFunction(function);
+    ASSERT(!function.HasImplicitClosureFunction());
   }
 }
 
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index ff01393..53f04b6 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -296,6 +296,18 @@
 #endif
 
 
+bool SampleFilter::TimeFilterSample(Sample* sample) {
+  if ((time_origin_micros_ == -1) ||
+      (time_extent_micros_ == -1)) {
+    // No time filter passed in, always pass.
+    return true;
+  }
+  const int64_t timestamp = sample->timestamp();
+  int64_t delta = timestamp - time_origin_micros_;
+  return (delta >= 0) && (delta <= time_extent_micros_);
+}
+
+
 ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate)
     : SampleVisitor(isolate) {
 }
@@ -1208,6 +1220,10 @@
       // No frames.
       continue;
     }
+    if (!filter->TimeFilterSample(sample)) {
+      // Did not pass time filter.
+      continue;
+    }
     if (!filter->FilterSample(sample)) {
       // Did not pass filter.
       continue;
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index e598e70..c755890 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -91,7 +91,15 @@
 
 class SampleFilter : public ValueObject {
  public:
-  explicit SampleFilter(Isolate* isolate) : isolate_(isolate) { }
+  SampleFilter(Isolate* isolate,
+               int64_t time_origin_micros,
+               int64_t time_extent_micros)
+      : isolate_(isolate),
+        time_origin_micros_(time_origin_micros),
+        time_extent_micros_(time_extent_micros) {
+    ASSERT(time_origin_micros_ >= -1);
+    ASSERT(time_extent_micros_ >= -1);
+  }
   virtual ~SampleFilter() { }
 
   // Override this function.
@@ -104,8 +112,14 @@
     return isolate_;
   }
 
+  // Returns |true| if |sample| passes the time filter.
+  bool TimeFilterSample(Sample* sample);
+
  private:
   Isolate* isolate_;
+
+  int64_t time_origin_micros_;
+  int64_t time_extent_micros_;
 };
 
 
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 9a0d5fc..1aba7d3 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -2304,8 +2304,12 @@
 
 class NoAllocationSampleFilter : public SampleFilter {
  public:
-  explicit NoAllocationSampleFilter(Isolate* isolate)
-      : SampleFilter(isolate) {
+  NoAllocationSampleFilter(Isolate* isolate,
+                           int64_t time_origin_micros,
+                           int64_t time_extent_micros)
+      : SampleFilter(isolate,
+                     time_origin_micros,
+                     time_extent_micros) {
   }
 
   bool FilterSample(Sample* sample) {
@@ -2316,10 +2320,14 @@
 
 void ProfilerService::PrintJSON(JSONStream* stream,
                                 Profile::TagOrder tag_order,
-                                intptr_t extra_tags) {
+                                intptr_t extra_tags,
+                                int64_t time_origin_micros,
+                                int64_t time_extent_micros) {
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
-  NoAllocationSampleFilter filter(isolate);
+  NoAllocationSampleFilter filter(isolate,
+                                  time_origin_micros,
+                                  time_extent_micros);
   const bool as_timeline = false;
   PrintJSONImpl(thread, stream, tag_order, extra_tags, &filter, as_timeline);
 }
@@ -2327,8 +2335,13 @@
 
 class ClassAllocationSampleFilter : public SampleFilter {
  public:
-  ClassAllocationSampleFilter(Isolate* isolate, const Class& cls)
-      : SampleFilter(isolate),
+  ClassAllocationSampleFilter(Isolate* isolate,
+                              const Class& cls,
+                              int64_t time_origin_micros,
+                              int64_t time_extent_micros)
+      : SampleFilter(isolate,
+                     time_origin_micros,
+                     time_extent_micros),
         cls_(Class::Handle(cls.raw())) {
     ASSERT(!cls_.IsNull());
   }
@@ -2345,20 +2358,29 @@
 
 void ProfilerService::PrintAllocationJSON(JSONStream* stream,
                                           Profile::TagOrder tag_order,
-                                          const Class& cls) {
+                                          const Class& cls,
+                                          int64_t time_origin_micros,
+                                          int64_t time_extent_micros) {
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
-  ClassAllocationSampleFilter filter(isolate, cls);
+  ClassAllocationSampleFilter filter(isolate,
+                                     cls,
+                                     time_origin_micros,
+                                     time_extent_micros);
   const bool as_timeline = false;
   PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline);
 }
 
 
 void ProfilerService::PrintTimelineJSON(JSONStream* stream,
-                                        Profile::TagOrder tag_order) {
+                                        Profile::TagOrder tag_order,
+                                        int64_t time_origin_micros,
+                                        int64_t time_extent_micros) {
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
-  NoAllocationSampleFilter filter(isolate);
+  NoAllocationSampleFilter filter(isolate,
+                                  time_origin_micros,
+                                  time_extent_micros);
   const bool as_timeline = true;
   PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline);
 }
diff --git a/runtime/vm/profiler_service.h b/runtime/vm/profiler_service.h
index e931598..15f3f7d 100644
--- a/runtime/vm/profiler_service.h
+++ b/runtime/vm/profiler_service.h
@@ -396,14 +396,20 @@
 
   static void PrintJSON(JSONStream* stream,
                         Profile::TagOrder tag_order,
-                        intptr_t extra_tags);
+                        intptr_t extra_tags,
+                        int64_t time_origin_micros,
+                        int64_t time_extent_micros);
 
   static void PrintAllocationJSON(JSONStream* stream,
                                   Profile::TagOrder tag_order,
-                                  const Class& cls);
+                                  const Class& cls,
+                                  int64_t time_origin_micros,
+                                  int64_t time_extent_micros);
 
   static void PrintTimelineJSON(JSONStream* stream,
-                                Profile::TagOrder tag_order);
+                                Profile::TagOrder tag_order,
+                                int64_t time_origin_micros,
+                                int64_t time_extent_micros);
 
   static void ClearSamples();
 
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index a35da30..3533851 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -149,8 +149,13 @@
 
 class AllocationFilter : public SampleFilter {
  public:
-  explicit AllocationFilter(Isolate* isolate, intptr_t cid)
-      : SampleFilter(isolate),
+  AllocationFilter(Isolate* isolate,
+                   intptr_t cid,
+                   int64_t time_origin_micros = -1,
+                   int64_t time_extent_micros = -1)
+      : SampleFilter(isolate,
+                     time_origin_micros,
+                     time_extent_micros),
         cid_(cid),
         enable_vm_ticks_(false) {
   }
@@ -196,6 +201,7 @@
   Library& root_library = Library::Handle();
   root_library ^= Api::UnwrapHandle(lib);
 
+  const int64_t before_allocations_micros = Dart_TimelineGetMicros();
   const Class& class_a = Class::Handle(GetClass(root_library, "A"));
   EXPECT(!class_a.IsNull());
   class_a.SetTraceAllocation(true);
@@ -203,14 +209,20 @@
   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
   EXPECT_VALID(result);
 
-
+  const int64_t after_allocations_micros = Dart_TimelineGetMicros();
+  const int64_t allocation_extent_micros =
+      after_allocations_micros - before_allocations_micros;
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
-    AllocationFilter filter(isolate, class_a.id());
+    // Filter for the class in the time range.
+    AllocationFilter filter(isolate,
+                            class_a.id(),
+                            before_allocations_micros,
+                            allocation_extent_micros);
     profile.Build(thread, &filter, Profile::kNoTags);
     // We should have 1 allocation sample.
     EXPECT_EQ(1, profile.sample_count());
@@ -252,6 +264,23 @@
     EXPECT_STREQ("B.boo", walker.CurrentName());
     EXPECT(!walker.Down());
   }
+
+  // Query with a time filter where no allocations occurred.
+  {
+    Thread* thread = Thread::Current();
+    Isolate* isolate = thread->isolate();
+    StackZone zone(thread);
+    HANDLESCOPE(thread);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate,
+                            class_a.id(),
+                            Dart_TimelineGetMicros(),
+                            16000);
+    profile.Build(thread, &filter, Profile::kNoTags);
+    // We should have no allocation samples because none occured within
+    // the specified time range.
+    EXPECT_EQ(0, profile.sample_count());
+  }
 }
 
 
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index df2902c..ee5450d 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1402,10 +1402,10 @@
   RawObject** from() {
     return reinterpret_cast<RawObject**>(&ptr()->owner_);
   }
-  RawFunction* owner_;         // Parent/calling function of this IC.
-  RawString* target_name_;     // Name of target function.
+  RawObject* owner_;  // Parent/calling function or original IC of cloned IC.
+  RawString* target_name_;  // Name of target function.
   RawArray* args_descriptor_;  // Arguments descriptor.
-  RawArray* ic_data_;          // Contains class-ids, target and count.
+  RawArray* ic_data_;  // Contains class-ids, target and count.
   RawObject** to() {
     return reinterpret_cast<RawObject**>(&ptr()->ic_data_);
   }
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index c8c4249..4735b51 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -476,6 +476,36 @@
 };
 
 
+class Int64Parameter : public MethodParameter {
+ public:
+  Int64Parameter(const char* name, bool required)
+      : MethodParameter(name, required) {
+  }
+
+  virtual bool Validate(const char* value) const {
+    if (value == NULL) {
+      return false;
+    }
+    for (const char* cp = value; *cp != '\0'; cp++) {
+      if ((*cp < '0' || *cp > '9') && (*cp != '-')) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  static int64_t Parse(const char* value, int64_t default_value = -1) {
+    if ((value == NULL) || (*value == '\0')) {
+      return default_value;
+    }
+    char* end_ptr = NULL;
+    int64_t result = strtoll(value, &end_ptr, 10);
+    ASSERT(*end_ptr == '\0');  // Parsed full string
+    return result;
+  }
+};
+
+
 class IdParameter : public MethodParameter {
  public:
   IdParameter(const char* name, bool required)
@@ -2605,6 +2635,8 @@
 
 static const MethodParameter* get_vm_timeline_params[] = {
   NO_ISOLATE_PARAMETER,
+  new Int64Parameter("timeOriginMicros", false),
+  new Int64Parameter("timeExtentMicros", false),
   NULL,
 };
 
@@ -2617,7 +2649,11 @@
   TimelineEventRecorder* timeline_recorder = Timeline::recorder();
   // TODO(johnmccutchan): Return an error.
   ASSERT(timeline_recorder != NULL);
-  TimelineEventFilter filter;
+  int64_t time_origin_micros =
+      Int64Parameter::Parse(js->LookupParam("timeOriginMicros"));
+  int64_t time_extent_micros =
+      Int64Parameter::Parse(js->LookupParam("timeExtentMicros"));
+  TimelineEventFilter filter(time_origin_micros, time_extent_micros);
   timeline_recorder->PrintJSON(js, &filter);
   return true;
 }
@@ -2733,6 +2769,8 @@
   ISOLATE_PARAMETER,
   new EnumParameter("tags", true, tags_enum_names),
   new BoolParameter("_codeTransitionTags", false),
+  new Int64Parameter("timeOriginMicros", false),
+  new Int64Parameter("timeExtentMicros", false),
   NULL,
 };
 
@@ -2745,7 +2783,15 @@
   if (BoolParameter::Parse(js->LookupParam("_codeTransitionTags"))) {
     extra_tags |= ProfilerService::kCodeTransitionTagsBit;
   }
-  ProfilerService::PrintJSON(js, tag_order, extra_tags);
+  int64_t time_origin_micros =
+      Int64Parameter::Parse(js->LookupParam("timeOriginMicros"));
+  int64_t time_extent_micros =
+      Int64Parameter::Parse(js->LookupParam("timeExtentMicros"));
+  ProfilerService::PrintJSON(js,
+                             tag_order,
+                             extra_tags,
+                             time_origin_micros,
+                             time_extent_micros);
   return true;
 }
 
@@ -2753,6 +2799,8 @@
 static const MethodParameter* get_cpu_profile_timeline_params[] = {
   ISOLATE_PARAMETER,
   new EnumParameter("tags", true, tags_enum_names),
+  new Int64Parameter("timeOriginMicros", false),
+  new Int64Parameter("timeExtentMicros", false),
   NULL,
 };
 
@@ -2760,7 +2808,14 @@
 static bool GetCpuProfileTimeline(Thread* thread, JSONStream* js) {
   Profile::TagOrder tag_order =
       EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values);
-  ProfilerService::PrintTimelineJSON(js, tag_order);
+  int64_t time_origin_micros =
+      UIntParameter::Parse(js->LookupParam("timeOriginMicros"));
+  int64_t time_extent_micros =
+      UIntParameter::Parse(js->LookupParam("timeExtentMicros"));
+  ProfilerService::PrintTimelineJSON(js,
+                                     tag_order,
+                                     time_origin_micros,
+                                     time_extent_micros);
   return true;
 }
 
@@ -2769,6 +2824,8 @@
   ISOLATE_PARAMETER,
   new EnumParameter("tags", true, tags_enum_names),
   new IdParameter("classId", false),
+  new Int64Parameter("timeOriginMicros", false),
+  new Int64Parameter("timeExtentMicros", false),
   NULL,
 };
 
@@ -2776,13 +2833,21 @@
 static bool GetAllocationSamples(Thread* thread, JSONStream* js) {
   Profile::TagOrder tag_order =
       EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values);
+  int64_t time_origin_micros =
+      Int64Parameter::Parse(js->LookupParam("timeOriginMicros"));
+  int64_t time_extent_micros =
+      Int64Parameter::Parse(js->LookupParam("timeExtentMicros"));
   const char* class_id = js->LookupParam("classId");
   intptr_t cid = -1;
   GetPrefixedIntegerId(class_id, "classes/", &cid);
   Isolate* isolate = thread->isolate();
   if (IsValidClassId(isolate, cid)) {
     const Class& cls = Class::Handle(GetClassForId(isolate, cid));
-    ProfilerService::PrintAllocationJSON(js, tag_order, cls);
+    ProfilerService::PrintAllocationJSON(js,
+                                         tag_order,
+                                         cls,
+                                         time_origin_micros,
+                                         time_extent_micros);
   } else {
     PrintInvalidParamError(js, "classId");
   }
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
new file mode 100644
index 0000000..242957b
--- /dev/null
+++ b/runtime/vm/source_report.cc
@@ -0,0 +1,318 @@
+// 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.
+
+#include "vm/source_report.h"
+
+#include "vm/compiler.h"
+#include "vm/object.h"
+#include "vm/object_store.h"
+
+namespace dart {
+
+SourceReport::SourceReport(ReportKind report_kind, CompileMode compile_mode)
+    : report_kind_(report_kind),
+      compile_mode_(compile_mode),
+      thread_(NULL),
+      script_(NULL),
+      start_pos_(-1),
+      end_pos_(-1),
+      next_script_index_(0) {
+}
+
+
+void SourceReport::Init(Thread* thread,
+                        const Script* script,
+                        intptr_t start_pos,
+                        intptr_t end_pos) {
+  thread_ = thread;
+  script_ = script;
+  start_pos_ = start_pos;
+  end_pos_ = end_pos;
+  script_table_entries_.Clear();
+  script_table_.Clear();
+  next_script_index_ = 0;
+}
+
+
+bool SourceReport::ShouldSkipFunction(const Function& func) {
+  if (script_ != NULL && !script_->IsNull()) {
+    if (func.script() != script_->raw()) {
+      // The function is from the wrong script.
+      return true;
+    }
+    if (((start_pos_ > 0) && (func.end_token_pos() < start_pos_)) ||
+        ((end_pos_ > 0) && (func.token_pos() > end_pos_))) {
+      // The function does not intersect with the requested token range.
+      return true;
+    }
+  }
+
+  switch (func.kind()) {
+    case RawFunction::kRegularFunction:
+    case RawFunction::kClosureFunction:
+    case RawFunction::kGetterFunction:
+    case RawFunction::kSetterFunction:
+    case RawFunction::kConstructor:
+      break;
+    default:
+      return true;
+  }
+  if (func.is_abstract() ||
+      func.IsImplicitConstructor() ||
+      func.IsRedirectingFactory()) {
+    return true;
+  }
+  if (func.IsNonImplicitClosureFunction() &&
+      (func.context_scope() == ContextScope::null())) {
+    // TODO(iposva): This can arise if we attempt to compile an inner function
+    // before we have compiled its enclosing function or if the enclosing
+    // function failed to compile.
+    return true;
+  }
+  return false;
+}
+
+
+intptr_t SourceReport::GetScriptIndex(const Script& script) {
+  const String& url = String::Handle(zone(), script.url());
+  ScriptTableEntry* pair = script_table_.Lookup(&url);
+  if (pair != NULL) {
+    return pair->index;
+  }
+
+  ScriptTableEntry tmp;
+  tmp.key = &url;
+  tmp.index = next_script_index_++;
+  tmp.script = &script;
+  script_table_entries_.Add(tmp);
+  script_table_.Insert(&(script_table_entries_.Last()));
+  return tmp.index;
+}
+
+
+bool SourceReport::ScriptIsLoadedByLibrary(const Script& script,
+                                           const Library& lib) {
+  const Array& scripts = Array::Handle(zone(), lib.LoadedScripts());
+  for (intptr_t j = 0; j < scripts.Length(); j++) {
+    if (scripts.At(j) == script.raw()) {
+      return true;
+    }
+  }
+  return false;
+}
+
+
+void SourceReport::PrintCallSitesData(JSONObject* jsobj,
+                                      const Function& func,
+                                      const Code& code) {
+  const intptr_t begin_pos = func.token_pos();
+  const intptr_t end_pos = func.end_token_pos();
+
+  ZoneGrowableArray<const ICData*>* ic_data_array =
+      new(zone()) ZoneGrowableArray<const ICData*>();
+  func.RestoreICDataMap(ic_data_array, false /* clone descriptors */);
+  const PcDescriptors& descriptors = PcDescriptors::Handle(
+      zone(), code.pc_descriptors());
+
+  JSONArray sites(jsobj, "callSites");
+
+  PcDescriptors::Iterator iter(
+      descriptors,
+      RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall);
+  while (iter.MoveNext()) {
+    HANDLESCOPE(thread());
+    const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
+    if (!ic_data->IsNull()) {
+      const intptr_t token_pos = iter.TokenPos();
+      if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+        // Does not correspond to a valid source position.
+        continue;
+      }
+      bool is_static_call = iter.Kind() == RawPcDescriptors::kUnoptStaticCall;
+      ic_data->PrintToJSONArrayNew(sites, token_pos, is_static_call);
+    }
+  }
+}
+
+void SourceReport::PrintCoverageData(JSONObject* jsobj,
+                                     const Function& func,
+                                     const Code& code) {
+  const intptr_t begin_pos = func.token_pos();
+  const intptr_t end_pos = func.end_token_pos();
+
+  ZoneGrowableArray<const ICData*>* ic_data_array =
+      new(zone()) ZoneGrowableArray<const ICData*>();
+  func.RestoreICDataMap(ic_data_array, false /* clone descriptors */);
+  const PcDescriptors& descriptors = PcDescriptors::Handle(
+      zone(), code.pc_descriptors());
+
+  const int kCoverageNone = 0;
+  const int kCoverageMiss = 1;
+  const int kCoverageHit = 2;
+
+  intptr_t func_length = (end_pos - begin_pos) + 1;
+  GrowableArray<char> coverage(func_length);
+  coverage.SetLength(func_length);
+  for (int i = 0; i < func_length; i++) {
+    coverage[i] = kCoverageNone;
+  }
+
+  PcDescriptors::Iterator iter(
+      descriptors,
+      RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall);
+  while (iter.MoveNext()) {
+    HANDLESCOPE(thread());
+    const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
+    if (!ic_data->IsNull()) {
+      const intptr_t token_pos = iter.TokenPos();
+      if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+        // Does not correspond to a valid source position.
+        continue;
+      }
+      intptr_t count = ic_data->AggregateCount();
+      intptr_t token_offset = token_pos - begin_pos;
+      if (count > 0) {
+        coverage[token_offset] = kCoverageHit;
+      } else {
+        if (coverage[token_offset] == kCoverageNone) {
+          coverage[token_offset] = kCoverageMiss;
+        }
+      }
+    }
+  }
+
+  JSONObject cov(jsobj, "coverage");
+  {
+    JSONArray hits(&cov, "hits");
+    for (int i = 0; i < func_length; i++) {
+      if (coverage[i] == kCoverageHit) {
+        hits.AddValue(begin_pos + i);  // Add the token position of the hit.
+      }
+    }
+  }
+  {
+    JSONArray misses(&cov, "misses");
+    for (int i = 0; i < func_length; i++) {
+      if (coverage[i] == kCoverageMiss) {
+        misses.AddValue(begin_pos + i);  // Add the token position of the miss.
+      }
+    }
+  }
+}
+
+
+void SourceReport::PrintScriptTable(JSONArray* scripts) {
+  for (int i = 0; i < script_table_entries_.length(); i++) {
+    const Script* script = script_table_entries_[i].script;
+    scripts->AddValue(*script);
+  }
+}
+
+
+void SourceReport::VisitFunction(JSONArray* jsarr, const Function& func) {
+  if (ShouldSkipFunction(func)) {
+    return;
+  }
+
+  const Script& script = Script::Handle(zone(), func.script());
+  const intptr_t begin_pos = func.token_pos();
+  const intptr_t end_pos = func.end_token_pos();
+
+  Code& code = Code::Handle(zone(), func.unoptimized_code());
+  if (code.IsNull()) {
+    if (func.HasCode() || (compile_mode_ == kForceCompile)) {
+      if (Compiler::EnsureUnoptimizedCode(thread(), func) != Error::null()) {
+        // Ignore the error and this function entirely.
+        return;
+      }
+      code = func.unoptimized_code();
+    } else {
+      // This function has not been compiled yet.
+      JSONObject range(jsarr);
+      range.AddProperty("scriptIndex", GetScriptIndex(script));
+      range.AddProperty("startPos", begin_pos);
+      range.AddProperty("endPos", end_pos);
+      range.AddProperty("compiled", false);
+      return;
+    }
+  }
+  ASSERT(!code.IsNull());
+
+  JSONObject range(jsarr);
+  range.AddProperty("scriptIndex", GetScriptIndex(script));
+  range.AddProperty("startPos", begin_pos);
+  range.AddProperty("endPos", end_pos);
+  range.AddProperty("compiled", true);
+
+  if (report_kind_ == kCallSites) {
+    PrintCallSitesData(&range, func, code);
+  } else if (report_kind_ == kCoverage) {
+    PrintCoverageData(&range, func, code);
+  }
+}
+
+
+void SourceReport::VisitLibrary(JSONArray* jsarr, const Library& lib) {
+  Class& cls = Class::Handle(zone());
+  Array& functions = Array::Handle(zone());
+  Function& func = Function::Handle(zone());
+  ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+  while (it.HasNext()) {
+    cls = it.GetNextClass();
+    functions = cls.functions();
+    for (int i = 0; i < functions.Length(); i++) {
+      func ^= functions.At(i);
+      VisitFunction(jsarr, func);
+    }
+  }
+}
+
+
+void SourceReport::VisitClosures(JSONArray* jsarr) {
+  const GrowableObjectArray& closures = GrowableObjectArray::Handle(
+      thread()->isolate()->object_store()->closure_functions());
+
+  // We need to keep rechecking the length of the closures array, as handling
+  // a closure potentially adds new entries to the end.
+  Function& func = Function::Handle(zone());
+  for (int i = 0; i < closures.Length(); i++) {
+    func ^= closures.At(i);
+    VisitFunction(jsarr, func);
+  }
+}
+
+
+void SourceReport::PrintJSON(JSONStream* js,
+                             const Script& script,
+                             intptr_t start_pos, intptr_t end_pos) {
+  Init(Thread::Current(), &script, start_pos, end_pos);
+
+  JSONObject report(js);
+  report.AddProperty("type", "SourceReport");
+  {
+    JSONArray ranges(&report, "ranges");
+
+    const GrowableObjectArray& libs = GrowableObjectArray::Handle(
+        zone(), thread()->isolate()->object_store()->libraries());
+
+    // We only visit the libraries which actually load the specified script.
+    Library& lib = Library::Handle(zone());
+    for (int i = 0; i < libs.Length(); i++) {
+      lib ^= libs.At(i);
+      if (script.IsNull() || ScriptIsLoadedByLibrary(script, lib)) {
+        VisitLibrary(&ranges, lib);
+      }
+    }
+
+    // Visit all closures for this isolate.
+    VisitClosures(&ranges);
+  }
+
+  // Print the script table.
+  JSONArray scripts(&report, "scripts");
+  PrintScriptTable(&scripts);
+}
+
+
+}  // namespace dart
diff --git a/runtime/vm/source_report.h b/runtime/vm/source_report.h
new file mode 100644
index 0000000..69529d3
--- /dev/null
+++ b/runtime/vm/source_report.h
@@ -0,0 +1,106 @@
+// 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.
+
+#ifndef VM_SOURCE_REPORT_H_
+#define VM_SOURCE_REPORT_H_
+
+#include "vm/allocation.h"
+#include "vm/flags.h"
+#include "vm/hash_map.h"
+#include "vm/object.h"
+
+namespace dart {
+
+// A SourceReport object is used to generate reports about the program
+// source code, with information associated with source token
+// positions.  There are multiple possible kinds of reports.
+class SourceReport {
+ public:
+  enum ReportKind {
+    kCallSites,
+    kCoverage,
+  };
+
+  enum CompileMode {
+    kNoCompile,
+    kForceCompile
+  };
+
+  explicit SourceReport(ReportKind report_kind,
+                        CompileMode compile = kNoCompile);
+
+  // Generate a source report for (some subrange of) a script.
+  //
+  // If script is null, then the report is generated for all scripts
+  // in the isolate.
+  void PrintJSON(JSONStream* js, const Script& script,
+                 intptr_t start_pos = -1, intptr_t end_pos = -1);
+
+ private:
+  void Init(Thread* thread, const Script* script,
+            intptr_t start_pos, intptr_t end_pos);
+
+  Thread* thread() const { return thread_; }
+  Zone* zone() const { return thread_->zone(); }
+
+  bool ShouldSkipFunction(const Function& func);
+  intptr_t GetScriptIndex(const Script& script);
+  bool ScriptIsLoadedByLibrary(const Script& script, const Library& lib);
+
+  void PrintCallSitesData(JSONObject* jsobj,
+                          const Function& func, const Code& code);
+  void PrintCoverageData(JSONObject* jsobj,
+                         const Function& func, const Code& code);
+  void PrintScriptTable(JSONArray* jsarr);
+
+  void VisitFunction(JSONArray* jsarr, const Function& func);
+  void VisitLibrary(JSONArray* jsarr, const Library& lib);
+  void VisitClosures(JSONArray* jsarr);
+
+  // An entry in the script table.
+  struct ScriptTableEntry {
+    ScriptTableEntry() : key(NULL), index(-1), script(NULL) {}
+
+    const String* key;
+    intptr_t index;
+    const Script* script;
+  };
+
+  // Needed for DirectChainedHashMap.
+  struct ScriptTableTrait {
+    typedef ScriptTableEntry* Value;
+    typedef const String* Key;
+    typedef ScriptTableEntry* Pair;
+
+    static Key KeyOf(Pair kv) {
+      return kv->key;
+    }
+
+    static Value ValueOf(Pair kv) {
+      return kv;
+    }
+
+    static inline intptr_t Hashcode(Key key) {
+      return key->Hash();
+    }
+
+    static inline bool IsKeyEqual(Pair kv, Key key) {
+      return kv->key->Equals(*key);
+    }
+  };
+
+  ReportKind report_kind_;
+  CompileMode compile_mode_;
+  Thread* thread_;
+  const Script* script_;
+  intptr_t start_pos_;
+  intptr_t end_pos_;
+  GrowableArray<ScriptTableEntry> script_table_entries_;
+  DirectChainedHashMap<ScriptTableTrait> script_table_;
+  intptr_t next_script_index_;
+};
+
+}  // namespace dart
+
+#endif  // VM_SOURCE_REPORT_H_
diff --git a/runtime/vm/source_report_test.cc b/runtime/vm/source_report_test.cc
new file mode 100644
index 0000000..075ac36
--- /dev/null
+++ b/runtime/vm/source_report_test.cc
@@ -0,0 +1,412 @@
+// 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.
+
+#include "vm/source_report.h"
+#include "vm/dart_api_impl.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+static RawObject* ExecuteScript(const char* script) {
+  Dart_Handle h_lib = TestCase::LoadTestScript(script, NULL);
+  EXPECT_VALID(h_lib);
+  Library& lib = Library::Handle();
+  lib ^= Api::UnwrapHandle(h_lib);
+  EXPECT(!lib.IsNull());
+  Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+  return Api::UnwrapHandle(h_lib);
+}
+
+
+TEST_CASE(SourceReport_Coverage_NoCalls) {
+  char buffer[1024];
+  const char* kScript =
+      "main() {\n"
+      "}";
+
+  Library& lib = Library::Handle();
+  lib ^= ExecuteScript(kScript);
+  ASSERT(!lib.IsNull());
+  const Script& script = Script::Handle(lib.LookupScript(
+      String::Handle(String::New("test-lib"))));
+
+  SourceReport report(SourceReport::kCoverage);
+  JSONStream js;
+  report.PrintJSON(&js, script);
+  ElideJSONSubstring("libraries", js.ToCString(), buffer);
+  EXPECT_STREQ(
+      "{\"type\":\"SourceReport\",\"ranges\":"
+
+      // One compiled range, no hits or misses.
+      "[{\"scriptIndex\":0,\"startPos\":0,\"endPos\":5,\"compiled\":true,"
+      "\"coverage\":{\"hits\":[],\"misses\":[]}}],"
+
+      // One script in the script table.
+      "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+      "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
+      buffer);
+}
+
+
+TEST_CASE(SourceReport_Coverage_SimpleCall) {
+  char buffer[1024];
+  const char* kScript =
+      "helper0() {}\n"
+      "helper1() {}\n"
+      "main() {\n"
+      "  if (true) {\n"
+      "    helper0();\n"
+      "  } else {\n"
+      "    helper1();\n"
+      "  }\n"
+      "}";
+
+  Library& lib = Library::Handle();
+  lib ^= ExecuteScript(kScript);
+  ASSERT(!lib.IsNull());
+  const Script& script = Script::Handle(lib.LookupScript(
+      String::Handle(String::New("test-lib"))));
+
+  SourceReport report(SourceReport::kCoverage);
+  JSONStream js;
+  report.PrintJSON(&js, script);
+  ElideJSONSubstring("classes", js.ToCString(), buffer);
+  ElideJSONSubstring("libraries", buffer, buffer);
+  EXPECT_STREQ(
+      "{\"type\":\"SourceReport\",\"ranges\":["
+
+      // One range compiled with no hits or misses (helper0).
+      "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":4,\"compiled\":true,"
+      "\"coverage\":{\"hits\":[],\"misses\":[]}},"
+
+      // One range not compiled (helper1).
+      "{\"scriptIndex\":0,\"startPos\":6,\"endPos\":10,\"compiled\":false},"
+
+      // One range with a hit and a miss (main).
+      "{\"scriptIndex\":0,\"startPos\":12,\"endPos\":39,\"compiled\":true,"
+      "\"coverage\":{\"hits\":[23],\"misses\":[32]}}],"
+
+      // Only one script in the script table.
+      "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+      "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
+      buffer);
+}
+
+
+TEST_CASE(SourceReport_Coverage_ForceCompile) {
+  char buffer[1024];
+  const char* kScript =
+      "helper0() {}\n"
+      "helper1() {}\n"
+      "main() {\n"
+      "  if (true) {\n"
+      "    helper0();\n"
+      "  } else {\n"
+      "    helper1();\n"
+      "  }\n"
+      "}";
+
+  Library& lib = Library::Handle();
+  lib ^= ExecuteScript(kScript);
+  ASSERT(!lib.IsNull());
+  const Script& script = Script::Handle(lib.LookupScript(
+      String::Handle(String::New("test-lib"))));
+
+  SourceReport report(SourceReport::kCoverage, SourceReport::kForceCompile);
+  JSONStream js;
+  report.PrintJSON(&js, script);
+  ElideJSONSubstring("classes", js.ToCString(), buffer);
+  ElideJSONSubstring("libraries", buffer, buffer);
+  EXPECT_STREQ(
+      "{\"type\":\"SourceReport\",\"ranges\":["
+
+      // One range compiled with no hits or misses (helper0).
+      "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":4,\"compiled\":true,"
+      "\"coverage\":{\"hits\":[],\"misses\":[]}},"
+
+      // This range is compiled even though it wasn't called (helper1).
+      "{\"scriptIndex\":0,\"startPos\":6,\"endPos\":10,\"compiled\":true,"
+      "\"coverage\":{\"hits\":[],\"misses\":[]}},"
+
+      // One range with a hit and a miss (main).
+      "{\"scriptIndex\":0,\"startPos\":12,\"endPos\":39,\"compiled\":true,"
+      "\"coverage\":{\"hits\":[23],\"misses\":[32]}}],"
+
+      // Only one script in the script table.
+      "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+      "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
+      buffer);
+}
+
+
+TEST_CASE(SourceReport_Coverage_NestedFunctions) {
+  char buffer[1024];
+  const char* kScript =
+      "helper0() {\n"
+      "  nestedHelper0() {}\n"
+      "  nestedHelper1() {}\n"
+      "  nestedHelper0();\n"
+      "}\n"
+      "helper1() {}\n"
+      "main() {\n"
+      "  if (true) {\n"
+      "    helper0();\n"
+      "  } else {\n"
+      "    helper1();\n"
+      "  }\n"
+      "}";
+
+  Library& lib = Library::Handle();
+  lib ^= ExecuteScript(kScript);
+  ASSERT(!lib.IsNull());
+  const Script& script = Script::Handle(lib.LookupScript(
+      String::Handle(String::New("test-lib"))));
+
+  SourceReport report(SourceReport::kCoverage);
+  JSONStream js;
+  report.PrintJSON(&js, script);
+  ElideJSONSubstring("classes", js.ToCString(), buffer);
+  ElideJSONSubstring("libraries", buffer, buffer);
+  EXPECT_STREQ(
+      "{\"type\":\"SourceReport\",\"ranges\":["
+
+      // One range compiled with one hit (helper0).
+      "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":22,\"compiled\":true,"
+      "\"coverage\":{\"hits\":[18],\"misses\":[]}},"
+
+      // One range not compiled (helper1).
+      "{\"scriptIndex\":0,\"startPos\":24,\"endPos\":28,\"compiled\":false},"
+
+      // One range with a hit and a miss (main).
+      "{\"scriptIndex\":0,\"startPos\":30,\"endPos\":57,\"compiled\":true,"
+      "\"coverage\":{\"hits\":[41],\"misses\":[50]}},"
+
+      // Nested range compiled (nestedHelper0).
+      "{\"scriptIndex\":0,\"startPos\":5,\"endPos\":9,\"compiled\":true,"
+      "\"coverage\":{\"hits\":[],\"misses\":[]}},"
+
+      // Nested range not compiled (nestedHelper1).
+      "{\"scriptIndex\":0,\"startPos\":11,\"endPos\":15,\"compiled\":false}],"
+
+      // Only one script in the script table.
+      "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+      "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
+      buffer);
+}
+
+
+TEST_CASE(SourceReport_Coverage_RestrictedRange) {
+  char buffer[1024];
+  const char* kScript =
+      "helper0() {\n"
+      "  nestedHelper0() {}\n"
+      "  nestedHelper1() {}\n"
+      "  nestedHelper0();\n"
+      "}\n"
+      "helper1() {}\n"
+      "main() {\n"
+      "  if (true) {\n"
+      "    helper0();\n"
+      "  } else {\n"
+      "    helper1();\n"
+      "  }\n"
+      "}";
+
+  Library& lib = Library::Handle();
+  lib ^= ExecuteScript(kScript);
+  ASSERT(!lib.IsNull());
+  const Script& script = Script::Handle(lib.LookupScript(
+      String::Handle(String::New("test-lib"))));
+  const Function& helper = Function::Handle(
+      lib.LookupLocalFunction(String::Handle(String::New("helper0"))));
+
+  SourceReport report(SourceReport::kCoverage);
+  JSONStream js;
+  // Restrict the report to only helper0 and it's nested functions.
+  report.PrintJSON(&js, script, helper.token_pos(), helper.end_token_pos());
+  ElideJSONSubstring("classes", js.ToCString(), buffer);
+  ElideJSONSubstring("libraries", buffer, buffer);
+  EXPECT_STREQ(
+      "{\"type\":\"SourceReport\",\"ranges\":["
+
+      // One range compiled with one hit (helper0).
+      "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":22,\"compiled\":true,"
+      "\"coverage\":{\"hits\":[18],\"misses\":[]}},"
+
+      // Nested range compiled (nestedHelper0).
+      "{\"scriptIndex\":0,\"startPos\":5,\"endPos\":9,\"compiled\":true,"
+      "\"coverage\":{\"hits\":[],\"misses\":[]}},"
+
+      // Nested range not compiled (nestedHelper1).
+      "{\"scriptIndex\":0,\"startPos\":11,\"endPos\":15,\"compiled\":false}],"
+
+      // Only one script in the script table.
+      "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+      "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
+      buffer);
+}
+
+
+TEST_CASE(SourceReport_Coverage_AllFunctions) {
+  const char* kScript =
+      "helper0() {}\n"
+      "helper1() {}\n"
+      "main() {\n"
+      "  if (true) {\n"
+      "    helper0();\n"
+      "  } else {\n"
+      "    helper1();\n"
+      "  }\n"
+      "}";
+
+  Library& lib = Library::Handle();
+  lib ^= ExecuteScript(kScript);
+  ASSERT(!lib.IsNull());
+
+  SourceReport report(SourceReport::kCoverage);
+  JSONStream js;
+
+  // We generate a report with all functions in the VM.
+  Script& null_script = Script::Handle();
+  report.PrintJSON(&js, null_script);
+  const char* result = js.ToCString();
+
+  // Sanity check the header.
+  EXPECT_SUBSTRING("{\"type\":\"SourceReport\",\"ranges\":[", result);
+
+  // Make sure that the main function was found.
+  EXPECT_SUBSTRING(
+      "\"startPos\":12,\"endPos\":39,\"compiled\":true,"
+      "\"coverage\":{\"hits\":[23],\"misses\":[32]}",
+      result);
+
+  // More than one script is referenced in the report.
+  EXPECT_SUBSTRING("\"scriptIndex\":0", result);
+  EXPECT_SUBSTRING("\"scriptIndex\":1", result);
+  EXPECT_SUBSTRING("\"scriptIndex\":2", result);
+}
+
+
+TEST_CASE(SourceReport_CallSites_SimpleCall) {
+  char buffer[1024];
+  const char* kScript =
+      "helper0() {}\n"
+      "helper1() {}\n"
+      "main() {\n"
+      "  helper0();\n"
+      "}";
+
+  Library& lib = Library::Handle();
+  lib ^= ExecuteScript(kScript);
+  ASSERT(!lib.IsNull());
+  const Script& script = Script::Handle(lib.LookupScript(
+      String::Handle(String::New("test-lib"))));
+
+  SourceReport report(SourceReport::kCallSites);
+  JSONStream js;
+  report.PrintJSON(&js, script);
+  ElideJSONSubstring("classes", js.ToCString(), buffer);
+  ElideJSONSubstring("libraries", buffer, buffer);
+  EXPECT_STREQ(
+      "{\"type\":\"SourceReport\",\"ranges\":["
+
+      // One range compiled with no callsites (helper0).
+      "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":4,\"compiled\":true,"
+      "\"callSites\":[]},"
+
+      // One range not compiled (helper1).
+      "{\"scriptIndex\":0,\"startPos\":6,\"endPos\":10,\"compiled\":false},"
+
+      // One range compiled with one callsite (main).
+      "{\"scriptIndex\":0,\"startPos\":12,\"endPos\":22,\"compiled\":true,"
+      "\"callSites\":["
+      "{\"name\":\"helper0\",\"tokenPos\":17,\"cacheEntries\":["
+      "{\"target\":{\"type\":\"@Function\",\"fixedId\":true,\"id\":\"\","
+      "\"name\":\"helper0\",\"owner\":{\"type\":\"@Library\",\"fixedId\":true,"
+      "\"id\":\"\",\"name\":\"\",\"uri\":\"test-lib\"},"
+      "\"_kind\":\"RegularFunction\",\"static\":true,\"const\":false,"
+      "\"_intrinsic\":false,\"_native\":false},\"count\":1}]}]}],"
+
+      // One script in the script table.
+      "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+      "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
+      buffer);
+}
+
+TEST_CASE(SourceReport_CallSites_PolymorphicCall) {
+  char buffer[1024];
+  const char* kScript =
+      "class Common {\n"
+      "  func() {}\n"
+      "}\n"
+      "class Uncommon {\n"
+      "  func() {}\n"
+      "}\n"
+      "helper(arg) {\n"
+      "  arg.func();\n"
+      "}\n"
+      "main() {\n"
+      "  Common common = new Common();\n"
+      "  Uncommon uncommon = new Uncommon();\n"
+      "  helper(common);\n"
+      "  helper(common);\n"
+      "  helper(uncommon);\n"
+      "}";
+
+  Library& lib = Library::Handle();
+  lib ^= ExecuteScript(kScript);
+  ASSERT(!lib.IsNull());
+  const Script& script = Script::Handle(lib.LookupScript(
+      String::Handle(String::New("test-lib"))));
+  const Function& helper = Function::Handle(
+      lib.LookupLocalFunction(String::Handle(String::New("helper"))));
+
+  SourceReport report(SourceReport::kCallSites);
+  JSONStream js;
+  report.PrintJSON(&js, script, helper.token_pos(), helper.end_token_pos());
+  ElideJSONSubstring("classes", js.ToCString(), buffer);
+  ElideJSONSubstring("libraries", buffer, buffer);
+  EXPECT_STREQ(
+      "{\"type\":\"SourceReport\",\"ranges\":["
+
+      // One range...
+      "{\"scriptIndex\":0,\"startPos\":24,\"endPos\":37,\"compiled\":true,"
+
+      // With one call site...
+      "\"callSites\":[{\"name\":\"func\",\"tokenPos\":32,\"cacheEntries\":["
+
+      // First receiver: "Common", called twice.
+      "{\"receiver\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
+      "\"name\":\"Common\"},"
+
+      "\"target\":{\"type\":\"@Function\",\"fixedId\":true,\"id\":\"\","
+      "\"name\":\"func\","
+      "\"owner\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
+      "\"name\":\"Common\"},\"_kind\":\"RegularFunction\","
+      "\"static\":false,\"const\":false,\"_intrinsic\":false,"
+      "\"_native\":false},"
+
+      "\"count\":2},"
+
+      // Second receiver: "Uncommon", called once.
+      "{\"receiver\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
+      "\"name\":\"Uncommon\"},"
+
+      "\"target\":{\"type\":\"@Function\",\"fixedId\":true,\"id\":\"\","
+      "\"name\":\"func\","
+      "\"owner\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
+      "\"name\":\"Uncommon\"},\"_kind\":\"RegularFunction\","
+      "\"static\":false,\"const\":false,\"_intrinsic\":false,"
+      "\"_native\":false},"
+
+      "\"count\":1}]}]}],"
+
+      // One script in the script table.
+      "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+      "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
+      buffer);
+}
+
+}  // namespace dart
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index d59ea20a..310660d 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -305,7 +305,6 @@
   V(OutOfMemoryError, "OutOfMemoryError")                                      \
   V(NullThrownError, "NullThrownError")                                        \
   V(IsolateSpawnException, "IsolateSpawnException")                            \
-  V(IsolateUnhandledException, "_IsolateUnhandledException")                   \
   V(JavascriptIntegerOverflowError, "_JavascriptIntegerOverflowError")         \
   V(JavascriptCompatibilityError, "_JavascriptCompatibilityError")             \
   V(BooleanExpression, "boolean expression")                                   \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 134b759..2357ce6 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -172,16 +172,20 @@
 }
 
 
-void Thread::EnterIsolate(Isolate* isolate) {
+bool Thread::EnterIsolate(Isolate* isolate) {
   const bool kIsMutatorThread = true;
   const bool kDontBypassSafepoints = false;
   ThreadRegistry* tr = isolate->thread_registry();
   Thread* thread = tr->Schedule(
       isolate, kIsMutatorThread, kDontBypassSafepoints);
-  isolate->MakeCurrentThreadMutator(thread);
-  thread->set_vm_tag(VMTag::kVMTagId);
-  ASSERT(thread->store_buffer_block_ == NULL);
-  thread->StoreBufferAcquire();
+  if (thread != NULL) {
+    isolate->MakeCurrentThreadMutator(thread);
+    thread->set_vm_tag(VMTag::kVMTagId);
+    ASSERT(thread->store_buffer_block_ == NULL);
+    thread->StoreBufferAcquire();
+    return true;
+  }
+  return false;
 }
 
 
@@ -210,16 +214,21 @@
 }
 
 
-void Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) {
+bool Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) {
   const bool kIsNotMutatorThread = false;
   ThreadRegistry* tr = isolate->thread_registry();
   Thread* thread = tr->Schedule(isolate, kIsNotMutatorThread, bypass_safepoint);
-  ASSERT(thread->store_buffer_block_ == NULL);
-  // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge.
-  thread->store_buffer_block_ =
-      thread->isolate()->store_buffer()->PopEmptyBlock();
-  // This thread should not be the main mutator.
-  ASSERT(!thread->IsMutatorThread());
+  if (thread != NULL) {
+    ASSERT(thread->store_buffer_block_ == NULL);
+    // TODO(koda): Use StoreBufferAcquire once we properly flush
+    // before Scavenge.
+    thread->store_buffer_block_ =
+        thread->isolate()->store_buffer()->PopEmptyBlock();
+    // This thread should not be the main mutator.
+    ASSERT(!thread->IsMutatorThread());
+    return true;
+  }
+  return false;
 }
 
 
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 281ac84..f85be7b 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -122,7 +122,7 @@
   }
 
   // Makes the current thread enter 'isolate'.
-  static void EnterIsolate(Isolate* isolate);
+  static bool EnterIsolate(Isolate* isolate);
   // Makes the current thread exit its isolate.
   static void ExitIsolate();
 
@@ -130,7 +130,7 @@
   // "helper" to gain limited concurrent access to the isolate. One example is
   // SweeperTask (which uses the class table, which is copy-on-write).
   // TODO(koda): Properly synchronize heap access to expand allowed operations.
-  static void EnterIsolateAsHelper(Isolate* isolate,
+  static bool EnterIsolateAsHelper(Isolate* isolate,
                                    bool bypass_safepoint = false);
   static void ExitIsolateAsHelper(bool bypass_safepoint = false);
 
diff --git a/runtime/vm/thread_pool.cc b/runtime/vm/thread_pool.cc
index 86d2f60..19c0a4d 100644
--- a/runtime/vm/thread_pool.cc
+++ b/runtime/vm/thread_pool.cc
@@ -258,6 +258,7 @@
 
 // Only call while holding the exit_monitor_
 void ThreadPool::AddWorkerToShutdownList(Worker* worker) {
+  ASSERT(exit_monitor_.IsOwnedByCurrentThread());
   worker->shutdown_next_ = shutting_down_workers_;
   shutting_down_workers_ = worker;
 }
@@ -267,6 +268,7 @@
 bool ThreadPool::RemoveWorkerFromShutdownList(Worker* worker) {
   ASSERT(worker != NULL);
   ASSERT(shutting_down_workers_ != NULL);
+  ASSERT(exit_monitor_.IsOwnedByCurrentThread());
 
   // Special case head of list.
   if (shutting_down_workers_ == worker) {
diff --git a/runtime/vm/thread_registry.cc b/runtime/vm/thread_registry.cc
index 5148808..2d2dee3 100644
--- a/runtime/vm/thread_registry.cc
+++ b/runtime/vm/thread_registry.cc
@@ -75,28 +75,29 @@
   }
   Thread* thread = NULL;
   OSThread* os_thread = OSThread::Current();
-  ASSERT(os_thread != NULL);
-  ASSERT(isolate->heap() != NULL);
-  // First get a Thread structure. (we special case the mutator thread
-  // by reusing the cached structure, see comment in 'thread_registry.h').
-  if (is_mutator) {
-    if (mutator_thread_ == NULL) {
-      mutator_thread_ = GetThreadFromFreelist(isolate);
+  if (os_thread != NULL) {
+    ASSERT(isolate->heap() != NULL);
+    // First get a Thread structure. (we special case the mutator thread
+    // by reusing the cached structure, see comment in 'thread_registry.h').
+    if (is_mutator) {
+      if (mutator_thread_ == NULL) {
+        mutator_thread_ = GetThreadFromFreelist(isolate);
+      }
+      thread = mutator_thread_;
+    } else {
+      thread = GetThreadFromFreelist(isolate);
+      ASSERT(thread->api_top_scope() == NULL);
     }
-    thread = mutator_thread_;
-  } else {
-    thread = GetThreadFromFreelist(isolate);
-    ASSERT(thread->api_top_scope() == NULL);
+    // Now add this Thread to the active list for the isolate.
+    AddThreadToActiveList(thread);
+    // Set up other values and set the TLS value.
+    thread->isolate_ = isolate;
+    thread->heap_ = isolate->heap();
+    thread->set_os_thread(os_thread);
+    os_thread->set_thread(thread);
+    Thread::SetCurrent(thread);
+    os_thread->EnableThreadInterrupts();
   }
-  // Now add this Thread to the active list for the isolate.
-  AddThreadToActiveList(thread);
-  // Set up other values and set the TLS value.
-  thread->isolate_ = isolate;
-  thread->heap_ = isolate->heap();
-  thread->set_os_thread(os_thread);
-  os_thread->set_thread(thread);
-  Thread::SetCurrent(thread);
-  os_thread->EnableThreadInterrupts();
   return thread;
 }
 
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index ab28bee..64c7127 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -200,47 +200,53 @@
 }
 
 
-void TimelineEvent::AsyncBegin(const char* label, int64_t async_id) {
+void TimelineEvent::AsyncBegin(const char* label,
+                               int64_t async_id,
+                               int64_t micros) {
   Init(kAsyncBegin, label);
-  set_timestamp0(OS::GetCurrentMonotonicMicros());
+  set_timestamp0(micros);
   // Overload timestamp1_ with the async_id.
   set_timestamp1(async_id);
 }
 
 
 void TimelineEvent::AsyncInstant(const char* label,
-                                 int64_t async_id) {
+                                 int64_t async_id,
+                                 int64_t micros) {
   Init(kAsyncInstant, label);
-  set_timestamp0(OS::GetCurrentMonotonicMicros());
+  set_timestamp0(micros);
   // Overload timestamp1_ with the async_id.
   set_timestamp1(async_id);
 }
 
 
 void TimelineEvent::AsyncEnd(const char* label,
-                             int64_t async_id) {
+                             int64_t async_id,
+                             int64_t micros) {
   Init(kAsyncEnd, label);
-  set_timestamp0(OS::GetCurrentMonotonicMicros());
+  set_timestamp0(micros);
   // Overload timestamp1_ with the async_id.
   set_timestamp1(async_id);
 }
 
 
-void TimelineEvent::DurationBegin(const char* label) {
+void TimelineEvent::DurationBegin(const char* label,
+                                  int64_t micros) {
   Init(kDuration, label);
-  set_timestamp0(OS::GetCurrentMonotonicMicros());
+  set_timestamp0(micros);
 }
 
 
-void TimelineEvent::DurationEnd() {
+void TimelineEvent::DurationEnd(int64_t micros) {
   ASSERT(timestamp1_ == 0);
-  set_timestamp1(OS::GetCurrentMonotonicMicros());
+  set_timestamp1(micros);
 }
 
 
-void TimelineEvent::Instant(const char* label) {
+void TimelineEvent::Instant(const char* label,
+                            int64_t micros) {
   Init(kInstant, label);
-  set_timestamp0(OS::GetCurrentMonotonicMicros());
+  set_timestamp0(micros);
 }
 
 
@@ -267,10 +273,11 @@
 }
 
 
-void TimelineEvent::SerializedJSON(const char* json) {
-  Init(kSerializedJSON, "Dart");
+void TimelineEvent::CompleteWithPreSerializedJSON(const char* json) {
+  set_pre_serialized_json(true);
   SetNumArguments(1);
   CopyArgument(0, "Dart", json);
+  Complete();
 }
 
 
@@ -378,8 +385,31 @@
 }
 
 
+bool TimelineEvent::Within(int64_t time_origin_micros,
+                           int64_t time_extent_micros) {
+  if ((time_origin_micros == -1) ||
+      (time_extent_micros == -1)) {
+    // No time range specified.
+    return true;
+  }
+  if (IsFinishedDuration()) {
+    // Event is from e_t0 to e_t1.
+    int64_t e_t0 = TimeOrigin();
+    int64_t e_t1 = TimeEnd();
+    ASSERT(e_t0 <= e_t1);
+    // Range is from r_t0 to r_t1.
+    int64_t r_t0 = time_origin_micros;
+    int64_t r_t1 = time_origin_micros + time_extent_micros;
+    ASSERT(r_t0 <= r_t1);
+    return !((r_t1 < e_t0) || (e_t1 < r_t0));
+  }
+  int64_t delta = TimeOrigin() - time_origin_micros;
+  return (delta >= 0) && (delta <= time_extent_micros);
+}
+
+
 const char* TimelineEvent::GetSerializedJSON() const {
-  ASSERT(event_type() == kSerializedJSON);
+  ASSERT(pre_serialized_json());
   ASSERT(arguments_length_ == 1);
   ASSERT(arguments_ != NULL);
   return arguments_[0].value;
@@ -387,7 +417,7 @@
 
 
 void TimelineEvent::PrintJSON(JSONStream* stream) const {
-  if (event_type() == kSerializedJSON) {
+  if (pre_serialized_json()) {
     // Event has already been serialized into JSON- just append the
     // raw data.
     stream->AppendSerializedObject(GetSerializedJSON());
@@ -714,7 +744,12 @@
 }
 
 
-TimelineEventFilter::TimelineEventFilter() {
+TimelineEventFilter::TimelineEventFilter(int64_t time_origin_micros,
+                                         int64_t time_extent_micros)
+    : time_origin_micros_(time_origin_micros),
+      time_extent_micros_(time_extent_micros) {
+  ASSERT(time_origin_micros_ >= -1);
+  ASSERT(time_extent_micros_ >= -1);
 }
 
 
@@ -722,8 +757,13 @@
 }
 
 
-IsolateTimelineEventFilter::IsolateTimelineEventFilter(Dart_Port isolate_id)
-    : isolate_id_(isolate_id) {
+IsolateTimelineEventFilter::IsolateTimelineEventFilter(
+    Dart_Port isolate_id,
+    int64_t time_origin_micros,
+    int64_t time_extent_micros)
+    : TimelineEventFilter(time_origin_micros,
+                          time_extent_micros),
+      isolate_id_(isolate_id) {
 }
 
 
@@ -937,7 +977,9 @@
     }
     for (intptr_t event_idx = 0; event_idx < block->length(); event_idx++) {
       TimelineEvent* event = block->At(event_idx);
-      if (filter->IncludeEvent(event)) {
+      if (filter->IncludeEvent(event) &&
+          event->Within(filter->time_origin_micros(),
+                        filter->time_extent_micros())) {
         events->AddValue(event);
       }
     }
@@ -1129,10 +1171,11 @@
     intptr_t length = current->length();
     for (intptr_t i = 0; i < length; i++) {
       TimelineEvent* event = current->At(i);
-      if (!filter->IncludeEvent(event)) {
-        continue;
+      if (filter->IncludeEvent(event) &&
+          event->Within(filter->time_origin_micros(),
+                        filter->time_extent_micros())) {
+        events->AddValue(event);
       }
-      events->AddValue(event);
     }
     current = current->next();
   }
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
index 40040a4..d0c43e0 100644
--- a/runtime/vm/timeline.h
+++ b/runtime/vm/timeline.h
@@ -115,17 +115,23 @@
   }
 
   // Marks the beginning of an asynchronous operation with |async_id|.
-  void AsyncBegin(const char* label, int64_t async_id);
+  void AsyncBegin(const char* label,
+                  int64_t async_id,
+                  int64_t micros = OS::GetCurrentMonotonicMicros());
   // Marks an instantaneous event associated with |async_id|.
   void AsyncInstant(const char* label,
-                    int64_t async_id);
+                    int64_t async_id,
+                    int64_t micros = OS::GetCurrentMonotonicMicros());
   // Marks the end of an asynchronous operation associated with |async_id|.
   void AsyncEnd(const char* label,
-                int64_t async_id);
+                int64_t async_id,
+                int64_t micros = OS::GetCurrentMonotonicMicros());
 
-  void DurationBegin(const char* label);
-  void DurationEnd();
-  void Instant(const char* label);
+  void DurationBegin(const char* label,
+                     int64_t micros = OS::GetCurrentMonotonicMicros());
+  void DurationEnd(int64_t micros = OS::GetCurrentMonotonicMicros());
+  void Instant(const char* label,
+               int64_t micros = OS::GetCurrentMonotonicMicros());
 
   void Duration(const char* label,
                 int64_t start_micros,
@@ -137,7 +143,8 @@
   void End(const char* label,
            int64_t micros = OS::GetCurrentMonotonicMicros());
 
-  void SerializedJSON(const char* json);
+  // Completes this event with pre-serialized JSON. Copies |json|.
+  void CompleteWithPreSerializedJSON(const char* json);
 
   // Set the number of arguments in the event.
   void SetNumArguments(intptr_t length);
@@ -236,6 +243,9 @@
     }
   }
 
+  bool Within(int64_t time_origin_micros,
+              int64_t time_extent_micros);
+
   const char* GetSerializedJSON() const;
 
  private:
@@ -259,12 +269,23 @@
     timestamp1_ = value;
   }
 
+  bool pre_serialized_json() const {
+    return PreSerializedJSON::decode(state_);
+  }
+
+  void set_pre_serialized_json(bool pre_serialized_json) {
+    state_ = PreSerializedJSON::update(pre_serialized_json, state_);
+  }
+
   enum StateBits {
     kEventTypeBit = 0,  // reserve 4 bits for type.
-    kNextBit = 4,
+    kPreSerializedJSON = 4,
+    kNextBit = 5,
   };
 
   class EventTypeField : public BitField<EventType, kEventTypeBit, 4> {};
+  class PreSerializedJSON :
+      public BitField<bool, kPreSerializedJSON, 1> {};
 
   int64_t timestamp0_;
   int64_t timestamp1_;
@@ -522,7 +543,9 @@
 
 class TimelineEventFilter : public ValueObject {
  public:
-  TimelineEventFilter();
+  TimelineEventFilter(int64_t time_origin_micros = -1,
+                      int64_t time_extent_micros = -1);
+
   virtual ~TimelineEventFilter();
 
   virtual bool IncludeBlock(TimelineEventBlock* block) {
@@ -540,13 +563,25 @@
     return event->IsValid();
   }
 
+  int64_t time_origin_micros() const {
+    return time_origin_micros_;
+  }
+
+  int64_t time_extent_micros() const {
+    return time_extent_micros_;
+  }
+
  private:
+  int64_t time_origin_micros_;
+  int64_t time_extent_micros_;
 };
 
 
 class IsolateTimelineEventFilter : public TimelineEventFilter {
  public:
-  explicit IsolateTimelineEventFilter(Dart_Port isolate_id);
+  explicit IsolateTimelineEventFilter(Dart_Port isolate_id,
+                                      int64_t time_origin_micros = -1,
+                                      int64_t time_extent_micros = -1);
 
   bool IncludeBlock(TimelineEventBlock* block) {
     if (block == NULL) {
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index f2cf962..67b23f1 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -416,6 +416,9 @@
     'snapshot.h',
     'snapshot_ids.h',
     'snapshot_test.cc',
+    'source_report.cc',
+    'source_report.h',
+    'source_report_test.cc',
     'spaces.h',
     'stack_frame.cc',
     'stack_frame.h',
diff --git a/runtime/vm/weak_code.cc b/runtime/vm/weak_code.cc
index e642204..7c817d0 100644
--- a/runtime/vm/weak_code.cc
+++ b/runtime/vm/weak_code.cc
@@ -14,6 +14,11 @@
 
 namespace dart {
 
+bool WeakCodeReferences::HasCodes() const {
+  return !array_.IsNull() && (array_.Length() > 0);
+}
+
+
 void WeakCodeReferences::Register(const Code& value) {
   if (!array_.IsNull()) {
     // Try to find and reuse cleared WeakProperty to avoid allocating new one.
diff --git a/runtime/vm/weak_code.h b/runtime/vm/weak_code.h
index 4529806..ea2d9c1 100644
--- a/runtime/vm/weak_code.h
+++ b/runtime/vm/weak_code.h
@@ -31,8 +31,10 @@
 
   void DisableCode();
 
+  bool HasCodes() const;
+
  private:
-  const Array& array_;
+  const Array& array_;  // Array of Code objects.
   DISALLOW_COPY_AND_ASSIGN(WeakCodeReferences);
 };
 
diff --git a/samples/samples.status b/samples/samples.status
index 81d9654..480d3f3 100644
--- a/samples/samples.status
+++ b/samples/samples.status
@@ -24,3 +24,5 @@
 [ $arch == simarm64 ]
 *: Skip
 
+[ $runtime == dart_precompiled ]
+sample_extension: RuntimeError # Platform.executable
diff --git a/sdk/bin/dart b/sdk/bin/dart
index 999034c..7dd1e92 100755
--- a/sdk/bin/dart
+++ b/sdk/bin/dart
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
diff --git a/sdk/bin/dart2js b/sdk/bin/dart2js
index 485d619..988a6fe 100755
--- a/sdk/bin/dart2js
+++ b/sdk/bin/dart2js
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
diff --git a/sdk/bin/dart2js_developer b/sdk/bin/dart2js_developer
index 948cb4a..226d1a9 100755
--- a/sdk/bin/dart2js_developer
+++ b/sdk/bin/dart2js_developer
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
diff --git a/sdk/bin/dart2js_sdk b/sdk/bin/dart2js_sdk
index 36b42a4..286859a 100755
--- a/sdk/bin/dart2js_sdk
+++ b/sdk/bin/dart2js_sdk
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
diff --git a/sdk/bin/dartanalyzer b/sdk/bin/dartanalyzer
index 0c23848..8f2274c 100755
--- a/sdk/bin/dartanalyzer
+++ b/sdk/bin/dartanalyzer
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # 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.
diff --git a/sdk/bin/dartanalyzer_developer b/sdk/bin/dartanalyzer_developer
index 0eeaf73..373dc67 100755
--- a/sdk/bin/dartanalyzer_developer
+++ b/sdk/bin/dartanalyzer_developer
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # 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.
diff --git a/sdk/bin/dartanalyzer_sdk b/sdk/bin/dartanalyzer_sdk
index cc49a5c..28f37ab 100755
--- a/sdk/bin/dartanalyzer_sdk
+++ b/sdk/bin/dartanalyzer_sdk
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # 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.
diff --git a/sdk/bin/dartdoc b/sdk/bin/dartdoc
index 319df02..caff494 100755
--- a/sdk/bin/dartdoc
+++ b/sdk/bin/dartdoc
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # 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.
diff --git a/sdk/bin/dartfmt b/sdk/bin/dartfmt
index bc53f36..ded1eac 100755
--- a/sdk/bin/dartfmt
+++ b/sdk/bin/dartfmt
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # 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.
diff --git a/sdk/bin/dartfmt_sdk b/sdk/bin/dartfmt_sdk
index 0a9cbef..273733c 100755
--- a/sdk/bin/dartfmt_sdk
+++ b/sdk/bin/dartfmt_sdk
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # 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.
diff --git a/sdk/bin/pub b/sdk/bin/pub
index a03070e..50f0d1d 100755
--- a/sdk/bin/pub
+++ b/sdk/bin/pub
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
diff --git a/sdk/bin/pub_sdk b/sdk/bin/pub_sdk
index bf48a16..f42f609 100755
--- a/sdk/bin/pub_sdk
+++ b/sdk/bin/pub_sdk
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # 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.
diff --git a/sdk/lib/_internal/js_runtime/lib/constant_map.dart b/sdk/lib/_internal/js_runtime/lib/constant_map.dart
index 8a6a5c9..9e98b13 100644
--- a/sdk/lib/_internal/js_runtime/lib/constant_map.dart
+++ b/sdk/lib/_internal/js_runtime/lib/constant_map.dart
@@ -67,14 +67,18 @@
 
   // This constructor is not used for actual compile-time constants.
   // The instantiation of constant maps is shortcut by the compiler.
-  const ConstantStringMap._(this.length, this._jsObject, this._keys)
+  const ConstantStringMap._(this._length, this._jsObject, this._keys)
       : super._();
 
-  final int length;
+  // TODO(18131): Ensure type inference knows the precise types of the fields.
+  final int _length;
   // A constant map is backed by a JavaScript object.
   final _jsObject;
   final List<K> _keys;
 
+  int get length => JS('JSUInt31', '#', _length);
+  List get _keysArray => JS('JSUnmodifiableArray', '#', _keys);
+
   bool containsValue(Object needle) {
     return values.any((V value) => value == needle);
   }
@@ -97,7 +101,7 @@
     // Use a JS 'cast' to get efficient loop.  Type inferrence doesn't get this
     // since constant map representation is chosen after type inferrence and the
     // instantiation is shortcut by the compiler.
-    var keys = JS('JSArray', '#', _keys);
+    var keys = _keysArray;
     for (int i = 0; i < keys.length; i++) {
       var key = keys[i];
       f(key, _fetch(key));
@@ -109,7 +113,7 @@
   }
 
   Iterable<V> get values {
-    return new MappedIterable<K, V>(_keys, (key) => _fetch(key));
+    return new MappedIterable<K, V>(_keysArray, (key) => _fetch(key));
   }
 }
 
@@ -135,9 +139,9 @@
   ConstantStringMap<K, dynamic> _map;
   _ConstantMapKeyIterable(this._map);
 
-  Iterator<K> get iterator => _map._keys.iterator;
+  Iterator<K> get iterator => _map._keysArray.iterator;
 
-  int get length => _map._keys.length;
+  int get length => _map._keysArray.length;
 }
 
 class GeneralConstantMap<K, V> extends ConstantMap<K, V> {
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index d6dd538..4976562 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -1932,8 +1932,7 @@
 
     // Since we want to create a new regular expression from an unknown string,
     // we must escape all regular expression syntax.
-    message = JS('String', r"#.replace(new RegExp(#, 'g'), '\\$&')",
-                 message, ESCAPE_REGEXP);
+    message = quoteStringForRegExp(message);
 
     // Look for the special pattern \$camelCase\$ (all the $ symbols
     // have been escaped already), as we will soon be inserting
@@ -2369,20 +2368,19 @@
               var arg2,
               var arg3,
               var arg4) {
-  if (numberOfArguments == 0) {
-    return JS_CALL_IN_ISOLATE(isolate, () => closure());
-  } else if (numberOfArguments == 1) {
-    return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1));
-  } else if (numberOfArguments == 2) {
-    return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2));
-  } else if (numberOfArguments == 3) {
-    return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2, arg3));
-  } else if (numberOfArguments == 4) {
-    return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2, arg3, arg4));
-  } else {
-    throw new Exception(
-        'Unsupported number of arguments for wrapped closure');
+  switch (numberOfArguments) {
+    case 0:
+      return JS_CALL_IN_ISOLATE(isolate, () => closure());
+    case 1:
+      return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1));
+    case 2:
+      return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2));
+    case 3:
+      return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2, arg3));
+    case 4:
+      return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2, arg3, arg4));
   }
+  throw new Exception('Unsupported number of arguments for wrapped closure');
 }
 
 /**
@@ -2394,21 +2392,18 @@
   var function = JS('var', r'#.$identity', closure);
   if (JS('bool', r'!!#', function)) return function;
 
-  // We use $0 and $1 to not clash with variable names used by the
-  // compiler and/or minifier.
-  function = JS('var',
-                '(function(closure, arity, context, invoke) {'
-                '  return function(a1, a2, a3, a4) {'
-                '     return invoke(closure, context, arity, a1, a2, a3, a4);'
-                '  };'
-                '})(#,#,#,#)',
-                closure,
-                arity,
-                // Capture the current isolate now.  Remember that "#"
-                // in JS is simply textual substitution of compiled
-                // expressions.
-                JS_CURRENT_ISOLATE_CONTEXT(),
-                DART_CLOSURE_TO_JS(invokeClosure));
+  function = JS(
+      'var',
+      r'''
+        (function(closure, arity, context, invoke) {
+          return function(a1, a2, a3, a4) {
+            return invoke(closure, context, arity, a1, a2, a3, a4);
+          };
+        })(#,#,#,#)''',
+      closure,
+      arity,
+      JS_CURRENT_ISOLATE_CONTEXT(),
+      DART_CLOSURE_TO_JS(invokeClosure));
 
   JS('void', r'#.$identity = #', closure, function);
   return function;
diff --git a/sdk/lib/_internal/js_runtime/lib/string_helper.dart b/sdk/lib/_internal/js_runtime/lib/string_helper.dart
index 9ce91f8..24e21f7 100644
--- a/sdk/lib/_internal/js_runtime/lib/string_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/string_helper.dart
@@ -130,7 +130,12 @@
   return stringReplaceRangeUnchecked(receiver, start, end, replacement);
 }
 
-const String ESCAPE_REGEXP = r'[[\]{}()*+?.\\^$|]';
+
+/// Returns a string for a RegExp pattern that matches [string]. This is done by
+/// escaping all RegExp metacharacters.
+quoteStringForRegExp(string) {
+  return JS('String', r'#.replace(/[[\]{}()*+?.\\^$|]/g, "\\$&")', string);
+}
 
 stringReplaceAllUnchecked(receiver, pattern, replacement) {
   checkString(replacement);
@@ -149,8 +154,7 @@
         return result.toString();
       }
     } else {
-      var quoter = JS('', "new RegExp(#, 'g')", ESCAPE_REGEXP);
-      var quoted = JS('String', r'#.replace(#, "\\$&")', pattern, quoter);
+      var quoted = quoteStringForRegExp(pattern);
       var replacer = JS('', "new RegExp(#, 'g')", quoted);
       return stringReplaceJS(receiver, replacer, replacement);
     }
diff --git a/sdk/lib/developer/timeline.dart b/sdk/lib/developer/timeline.dart
index 15ed062..c463d8b 100644
--- a/sdk/lib/developer/timeline.dart
+++ b/sdk/lib/developer/timeline.dart
@@ -68,6 +68,9 @@
     }
   }
 
+  /// The current time stamp from the clock used by the timeline. Units are
+  /// microseconds.
+  static int get now => _getTraceClock();
   static final List<_SyncBlock> _stack = new List<_SyncBlock>();
   static final int _isolateId = _getIsolateNum();
   static final String _isolateIdString = _isolateId.toString();
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 8acae64..883ae88 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -31962,10 +31962,11 @@
    */
   Document get document => JS('Document', '#.document', this);
 
-  WindowBase _open2(url, name) => JS('Window', '#.open(#,#)', this, url, name);
+  WindowBase _open2(url, name) =>
+      JS('Window|Null', '#.open(#,#)', this, url, name);
 
   WindowBase _open3(url, name, options) =>
-      JS('Window', '#.open(#,#,#)', this, url, name, options);
+      JS('Window|Null', '#.open(#,#,#)', this, url, name, options);
 
   /**
    * Opens a new window.
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 6b1a7f7..0d1edad 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -20360,16 +20360,9 @@
             createdParametersValid = createdParametersValid && parameter.isOptional;
           });
         }
-
-        // Get the created constructor source and look at the initializer;
-        // Must call super.created() if not its as an error.
-        var createdSource = methodMirror.source;
-        superCreatedCalled = createdSource.contains("super.created(");
       }
 
-      if (!superCreatedCalled) {
-        throw new DomException.jsInterop('created constructor initializer must call super.created()');
-      } else if (!createdParametersValid) {
+      if (!createdParametersValid) {
         throw new DomException.jsInterop('created constructor must have no parameters');
       }
 
diff --git a/site/try/create_manifest.sh b/site/try/create_manifest.sh
index c445833..0f145ac 100644
--- a/site/try/create_manifest.sh
+++ b/site/try/create_manifest.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # 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.
diff --git a/tests/benchmark_smoke/benchmark_smoke.status b/tests/benchmark_smoke/benchmark_smoke.status
index d3fe9a3..a83fd89 100644
--- a/tests/benchmark_smoke/benchmark_smoke.status
+++ b/tests/benchmark_smoke/benchmark_smoke.status
@@ -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.
 
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
 *: Skip
 
 [ $compiler == dart2js && $runtime == none ]
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 64cea7e..19f53a4 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -135,7 +135,7 @@
 Language/Statements/Local_Function_Declaration/reference_before_declaration_t03: MissingCompileTimeError # Issue 21050
 Language/Types/Interface_Types/subtype_t27: Skip # Times out or crashes. Issue 21174
 Language/Types/Interface_Types/subtype_t30: fail # Issue 14654
-Language/Types/Interface_Types/subtype_t28: Pass, Fail # Stack overflow. Issue 25282
+Language/Types/Interface_Types/subtype_t28: Pass, Fail, Crash # Stack overflow. Issue 25282
 Language/Variables/final_t01: fail # Issue 21093
 Language/Variables/final_t02: fail # Issue 21093
 Language/Variables/local_variable_t01: MissingCompileTimeError # Issue 21050
@@ -1727,7 +1727,6 @@
 LayoutTests/fast/canvas/canvas-toDataURL-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/crash-set-font_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/draw-custom-focus-ring_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/drawImage-with-negative-source-destination_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/drawImage-with-valid-image_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/getPutImageDataPairTest_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/rgba-parsing_t01: RuntimeError # Please triage this failure
@@ -3167,6 +3166,7 @@
 [ $compiler == dart2js && $runtime == ff && $system != windows ]
 LayoutTests/fast/canvas/canvas-resetTransform_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-setTransform_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/drawImage-with-negative-source-destination_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLAnchorElement/set-href-attribute-pathname_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/xpath/4XPath/Core/test_parser_t01: RuntimeError # Dartium JSInterop failure
 LayoutTests/fast/xpath/py-dom-xpath/abbreviations_t01: RuntimeError # Dartium JSInterop failure
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index c5bfba7..0b6ea52 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -3,7 +3,12 @@
 # BSD-style license that can be found in the LICENSE file.
 
 
-[ $compiler == none && ($runtime == vm || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && (($runtime == vm || $runtime == dart_precompiled) || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+
+# Failures ok in tests below. VM moves super initializer to end of list.
+Language/Classes/Constructors/Generative_Constructors/execution_t03: Fail, OK
+Language/Expressions/Instance_Creation/New/execution_t04: Fail, OK
+Language/Expressions/Instance_Creation/New/execution_t06: Fail, OK
 
 LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail # Issue 22200
 LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: Fail # Issue 22200
@@ -38,7 +43,7 @@
 LibTest/core/Symbol/Symbol_A01_t03: RuntimeError # Issue 13596
 LibTest/core/Symbol/Symbol_A01_t05: RuntimeError # Issue 13596
 
-[ $compiler == none && $runtime == vm ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) ]
 LibTest/typed_data/Float32x4/reciprocalSqrt_A01_t01: Pass, Fail # co19 issue 599
 LibTest/typed_data/Float32x4/reciprocal_A01_t01: Pass, Fail # co19 issue 599
 Language/Expressions/Instance_Creation/Const/abstract_class_t01: MissingCompileTimeError # Issue 22007
@@ -48,16 +53,16 @@
 Language/Libraries_and_Scripts/Exports/invalid_uri_t02: Fail
 Language/Libraries_and_Scripts/Parts/syntax_t06: Fail
 
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
 LibTest/math/MutableRectangle/MutableRectangle.fromPoints_A01_t01: Pass, RuntimeError # co19-roll r607: Please triage this failure
 
-[ $compiler == none && $runtime == vm && $mode == debug ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && $mode == debug ]
 LibTest/core/List/List_class_A01_t02: Pass, Slow
 
-[ $compiler == none && $runtime == vm && ($arch != x64 && $arch != simarm64) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ($arch != x64 && $arch != simarm64) ]
 LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
 
-[ $compiler == none && $runtime == vm && $arch == mips ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && $arch == mips ]
 LibTest/core/double/toInt_A01_t01: Fail
 # These tests take too much memory (300 MB) for our 1 GB test machine.
 # co19 issue 673. http://code.google.com/p/co19/issues/detail?id=673
@@ -65,30 +70,30 @@
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Skip # co19 issue 673
 LibTest/collection/ListBase/ListBase_class_A01_t02: Skip # co19 issue 673
 
-[ $compiler == none && $runtime == vm && $arch == mips && $mode == debug ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && $arch == mips && $mode == debug ]
 LibTest/isolate/Isolate/spawnUri_A01_t04: Crash, Pass # Issue 17440
 LibTest/isolate/Isolate/spawn_A01_t04: Crash, Pass # Issue 17440
 
-[ $compiler == none && $runtime == vm && ($arch == simarm || $arch == simarmv5te || $arch == simmips || $arch == simarm64) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ($arch == simarm || $arch == simarmv5te || $arch == simmips || $arch == simarm64) ]
 LibTest/core/Uri/Uri_A06_t03: Skip  # Timeout
 LibTest/collection/ListMixin/ListMixin_class_A01_t01: Skip  # Timeout
 LibTest/collection/ListBase/ListBase_class_A01_t01: Skip  # Timeout
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Skip  # Timeout
 LibTest/collection/ListBase/ListBase_class_A01_t02: Skip  # Timeout
 
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
 LibTest/isolate/Isolate/spawn_A02_t01: Skip # co19 issue 667
 LibTest/html/*: SkipByDesign # dart:html not supported on VM.
 LayoutTests/fast/*: SkipByDesign # DOM not supported on VM.
 WebPlatformTest/*: SkipByDesign # dart:html not supported on VM.
 
-[ $runtime == vm && $mode == debug && $builder_tag == asan ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $mode == debug && $builder_tag == asan ]
 Language/Types/Interface_Types/subtype_t27: Skip  # Issue 21174.
 
-[ $runtime == vm && $arch == arm ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $arch == arm ]
 LibTest/typed_data/Float32x4/operator_multiplication_A01_t01: Fail # Dart issue 24416
 
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
 # co19 update Sep 29, 2015 (3ed795ea02e022ef19c77cf1b6095b7c8f5584d0)
 Language/Classes/Constructors/Constant_Constructors/initializer_not_a_constant_t01: MissingCompileTimeError # Please triage this failure
 Language/Classes/Constructors/Constant_Constructors/initializer_not_a_constant_t02: MissingCompileTimeError # Please triage this failure
@@ -131,10 +136,10 @@
 Language/Mixins/not_object_superclass_t01: MissingCompileTimeError # Please triage this failure
 Language/Mixins/reference_to_super_t01: MissingCompileTimeError # Please triage this failure
 
-[ $runtime == vm && $mode == debug ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $mode == debug ]
 Language/Mixins/Mixin_Application/wrong_type_t02: Crash # Please triage this failure
 
-[ $runtime == vm && $checked ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $checked ]
 Language/Errors_and_Warnings/static_warning_t01: RuntimeError # Please triage this failure
 Language/Errors_and_Warnings/static_warning_t02: RuntimeError # Please triage this failure
 Language/Errors_and_Warnings/static_warning_t03: RuntimeError # Please triage this failure
@@ -142,7 +147,7 @@
 Language/Errors_and_Warnings/static_warning_t05: RuntimeError # Please triage this failure
 Language/Errors_and_Warnings/static_warning_t06: RuntimeError # Please triage this failure
 
-[ $runtime == vm && $noopt ]
+[ ($noopt || $compiler == precompiler) ]
 LibTest/collection/ListBase/ListBase_class_A01_t02: Pass, Timeout
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Pass, Timeout
 LibTest/core/Map/Map_class_A01_t04: Pass, Timeout
@@ -152,3 +157,6 @@
 Language/Mixins/declaring_constructor_t01: Pass
 Language/Expressions/Property_Extraction/Named_Constructor_Extraction/deferred_type_t01: Pass
 Language/Metadata/*: Skip # Uses dart:mirrors
+
+[ $runtime == dart_precompiled ]
+LibTest/isolate/Isolate/spawnUri*: RuntimeError # Isolate.spawnUri
\ No newline at end of file
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index b7a65e8..70a2a3a 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -52,6 +52,12 @@
 js_backend_cps_ir_closures_test: Pass, Slow
 js_backend_cps_ir_constructor_test: Pass, Slow
 
+# Source information is not correct due to inlining.
+js_backend_cps_ir_source_information_test: Fail
+sourcemaps/source_mapping_operators_test: Fail # Issue 25304 for checked mode, was: Pass, Slow
+
+check_elements_invariants_test: Slow, Pass, Timeout # Slow due to inlining in the CPS backend
+
 [ $unchecked ]
 exit_code_test: Skip # This tests requires checked mode.
 
@@ -59,7 +65,6 @@
 analyze_dart2js_helpers_test: Pass, Slow
 analyze_dart2js_test: Pass, Slow
 analyze_unused_dart2js_test: Pass, Slow
-check_elements_invariants_test: Slow, Pass, Timeout
 deferred_mirrors_test: Pass, Slow
 duplicate_library_test: Pass, Slow
 exit_code_test: Pass, Slow
@@ -67,7 +72,6 @@
 interop_anonymous_unreachable_test: Pass, Slow
 mirror_final_field_inferrer2_test: Pass, Slow
 source_map_pub_build_validity_test: Pass, Slow
-sourcemaps/source_mapping_operators_test: Pass, Slow
 uri_retention_test: Pass, Slow
 value_range_test: Pass, Slow
 
diff --git a/tests/compiler/dart2js/incremental/hello_test.dart b/tests/compiler/dart2js/incremental/hello_test.dart
index 83215dc..e47ef9d 100644
--- a/tests/compiler/dart2js/incremental/hello_test.dart
+++ b/tests/compiler/dart2js/incremental/hello_test.dart
@@ -85,8 +85,7 @@
 
 main() {
   Uri libraryRoot = Uri.base.resolve('sdk/');
-  Uri packageRoot = Uri.base.resolveUri(
-      new Uri.file('${Platform.packageRoot}/'));
+  Uri packageRoot = Uri.base.resolve(Platform.packageRoot);
   MemorySourceFileProvider provider =
       new MemorySourceFileProvider(tests);
   asyncTest(() => runTests(libraryRoot, packageRoot, provider));
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_basic_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_basic_test.dart
index 51d2762..614a102 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_basic_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_basic_test.dart
@@ -25,15 +25,23 @@
   print('($m)');
 }""",r"""
 function() {
-  var l = [1, 2, 3], m = P.LinkedHashMap_LinkedHashMap$_literal(["s", 1]);
+  var l = [1, 2, 3], m = P.LinkedHashMap_LinkedHashMap$_literal(["s", 1]), value_ = C.JSArray_methods, res, v0, v1;
   P.print("()");
   P.print("(true)");
   P.print("(1)");
-  P.print("(" + H.S([1, 2, 3]) + ")");
-  P.print("(" + H.S(P.LinkedHashMap_LinkedHashMap$_literal(["s", 1])) + ")");
+  if (!(typeof (res = value_.toString$0(v0 = [1, 2, 3])) === "string"))
+    throw H.wrapException(H.argumentErrorValue(v0));
+  P.print("(" + res + ")");
+  if (!(typeof (v1 = P.Maps_mapToString(v0 = P.LinkedHashMap_LinkedHashMap$_literal(["s", 1]))) === "string"))
+    throw H.wrapException(H.argumentErrorValue(v0));
+  P.print("(" + v1 + ")");
   P.print("(1)");
-  P.print("(" + H.S(l) + ")");
-  P.print("(" + H.S(m) + ")");
+  if (!(typeof (res = value_.toString$0(l)) === "string"))
+    throw H.wrapException(H.argumentErrorValue(l));
+  P.print("(" + res + ")");
+  if (!(typeof (v0 = P.Maps_mapToString(m)) === "string"))
+    throw H.wrapException(H.argumentErrorValue(m));
+  P.print("(" + v0 + ")");
 }"""),
   const TestEntry("""
 foo(a, [b = "b"]) { print(b); return b; }
@@ -49,12 +57,12 @@
 """,
 """
 function() {
-  V.foo(0, "b");
-  V.foo(1, 2);
-  V.bar(3, "b", "c");
-  V.bar(4, 5, "c");
-  V.bar(6, "b", 7);
-  V.bar(8, 9, 10);
+  P.print("b");
+  P.print(2);
+  P.print("c");
+  P.print("c");
+  P.print(7);
+  P.print(10);
 }"""),
   const TestEntry(
   """
@@ -77,19 +85,30 @@
   """,
   """
 function() {
-  var a = 10, b = 1;
-  P.print(b);
-  P.print(a);
-  P.print(a);
-  P.print(V.foo(b));
+  P.print(1);
+  P.print(10);
+  P.print(10);
+  P.print(1);
+  P.print(1);
 }"""),
   const TestEntry(
   """
 foo() { print(42); return 42; }
 main() { return foo(); }
   """,
-  """function() {
-  return V.foo();
+  """
+function() {
+  var v0 = H.S(42);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
+  return 42;
 }"""),
   const TestEntry("main() {}"),
   const TestEntry("main() { return 42; }"),
@@ -103,7 +122,7 @@
   print(new Set.from([1, 2, 3]));
 }""", r"""
 function() {
-  P.print(P.LinkedHashSet_LinkedHashSet(null, null, null, null));
+  P.print(P._LinkedHashSet$(null));
   P.print(P.LinkedHashSet_LinkedHashSet$from([1, 2, 3], null));
 }"""),
   // Call synthetic constructor.
@@ -118,7 +137,16 @@
   print(new DateTime.now().isBefore(new DateTime.now()));
 }""", r"""
 function() {
-  P.print(P.DateTime$now().isBefore$1(P.DateTime$now()));
+  var v0 = H.S(Date.now() < Date.now());
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
   // Static calls
   const TestEntry("""
@@ -126,7 +154,16 @@
 main() { foo(); }
 """, r"""
 function() {
-  V.foo();
+  var v0 = H.S(42);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
   // Static getters
   const TestEntry("""
@@ -134,14 +171,32 @@
 main() { print(foo); }
 """, r"""
 function() {
-  P.print($.foo);
+  var v0 = H.S($.foo);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
   const TestEntry("""
 get foo { print(42); }
 main() { foo; }
 """, r"""
 function() {
-  V.foo();
+  var v0 = H.S(42);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
   // Static setters
   const TestEntry("""
@@ -149,16 +204,34 @@
 main() { print(foo = 42); }
 """, r"""
 function() {
-  var v0 = 42;
-  $.foo = v0;
-  P.print(v0);
+  var v0;
+  $.foo = 42;
+  v0 = H.S(42);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
   const TestEntry("""
 set foo(x) { print(x); }
 main() { foo = 42; }
 """, r"""
 function() {
-  V.foo(42);
+  var v0 = H.S(42);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
   // Assert
   const TestEntry("""
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart
index dc4552b..f3d55a0 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart
@@ -81,7 +81,16 @@
 """,
 r"""
 function() {
-  P.print(122 + 1);
+  var v0 = H.S(122 + 1);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
 
   const TestEntry("""
@@ -95,10 +104,19 @@
 """,
 r"""
 function() {
-  var _box_0 = {}, a = new V.main_closure(_box_0);
+  var _box_0 = {}, a = new V.main_closure(_box_0), v0;
   _box_0.x = 122;
   _box_0.x = _box_0.x + 1;
-  P.print(a.call$0());
+  v0 = H.S(a.call$0());
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
   return a;
 }"""),
 
@@ -115,7 +133,16 @@
 """,
 r"""
 function() {
-  P.print(122 + 1);
+  var v0 = H.S(122 + 1);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
 
   const TestEntry("""
@@ -132,10 +159,19 @@
 """,
 r"""
 function() {
-  var _box_0 = {}, a = new V.main_closure(_box_0);
+  var _box_0 = {}, a = new V.main_closure(_box_0), v0;
   _box_0.x = 122;
   _box_0.x = _box_0.x + 1;
-  P.print(a.call$0().call$0());
+  v0 = H.S(a.call$0().call$0());
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
   return a;
 }"""),
 
@@ -150,13 +186,22 @@
 """,
 r"""
 function() {
-  var a = null, i = 0;
+  var a = null, i = 0, v0;
   for (; i < 10; a = new V.main_closure(i), i = i + 1)
     ;
-  P.print(a.call$0());
+  v0 = H.S(a.call$0());
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
 
-  const TestEntry.forMethod('function(A#b)', """
+  const TestEntry("""
 class A {
   a() => 1;
   b() => () => a();
@@ -167,7 +212,16 @@
 """,
 r"""
 function() {
-  return new V.A_b_closure(this);
+  var v0 = H.S(new V.A_b_closure(V.A$()).call$0());
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
 
   const TestEntry("""
@@ -179,7 +233,8 @@
 """,
 r"""
 function(x) {
-  P.print(V.staticMethod(123));
+  P.print(123);
+  P.print(123);
 }"""),
 
   const TestEntry("""
@@ -193,7 +248,8 @@
 """,
 r"""
 function(x) {
-  P.print(V.Foo$().instanceMethod$1(123));
+  V.Foo$();
+  P.print(123);
 }"""),
 
   const TestEntry("""
@@ -208,9 +264,9 @@
 """,
 r"""
 function(x) {
-  var v0 = V.Foo$();
-  P.print(v0.instanceMethod$1(123));
-  P.print(v0.instanceMethod$1(321));
+  V.Foo$();
+  P.print(123);
+  P.print(321);
 }"""),
 
   const TestEntry("""
@@ -228,9 +284,11 @@
 """,
 r"""
 function(x) {
-  var notTearOff = V.Foo$().get$getter();
-  P.print(notTearOff.call$1(123));
-  P.print(notTearOff.call$1(321));
+  var v0 = new V.Foo_getter_closure();
+  V.Foo$();
+  P.print("getter");
+  P.print(v0.call$1(123));
+  P.print(v0.call$1(321));
 }"""),
 
   const TestEntry("""
@@ -247,7 +305,9 @@
 """,
 r"""
 function(x) {
-  P.print(V.Foo$().get$getter().call$1(123));
+  V.Foo$();
+  P.print("getter");
+  P.print(new V.Foo_getter_closure().call$1(123));
 }"""),
 ];
 
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_codeUnitAt_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_codeUnitAt_test.dart
index b3f2808..9da3350 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_codeUnitAt_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_codeUnitAt_test.dart
@@ -16,7 +16,16 @@
   print('A'.codeUnitAt(0));
 }""",r"""
 function() {
-  P.print(65);
+  var v0 = H.S(65);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
 
 
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_constructor_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_constructor_test.dart
index ec45a16..a3d9bcd 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_constructor_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_constructor_test.dart
@@ -9,7 +9,7 @@
 import 'js_backend_cps_ir.dart';
 
 const List<TestEntry> tests = const [
-  const TestEntry.forMethod('generative_constructor(Sub#)', """
+  const TestEntry("""
 class Base {
   var x;
   Base(this.x);
@@ -22,11 +22,20 @@
   print(new Sub(1, 2).x);
 }""",
 r"""
-function(x, y) {
-  return new V.Sub(y, x);
+function() {
+  var v0 = H.S(1);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
 
-  const TestEntry.forMethod('generative_constructor_body(Sub#)', """
+  const TestEntry("""
 class Base {
   var x;
   Base(this.x);
@@ -41,11 +50,12 @@
   print(new Sub(1, 2).x);
 }""",
 r"""
-function(x, y) {
-  P.print(x);
+function() {
+  P.print(1);
+  P.print(1);
 }"""),
 
-  const TestEntry.forMethod('generative_constructor(Sub#)', """
+  const TestEntry("""
 class Base0 {
   Base0() {
     print('Base0');
@@ -65,14 +75,13 @@
   print(new Sub(1, 2).x);
 }""",
 r"""
-function(x, y) {
-  var v0 = new V.Sub(y, x);
-  v0.Base0$0();
-  v0.Sub$2(x, y);
-  return v0;
+function() {
+  P.print("Base0");
+  P.print(1);
+  P.print(1);
 }"""),
 
-  const TestEntry.forMethod('generative_constructor(Sub#)', """
+  const TestEntry("""
 class Base0 {
   Base0() {
     print('Base0');
@@ -94,16 +103,16 @@
   print(new Sub(1, 2).x);
 }""",
 r"""
-function(x, y) {
-  var _box_0 = {}, v0 = new V.Sub(y, new V.Base_closure(_box_0));
-  _box_0.x1 = x;
-  v0.Base0$0();
-  v0.Base$1(_box_0);
-  v0.Sub$2(x, y);
-  return v0;
+function() {
+  var _box_0 = {};
+  _box_0.x1 = 1;
+  P.print("Base0");
+  P.print(_box_0.x1);
+  P.print(1);
+  P.print(new V.Base_closure(_box_0));
 }"""),
 
-  const TestEntry.forMethod('generative_constructor(Sub#)', """
+  const TestEntry("""
 foo(x) {
   print(x);
 }
@@ -125,12 +134,16 @@
 """,
 r"""
 function() {
-  var v0 = V.foo("y1"), v1 = V.foo("y2"), v2 = V.foo("x1"), v3 = V.foo("x3"), v4 = V.foo("x2");
-  return new V.Sub(v0, v1, V.foo("y3"), v2, v4, v3);
+  V.foo("y1");
+  V.foo("y2");
+  V.foo("x1");
+  V.foo("x3");
+  V.foo("x2");
+  V.foo("y3");
 }"""),
 
 
-  const TestEntry.forMethod('generative_constructor(Foo#)', """
+  const TestEntry("""
 class Bar {
   Bar(x, {y, z: 'z', w: '_', q}) {
     print(x);
@@ -149,9 +162,11 @@
 """,
 r"""
 function() {
-  var v0 = new V.Foo();
-  v0.Bar$5$q$w$y$z("x", null, "w", "y", "z");
-  return v0;
+  P.print("x");
+  P.print("y");
+  P.print("z");
+  P.print("w");
+  P.print(null);
 }"""),
   const TestEntry(r"""
 class C<T> {
@@ -161,7 +176,16 @@
   print(new C<int>().foo());
 }""", r"""
 function() {
-  P.print(V.C$(P.$int).foo$0());
+  var v0 = H.S(H.createRuntimeType(H.runtimeTypeToString(H.getTypeArgumentByIndex(V.C$(P.$int), 0))));
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
   const TestEntry(r"""
 class C<T> {
@@ -171,7 +195,18 @@
   print(new C<int>().foo());
 }""", r"""
 function() {
-  P.print(V.C$().foo$0());
+  var v0;
+  V.C$();
+  v0 = H.S(C.Type_C_cdS);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
   const TestEntry.forMethod('generative_constructor(C#)', r"""
 class C<T> {
@@ -202,7 +237,7 @@
 }"""),
 
 
-  const TestEntry.forMethod('generative_constructor(A#)', r"""
+  const TestEntry(r"""
 class A {
   var x;
   A() : this.b(1);
@@ -212,11 +247,20 @@
   print(new A().x);
 }""", r"""
 function() {
-  return new V.A(1);
+  var v0 = H.S(1);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
 
 
-const TestEntry.forMethod('factory_constructor(Foo#make)', r"""
+const TestEntry(r"""
 class Foo {
   factory Foo.make(x) {
     print('Foo');
@@ -228,9 +272,9 @@
 main() {
   print(new Foo.make(5));
 }""", r"""
-function(x) {
+function() {
   P.print("Foo");
-  return V.Foo$create(x);
+  P.print(new V.Foo(5));
 }"""),
 const TestEntry(r"""
 class Foo {
@@ -242,7 +286,19 @@
   print(new Foo.make(5));
 }""", r"""
 function() {
-  P.print(V.Foo$create(5));
+  var v0 = new V.Foo(5), v1 = "Instance of '" + H.Primitives_objectTypeName(v0) + "'";
+  if (!(typeof v1 === "string"))
+    throw H.wrapException(H.argumentErrorValue(v0));
+  v0 = v1;
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
 const TestEntry(r"""
 class A {
@@ -259,7 +315,7 @@
   new A(5).typevar;
 }""", r"""
 function() {
-  V.B$(5, P.$int).get$typevar();
+  V.B$(5, P.$int);
 }"""),
 ];
 
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_control_flow_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_control_flow_test.dart
index 2d9e07e..62f2537 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_control_flow_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_control_flow_test.dart
@@ -34,16 +34,22 @@
 }
 """, """
 function() {
-  L0:
+  L1:
     while (true)
-      while (true) {
-        while (V.foo(true))
-          if (V.foo(false)) {
-            P.print(2);
-            continue L0;
+      L0:
+        while (true)
+          while (true) {
+            P.print(true);
+            if (false) {
+              P.print(1);
+              continue L0;
+            }
+            P.print(false);
+            if (false) {
+              P.print(2);
+              continue L1;
+            }
           }
-        P.print(1);
-      }
 }"""),
   const TestEntry("""
 foo(a) { print(a); return a; }
@@ -56,13 +62,19 @@
   print(2);
 }""", """
 function() {
-  var i = 0;
-  for (; V.foo(true) === true; i = V.foo(i)) {
-    P.print(1);
-    if (V.foo(false) === true)
-      break;
+  while (true) {
+    P.print(true);
+    if (true === true) {
+      P.print(1);
+      P.print(false);
+      if (false !== true) {
+        P.print(0);
+        continue;
+      }
+    }
+    P.print(2);
+    return null;
   }
-  P.print(2);
 }"""),
 const TestEntry("""
 foo(a) { print(a); return a; }
@@ -77,8 +89,9 @@
  print(3);
 }""", """
 function() {
-  V.foo(false);
-  V.foo(true) ? P.print(1) : P.print(2);
+  P.print(false);
+  P.print(true);
+  true ? P.print(1) : P.print(2);
   P.print(3);
 }"""),
 const TestEntry("""
@@ -96,8 +109,9 @@
  print(3);
 }""", """
 function() {
-  V.foo(false);
-  if (V.foo(true)) {
+  P.print(false);
+  P.print(true);
+  if (true) {
     P.print(1);
     P.print(1);
   } else {
@@ -127,7 +141,7 @@
   }
 }""","""
 function() {
-  V.foo();
+  P.print("2");
   P.print("good");
 }"""),
   const TestEntry("""
@@ -138,9 +152,19 @@
   }
 }""",r"""
 function() {
-  var list = [1, 2, 3, 4, 5, 6], i = 0;
-  for (; i < 6; i = i + 1)
-    P.print(list[i]);
+  var list = [1, 2, 3, 4, 5, 6], i = 0, v0;
+  for (; i < 6; i = i + 1) {
+    v0 = H.S(list[i]);
+    if (typeof dartPrint == "function")
+      dartPrint(v0);
+    else if (typeof console == "object" && typeof console.log != "undefined")
+      console.log(v0);
+    else if (!(typeof window == "object")) {
+      if (!(typeof print == "function"))
+        throw "Unable to print message: " + String(v0);
+      print(v0);
+    }
+  }
 }"""),
   const TestEntry("""
 main() {
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_gvn_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_gvn_test.dart
index 27cfbae..604c19a 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_gvn_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_gvn_test.dart
@@ -9,7 +9,7 @@
 import 'js_backend_cps_ir.dart';
 
 const List<TestEntry> tests = const [
-  const TestEntry.forMethod('function(foo)', r"""
+  const TestEntry(r"""
 foo(x, list) {
   var sum = 0;
   for (int k = 0; k < 10; k++) {
@@ -51,18 +51,24 @@
   print(foo(z, [1,2,3,4,5,6,7,8,9,10]));
 }
 """,r"""
-function(x, list) {
-  var v0 = x.left, a = v0.left, b = v0.right, sum = 0, k = 0, c = (v0 = x.right).left, d = v0.right, v1, v2, v3, i, v4;
-  v0 = a.value;
-  v1 = c.value;
-  v2 = b.value;
-  for (v3 = d.value; k < 10; sum = sum + (i + list[v4]), k = k + 1) {
-    i = v0 + v1;
-    v4 = i * (v2 + v3);
-    if (v4 < 0 || v4 >= 10)
-      return H.ioore(list, v4);
+function() {
+  var v0 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], sum = 0, k = 0, i, v1;
+  for (; k < 10; sum = sum + (i + v0[v1]), k = k + 1) {
+    i = 1 + 20;
+    v1 = i * (10 + -10);
+    if (v1 < 0 || v1 >= 10)
+      return H.ioore(v0, v1);
   }
-  return sum;
+  v0 = H.S(sum);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
 ];
 
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart
index 4de37b1..382736c 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart
@@ -18,7 +18,16 @@
 }""",
 r"""
 function() {
-  P.print(4);
+  var v0 = H.S(4);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
   const TestEntry("""
 main() {
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_operators2_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_operators2_test.dart
index 1ced961..21ffdc5 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_operators2_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_operators2_test.dart
@@ -10,26 +10,26 @@
 
 const List<TestEntry> tests = const [
 
-  const TestEntry.forMethod('function(foo)',
-      r"""
+  const TestEntry(r"""
 foo(a, b) => ((a & 0xff0000) >> 1) & b;
 main() {
   print(foo(123, 234));
   print(foo(0, 2));
 }""", r"""
-function(a, b) {
-  return (a & 16711680) >>> 1 & b;
+function() {
+  P.print((123 & 16711680) >>> 1 & 234);
+  P.print((0 & 16711680) >>> 1 & 2);
 }"""),
 
-  const TestEntry.forMethod('function(foo)',
-      r"""
+  const TestEntry(r"""
 foo(a) => ~a;
 main() {
   print(foo(1));
   print(foo(10));
 }""", r"""
-function(a) {
-  return ~a >>> 0;
+function() {
+  P.print(~1 >>> 0);
+  P.print(~10 >>> 0);
 }"""),
 
   const TestEntry.forMethod('function(foo)',
@@ -40,29 +40,30 @@
   print(foo(-100));
 }""", r"""
 function(a) {
-  return C.JSInt_methods.$mod(a, 13);
+  var result = a % 13;
+  return result === 0 ? 0 : result > 0 ? result : 13 < 0 ? result - 13 : result + 13;
 }"""),
 
-  const TestEntry.forMethod('function(foo)',
-      r"""
+  const TestEntry(r"""
 foo(a) => a % 13;
 main() {
   print(foo(5));
   print(foo(100));
 }""", r"""
-function(a) {
-  return a % 13;
+function() {
+  P.print(5 % 13);
+  P.print(100 % 13);
 }"""),
 
-  const TestEntry.forMethod('function(foo)',
-      r"""
+  const TestEntry(r"""
 foo(a) => a.remainder(13);
 main() {
   print(foo(5));
   print(foo(-100));
 }""", r"""
-function(a) {
-  return a % 13;
+function() {
+  P.print(5 % 13);
+  P.print(-100 % 13);
 }"""),
 
   const TestEntry.forMethod('function(foo)',
@@ -73,18 +74,19 @@
   print(foo(-100));
 }""", r"""
 function(a) {
-  return C.JSInt_methods.$tdiv(a, 13);
+  var v0;
+  return (a | 0) === a && (13 | 0) === 13 ? a / 13 | 0 : J.getInterceptor$n(v0 = a / 13).toInt$0(v0);
 }"""),
 
-  const TestEntry.forMethod('function(foo)',
-      r"""
+  const TestEntry(r"""
 foo(a) => a ~/ 13;
 main() {
   print(foo(5));
   print(foo(100));
 }""", r"""
-function(a) {
-  return a / 13 | 0;
+function() {
+  P.print(5 / 13 | 0);
+  P.print(100 / 13 | 0);
 }"""),
 
   const TestEntry.forMethod('function(foo)',
@@ -95,7 +97,8 @@
   print(foo(8000000000));
 }""", r"""
 function(a) {
-  return C.JSInt_methods.$tdiv(a, 13);
+  var v0;
+  return (a | 0) === a && (13 | 0) === 13 ? a / 13 | 0 : J.getInterceptor$n(v0 = a / 13).toInt$0(v0);
 }"""),
 
 ];
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
index a6d7a1c..152a552 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
@@ -15,43 +15,89 @@
 foo() => ++x > 10;
 main() {
   print(foo() ? "hello world" : "bad bad");
-}""","""
+}""",r"""
 function() {
-  P.print(V.foo() ? "hello world" : "bad bad");
-}"""),
-  const TestEntry("""
-var x = 1;
-foo() => ++x > 10;
-main() {
-  print(foo() ? "hello world" : "bad bad");
-}""","""
-function() {
-  P.print(V.foo() ? "hello world" : "bad bad");
+  var v0 = $.x + 1;
+  $.x = v0;
+  v0 = v0 > 10 ? "hello world" : "bad bad";
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
   const TestEntry("""
 var x = 1;
 get foo => ++x > 10;
 main() {
   print(foo ? "hello world" : "bad bad");
-}""","""
+}""",r"""
 function() {
-  P.print(V.foo() ? "hello world" : "bad bad");
+  var v0 = $.x + 1;
+  $.x = v0;
+  v0 = v0 > 10 ? "hello world" : "bad bad";
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
   const TestEntry("""
 var x = 1;
 get foo => ++x > 10;
 main() { print(foo && foo); }
-""", """
+""", r"""
 function() {
-  P.print(V.foo() ? !!V.foo() : false);
+  var v0 = $.x + 1;
+  $.x = v0;
+  if (v0 > 10) {
+    $.x = v0 = $.x + 1;
+    v0 = v0 > 10;
+  } else
+    v0 = false;
+  v0 = H.S(v0);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
   const TestEntry("""
 var x = 1;
 get foo => ++x > 10;
 main() { print(foo || foo); }
-""","""
+""",r"""
 function() {
-  P.print(V.foo() ? true : !!V.foo());
+  var v0 = $.x + 1;
+  $.x = v0;
+  if (v0 > 10)
+    v0 = true;
+  else {
+    $.x = v0 = $.x + 1;
+    v0 = v0 > 10;
+  }
+  v0 = H.S(v0);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
 const TestEntry("""
 get foo => foo;
@@ -84,9 +130,20 @@
   print(list);
 }""", r"""
 function() {
-  var list = [1, 2, 3];
+  var list = [1, 2, 3], res, v0;
   list[1] = 6;
-  P.print(list);
+  if (!(typeof (res = C.JSArray_methods.toString$0(list)) === "string"))
+    throw H.wrapException(H.argumentErrorValue(list));
+  v0 = res;
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
 ];
 
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_runtime_types_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_runtime_types_test.dart
index 4353b69..fcdc6cb 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_runtime_types_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_runtime_types_test.dart
@@ -14,8 +14,7 @@
 const String createType = r'H.createRuntimeType';
 
 const List<TestEntry> tests = const [
-    const TestEntry.forMethod("function(C#foo)",
-r"""
+    const TestEntry(r"""
 class C<T> {
   foo() => print(T);
 }
@@ -23,12 +22,20 @@
 main() {
   new C<int>().foo();
 }""",
-"""
-function() {
-  return P.print($createType($typeToString($getTypeArgument(this, 0))));
-}"""),
-    const TestEntry.forMethod("function(C#foo)",
 r"""
+function() {
+  var v0 = H.S(H.createRuntimeType(H.runtimeTypeToString(H.getTypeArgumentByIndex(V.C$(P.$int), 0))));
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
+}"""),
+    const TestEntry(r"""
 class C<T, U> {
   foo() => print(U);
 }
@@ -38,11 +45,20 @@
 main() {
   new D().foo();
 }""",
-"""
+r"""
 function() {
-  return P.print($createType($typeToString($getSubstitutedTypeArgument(this, "C", 1))));
+  var v0 = H.S(H.createRuntimeType(H.runtimeTypeToString(H.getRuntimeTypeArgument(V.D$(), "C", 1))));
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
-  const TestEntry.forMethod('function(C#foo)', r"""
+  const TestEntry(r"""
 class C<T> {
   foo() => new D<C<T>>();
 }
@@ -51,9 +67,18 @@
 }
 main() {
   print(new C<int>().foo().bar());
-}""", """
+}""", r"""
 function() {
-  return V.D\$([V.C, $getTypeArgument(this, 0)]);
+  var v0 = H.S(H.createRuntimeType(H.runtimeTypeToString(H.getTypeArgumentByIndex(V.D$([V.C, H.getTypeArgumentByIndex(V.C$(P.$int), 0)]), 0))));
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
     const TestEntry.forMethod('generative_constructor(C#)', r"""
 class C<X, Y, Z> {
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart
index 7d9283e..bb19616 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart
@@ -9,7 +9,7 @@
 import 'js_backend_cps_ir.dart';
 
 const List<TestEntry> tests = const [
-  const TestEntry.forMethod('function(Sub#m)', """
+  const TestEntry("""
 class Base {
   m(x) {
     print(x+1);
@@ -22,8 +22,19 @@
   new Sub().m(100);
 }""",
 r"""
-function(x) {
-  return V.Base.prototype.m$1.call(this, x + 10);
+function() {
+  var v0;
+  V.Sub$();
+  v0 = H.S(100 + 10 + 1);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
 
   // Reenable when we support compiling functions that
@@ -51,7 +62,7 @@
 //   return V.Base.prototype.$add.call(null, v2, v1);
 // }"""),
 
-const TestEntry.forMethod('function(Sub#m)', """
+const TestEntry("""
 class Base {
   var field = 123;
 }
@@ -62,8 +73,17 @@
   print(new Sub().m(10));
 }""",
 r"""
-function(x) {
-  return x + this.field;
+function() {
+  var v0 = H.S(10 + V.Sub$().field);
+  if (typeof dartPrint == "function")
+    dartPrint(v0);
+  else if (typeof console == "object" && typeof console.log != "undefined")
+    console.log(v0);
+  else if (!(typeof window == "object")) {
+    if (!(typeof print == "function"))
+      throw "Unable to print message: " + String(v0);
+    print(v0);
+  }
 }"""),
 
 
diff --git a/tests/compiler/dart2js/memory_compiler.dart b/tests/compiler/dart2js/memory_compiler.dart
index ce01ed0..fa69df7 100644
--- a/tests/compiler/dart2js/memory_compiler.dart
+++ b/tests/compiler/dart2js/memory_compiler.dart
@@ -265,8 +265,7 @@
                                       List<String> options: const [],
                                       bool showDiagnostics: true}) {
   Uri libraryRoot = Uri.base.resolve('sdk/');
-  Uri packageRoot = Uri.base.resolveUri(
-      new Uri.file('${Platform.packageRoot}/'));
+  Uri packageRoot = Uri.base.resolve(Platform.packageRoot);
 
   var provider = new MemorySourceFileProvider(memorySourceFiles);
   var handler =
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 9a04a94..4045cfa 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -72,6 +72,7 @@
 
 [ $compiler == dart2js && $cps_ir ]
 16407_test: Pass # Please triage this failure.
+code_motion_exception_test: Fail # .toString to null check a primitive, triggered by inlining
 async_stacktrace_test/asyncStar: Crash # (foo()async*{try {tr...  cannot handle sync*/async* functions
 deferred/deferred_class_test: RuntimeError # Z.loadLibrary is not a function
 deferred/deferred_constant2_test: RuntimeError # U.loadLibrary is not a function
diff --git a/tests/compiler/dart2js_native/dart2js_native.status b/tests/compiler/dart2js_native/dart2js_native.status
index e83f9d9..ad3536a 100644
--- a/tests/compiler/dart2js_native/dart2js_native.status
+++ b/tests/compiler/dart2js_native/dart2js_native.status
@@ -6,12 +6,12 @@
 *: Skip
 
 [ $compiler == dart2js ]
-bound_closure_super_test: Fail
 call_on_native_class_test: CompileTimeError # Issue 14813
 native_no_such_method_exception4_frog_test: CompileTimeError # Issue 9631
 native_no_such_method_exception5_frog_test: CompileTimeError # Issue 9631
 
-[ $compiler == dart2js ]
+[ $compiler == dart2js && $cps_ir == false ]
+bound_closure_super_test: Fail
 fake_thing_test: Fail # Issue 13010
 
 [ $compiler == dart2js && $minified ]
@@ -21,10 +21,7 @@
 compute_this_script_test: Skip # Issue 17458
 
 [ $compiler == dart2js && $cps_ir ]
+foreign_test: RuntimeError # Fails due to inlining, please triage.  Expect.equals(expected: <1234567891011>, actual: <1234567891011>) fails
 native_exception_test: RuntimeError # Issue 24421
-native_method_inlining_test: RuntimeError # Please triage this failure.
 optimization_hints_test: RuntimeError # Please triage this failure.
-subclassing_constructor_1_test: RuntimeError # Please triage this failure.
 subclassing_constructor_2_test: RuntimeError # Please triage this failure.
-subclassing_super_field_1_test: RuntimeError # Please triage this failure.
-subclassing_super_field_2_test: RuntimeError # Please triage this failure.
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 2757d9e..88b3ccd 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -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.
 
-[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 bool_from_environment2_test: Skip
 bool_from_environment_test: Skip
 from_environment_const_type_test: Skip
@@ -14,18 +14,18 @@
 string_from_environment3_test: Skip
 string_from_environment_test: Skip
 
-[ $compiler == none ]
+[ ($compiler == none || $compiler == precompiler) ]
 unicode_test: Fail        # Bug 6706
 compare_to2_test: Fail    # Bug 4018
 
 symbol_test/01: Fail, Pass # bug 11669
 
 # #void should be a valid symbol.
-[ $compiler == none || $compiler == dart2js ]
+[ ($compiler == none || $compiler == precompiler) || $compiler == dart2js ]
 symbol_reserved_word_test/02: CompileTimeError # bug 20191
 symbol_reserved_word_test/05: CompileTimeError # bug 20191
 
-[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 symbol_reserved_word_test/02: RuntimeError # bug 20191 / dartium/drt cannot detect CompileTimeErrors
 symbol_reserved_word_test/05: RuntimeError # bug 20191 / dartium/drt cannot detect CompileTimeErrors
 
@@ -42,27 +42,27 @@
 
 # With the exception of 'void', const Symbol() should not accept reserved
 # words.
-[ $compiler == none || $compiler == dart2js ]
+[ ($compiler == none || $compiler == precompiler) || $compiler == dart2js ]
 symbol_reserved_word_test/04: MissingCompileTimeError # bug 11669, 19972
 symbol_reserved_word_test/07: MissingCompileTimeError # bug 11669, 19972
 symbol_reserved_word_test/10: MissingCompileTimeError # bug 11669, 19972
 
-[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 symbol_reserved_word_test/04: Fail # bug 11669, 19972 / dartium/drt cannot detect CompileTimeErrors
 symbol_reserved_word_test/07: Fail # bug 11669, 19972 / dartium/drt cannot detect CompileTimeErrors
 symbol_reserved_word_test/10: Fail # bug 11669, 19972 / dartium/drt cannot detect CompileTimeErrors
 
 # With the exception of 'void', new Symbol() should not accept reserved words.
-[ $compiler == none ]
+[ ($compiler == none || $compiler == precompiler) ]
 symbol_reserved_word_test/06: RuntimeError # bug 11669
 symbol_reserved_word_test/09: RuntimeError # bug 11669
 symbol_reserved_word_test/12: RuntimeError # bug 11669
 
-[ $compiler == none && $runtime != dartium && $runtime != drt && $runtime != ContentShellOnAndroid ]
+[ ($compiler == none || $compiler == precompiler) && $runtime != dartium && $runtime != drt && $runtime != ContentShellOnAndroid ]
 symbol_test/02: MissingCompileTimeError # bug 11669
 symbol_test/03: MissingCompileTimeError # bug 11669
 
-[ $compiler == none ]
+[ ($compiler == none || $compiler == precompiler) ]
 symbol_test/none: Fail # bug 11669
 symbol_operator_test/03: Fail # bug 11669
 string_case_test/01: Fail # Bug 18061
@@ -70,10 +70,10 @@
 iterable_return_type_test/01: RuntimeError # Issue 13646
 iterable_return_type_test/02: RuntimeError # Issue 13646
 
-[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 main_test: Fail  # Dartium needs to check for both main() and main(args).
 
-[ $compiler == none && $runtime == ContentShellOnAndroid ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == ContentShellOnAndroid ]
 core_runtime_types_test: Pass, Fail # Issue 20525
 
 [ $runtime == ff || $runtime == jsshell ]
@@ -170,7 +170,7 @@
 # The regexp tests are not verified to work on non d8/vm platforms yet.
 regexp/*: Skip
 
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
 regexp/global_test: Skip # Timeout. Issue 21709 and 21708
 
 [ $runtime != vm && $compiler != dart2analyzer]
@@ -182,7 +182,7 @@
 [ $mode == debug ]
 regexp/pcre_test: Pass, Slow # Timeout. Issue 22008
 
-[ $runtime == vm && $arch == simarmv5te ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $arch == simarmv5te ]
 int_parse_radix_test/*: Pass, Slow
 big_integer_parsed_mul_div_vm_test: Pass, Slow
 
@@ -211,7 +211,7 @@
 [ $compiler == dart2js && $cps_ir && $host_checked ]
 regexp/pcre_test: Crash # Stack Overflow
 
-[ $noopt ]
+[ ($noopt || $compiler == precompiler) ]
 apply3_test: CompileTimeError # Imports dart:mirrors
 regexp/stack-overflow_test: RuntimeError, OK # Smaller limit with irregex interpreter
 big_integer_huge_mul_vm_test: Pass, Timeout # --no_intrinsify
diff --git a/tests/corelib/string_replace_all_test.dart b/tests/corelib/string_replace_all_test.dart
index 299d56a..f63a9f7 100644
--- a/tests/corelib/string_replace_all_test.dart
+++ b/tests/corelib/string_replace_all_test.dart
@@ -46,6 +46,16 @@
 
   // Test replacing the empty string.
   Expect.equals("toAtoBtoCto", "ABC".replaceAll("", "to"));
+
+  // Pattern strings containing RegExp metacharacters - these are not
+  // interpreted as RegExps.
+  Expect.equals(r"$$", "||".replaceAll("|", r"$"));
+  Expect.equals(r"$$$$", "||".replaceAll("|", r"$$"));
+  Expect.equals(r"x$|x", "x|.|x".replaceAll("|.", r"$"));
+  Expect.equals(r"$$", "..".replaceAll(".", r"$"));
+  Expect.equals(r"[$$$$]", "[..]".replaceAll(".", r"$$"));
+  Expect.equals(r"[$]", "[..]".replaceAll("..", r"$"));
+  Expect.equals(r"$$", r"\\".replaceAll(r"\", r"$"));
 }
 
 testReplaceAllMapped() {
diff --git a/tests/html/html.status b/tests/html/html.status
index faeaa01..1783cf0 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -382,7 +382,7 @@
 
 # 'html' tests import the HTML library, so they only make sense in
 # a browser environment.
-[ $runtime == vm ]
+[ $runtime == vm || $runtime == dart_precompiled ]
 *: Skip
 
 [ $compiler == dart2js && ($runtime == drt || $runtime == ff) ]
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 04bb204..71e28ae 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -2,17 +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.
 
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
 browser/*: SkipByDesign  # Browser specific tests
 isolate_stress_test: Fail # Issue 12588: This should be able to pass when we have wrapper-less tests.
 
 [ $runtime != vm ]
 checked_test: Skip # Unsupported.
 
-[ $runtime == vm && $arch == mips && $mode == debug ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $arch == mips && $mode == debug ]
 mandel_isolate_test: Skip # Uses 600 MB Ram on our 1 GB test device.
 
-[ $compiler == none ]
+[ ($compiler == none || $compiler == precompiler) ]
 compile_time_error_test/01: Skip # Issue 12587
 ping_test: Skip           # Resolve test issues
 ping_pause_test: Skip     # Resolve test issues
@@ -20,7 +20,7 @@
 
 message3_test/int32x4: Crash, Timeout # Issue 21818
 
-[ $compiler == none && $runtime == ContentShellOnAndroid ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == ContentShellOnAndroid ]
 *: Skip # Isolate tests are timing out flakily on Android content_shell.  Issue 19795
 
 [ $compiler == dart2js && $runtime == safarimobilesim ]
@@ -78,25 +78,25 @@
 [ $compiler == dart2js && $runtime == chromeOnAndroid ]
 unresolved_ports_test: Pass, Timeout # Issue 15610
 
-[ $compiler == none && $runtime == drt ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == drt ]
 spawn_uri_nested_vm_test: Skip # Issue 14463
 
 [ $jscl ]
 spawn_uri_multi_test/none: RuntimeError # Issue 13544
 
-[ $compiler == none && ($runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) ]
 pause_test: Fail         # Not implemented yet
 
-[ $compiler == none && $runtime == ContentShellOnAndroid ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == ContentShellOnAndroid ]
 nested_spawn2_test: Skip # Issue 19127: This test is timing out.
 
-[ $compiler == none && ($runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == dartium || $runtime == ContentShellOnAndroid) ]
 spawn_uri_nested_vm_test: Skip # Issue 14479: This test is timing out.
 
-[ $compiler == none && $runtime == dartium && $arch == x64 ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == dartium && $arch == x64 ]
 isolate/spawn_uri_multi_test/01: Skip # Times out. Issue 24795
 
-[ $compiler == none && ( $runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ( $runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) ]
 typed_message_test: Crash, Fail # Issue 13921, 14400
 message_enum_test: Fail, OK # Issue 13921 Dom isolates don't support spawnFunction
 compile_time_error_test/none: Fail, OK # Issue 13921 Dom isolates don't support spawnFunction
@@ -143,9 +143,8 @@
 
 [ $compiler == dart2js && $cps_ir ]
 deferred_in_isolate2_test: RuntimeError # A.loadLibrary is not a function
-isolate_current_test: RuntimeError # Please triage this failure.
 
-[ $noopt ]
+[ ($noopt || $compiler == precompiler) ]
 # Imports dart:mirrors
 count_test: CompileTimeError
 cross_isolate_message_test: CompileTimeError
@@ -166,3 +165,19 @@
 stacktrace_message_test: CompileTimeError
 static_function_test: CompileTimeError
 unresolved_ports_test: CompileTimeError
+
+[ $runtime == dart_precompiled ]
+deferred_in_isolate_test: Skip # Isolate.spawnUri
+deferred_in_isolate2_test: Skip # Isolate.spawnUri
+exit_at_spawnuri_test: Skip # Isolate.spawnUri
+error_exit_at_spawnuri_test: Skip # Isolate.spawnUri
+issue_24243_parent_isolate_test: Skip # Isolate.spawnUri
+issue_21398_parent_isolate1_test: Skip # Isolate.spawnUri
+spawn_uri_exported_main_test: Skip # Isolate.spawnUri
+spawn_uri_test: Skip # Isolate.spawnUri
+spawn_uri_nested_vm_test: Skip # Isolate.spawnUri
+deferred_in_isolate_test: Skip # Isolate.spawnUri
+spawn_uri_multi_test: Skip # Isolate.spawnUri
+spawn_uri_vm_test: Skip # Isolate.spawnUri
+issue_21398_parent_isolate_test: Skip # Isolate.spawnUri
+error_at_spawnuri_test: Skip # Isolate.spawnUri
diff --git a/tests/language/const_string_test.dart b/tests/language/const_string_test.dart
index 4736ca4..13f1a9c 100644
--- a/tests/language/const_string_test.dart
+++ b/tests/language/const_string_test.dart
@@ -6,6 +6,8 @@
 
 // Exercises compile-time string constants
 
+const yz = "y" + "z";
+
 main() {
   // Constant comparisons are independent of the quotes used.
   Expect.isTrue(identical("abcd", 'abcd'));
@@ -34,4 +36,16 @@
   Expect.isTrue(identical('a\'b\'cd', "a" "'b'" 'c' "d"));
   Expect.isTrue(identical('a"b"cd', 'a' '"b"' 'c' "d"));
   Expect.isTrue(identical("a\"b\"cd", 'a' '"b"' 'c' "d"));
+
+  const a = identical("ab", "a" + "b");
+  Expect.isTrue(a);
+
+  const b = identical("xyz", "x" + yz);
+  Expect.isTrue(b);
+
+  const c = identical("12", "1" "2");
+  Expect.isTrue(c);
+
+  const d = identical("zyz", "z$yz");
+  Expect.isTrue(d);
 }
diff --git a/tests/language/language.status b/tests/language/language.status
index 79d8804..b16b0c9 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -5,15 +5,21 @@
 # This directory contains tests that are intended to show the
 # current state of the language.
 
-[ $compiler == none ]
+[ ($compiler == none || $compiler == precompiler) ]
 built_in_identifier_prefix_test: Fail # Issue 6970
 tearoff_constructor_basic_test: Skip # Crashes in checked mode -- hausner investigating
 
 # These bugs refer currently ongoing language discussions.
-constructor_initializer_test/none: Fail # Issue 12633
 constructor5_test: Fail # Issue 6422
 constructor6_test: Fail # Issue 6422
-closure_in_initializer_test: Fail # Issue 6422
+
+# Failures related to super call in ctor initializer list
+super_test: Fail, OK
+final_field_initialization_order_test: Fail, OK
+field_initialization_order_test: Fail, OK
+example_constructor_test: Fail, OK
+constructor3_test: Fail, OK
+constructor2_test: Fail, OK
 
 # Regular bugs which should be fixed.
 duplicate_export_negative_test: Fail # Issue 6134
@@ -34,24 +40,24 @@
 # Unsupported configuration specific imports.
 config_import_test: Fail # Issue 24581
 
-[ $compiler == none && $runtime == vm ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) ]
 class_keyword_test/02: MissingCompileTimeError # Issue 13627
 unicode_bom_test: Fail # Issue 16067
 vm/debug_break_enabled_vm_test/01: Crash, OK # Expected to hit breakpoint.
 try_catch_optimized1_test: Skip # Srdjan investigating
 
-[ $compiler == none && $checked ]
+[ ($compiler == none || $compiler == precompiler) && $checked ]
 type_variable_bounds4_test/01: Fail # Issue 14006
 
-[ $compiler == none ]
+[ ($compiler == none || $compiler == precompiler) ]
 dynamic_prefix_core_test/01: RuntimeError # Issue 12478
 multiline_strings_test: Fail # Issue 23020
 
-[ $compiler == none && ($runtime == vm || $runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && (($runtime == vm || $runtime == dart_precompiled) || $runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 dynamic_prefix_core_test/none: Fail # Issue 12478
 export_ambiguous_main_negative_test: Fail # Issue 14763
 
-[ $compiler == none && ($runtime == dartium || $runtime == ContentShellOnAndroid) && $unchecked ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == dartium || $runtime == ContentShellOnAndroid) && $unchecked ]
 assertion_test: Fail # Issue 14651.
 generic_test: Fail # Issue 14651.
 list_literal4_test: Fail # Issue 14651.
@@ -64,7 +70,7 @@
 type_checks_in_factory_method_test: Fail # Issue 14651.
 vm/type_vm_test: Fail # Issue 14651.
 
-[ $compiler == none && ( $runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ( $runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) ]
 issue13474_test: Pass, Fail # Issue 14651.
 vm/optimized_guarded_field_isolates_test: Fail # Issue 13921.
 main_test/01: Fail # Issue 20028
@@ -76,36 +82,36 @@
 mirror_in_static_init_test: Fail # Issue 22071
 vm/debug_break_enabled_vm_test/*: Skip # Issue 14651.
 
-[ $compiler == none && $runtime == dartium && $system == linux && $arch != x64 ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == dartium && $system == linux && $arch != x64 ]
 issue_22780_test/01 : Pass, Timeout # Issue 24473
 
-[ $compiler == none && $runtime == drt ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == drt ]
 disassemble_test: Pass, Fail # Issue 18122
 
-[ $compiler == none && $runtime == vm && $arch == mips && $checked ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && $arch == mips && $checked ]
 generic_instanceof3_test: Pass, Crash # Issue 17440.
 
-[ $compiler == none && $runtime == vm && $arch == mips && $mode == debug ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && $arch == mips && $mode == debug ]
 stack_overflow_test: Skip # Crashes. Issue 17440.
 stack_overflow_stacktrace_test: Skip # Crashes. Issue 17440.
 large_class_declaration_test: SkipSlow # Times out. Issue 20352
 
-[ $compiler == none && ($runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) && $mode == debug ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) && $mode == debug ]
 large_class_declaration_test: SkipSlow # Times out. Issue 20352
 
-[ $compiler == none && $runtime == ContentShellOnAndroid ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == ContentShellOnAndroid ]
 gc_test: SkipSlow # Times out flakily. Issue 20956
 
-[ $compiler == none && $runtime == vm && ( $arch == simarm || $arch == arm || $arch == simarmv5te || $arch == armv5te || $arch == simarm64 || $arch == arm64 || $arch == simmips || $arch == mips) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ( $arch == simarm || $arch == arm || $arch == simarmv5te || $arch == armv5te || $arch == simarm64 || $arch == arm64 || $arch == simmips || $arch == mips) ]
 vm/load_to_load_unaligned_forwarding_vm_test: Pass, Crash # Unaligned offset. Issue 22151
 
-[ $compiler == none && $runtime == dartium ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == dartium ]
 issue23244_test: Fail # Issue 23244
 
-[ $compiler == none && ($runtime == vm || $runtime == drt || $runtime == dartium) && $arch == ia32 ]
+[ ($compiler == none || $compiler == precompiler) && (($runtime == vm || $runtime == dart_precompiled) || $runtime == drt || $runtime == dartium) && $arch == ia32 ]
 vm/regress_24517_test: Pass, Fail # Issue 24517.
 
-[ $noopt ]
+[ ($noopt || $compiler == precompiler) ]
 # Imports dart:mirrors
 const_evaluation_test: CompileTimeError
 deferred_constraints_constants_test: CompileTimeError
@@ -139,3 +145,9 @@
 tearoff_basic_test: RuntimeError, Crash # Conflicting flag.
 vm/type_cast_vm_test: RuntimeError # Line number mismatch.
 stack_trace_test: Fail  # Issue 24783 - inlined frames missing
+
+[ $runtime == dart_precompiled ]
+ct_const2_test: Pass, Crash # Incompatible flag --compile_all
+hello_dart_test: Pass, Crash # Incompatible flag --compile_all
+
+implicit_closure_test: Pass, Crash # --use_slow_path
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index e872f46..2ec0676 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -165,7 +165,6 @@
 const_dynamic_type_literal_test/03: CompileTimeError # Issue 23009
 
 # Compilation errors.
-method_override5_test: RuntimeError # Issue 12809
 external_test/10: CompileTimeError # Issue 12887
 external_test/13: CompileTimeError # Issue 12887
 external_test/20: CompileTimeError # Issue 12887
@@ -217,12 +216,12 @@
 generic_field_mixin4_test: Crash # Issue 18651
 generic_field_mixin5_test: Crash # Issue 18651
 many_method_calls_test: Crash # Stack overflow in HGraphVisitor.visitPostDominatorTree.visitBasicBlockAndSuccessors
+method_override5_test: RuntimeError # Issue 12809
 
 [ $compiler == dart2js && $runtime != drt && $runtime != dartium ]
 issue23244_test: RuntimeError # 23244
 
 [ $compiler == dart2js && $cps_ir ]
-assert_assignable_type_test: Crash # Internal Error: Pending statics.
 async_await_syntax_test/a03a: Crash # (a03a()async*{}): cannot handle sync*/async* functions
 async_await_syntax_test/a03b: Crash # (a03b()async*{}): cannot handle sync*/async* functions
 async_await_syntax_test/a06a: Crash # (await for(var o in st){}): await for
@@ -336,6 +335,7 @@
 regress_22443_test: RuntimeError # M.loadLibrary is not a function
 regress_23408_test: RuntimeError # G.loadLibrary is not a function
 regress_23500_test/01: Crash # (await for(var c in new Stream.fromIterable([] )){}): await for
+stack_trace_test: Fail # Stack trace not preserved when inlining?
 super_call4_test: RuntimeError # Please triage this failure.
 super_getter_setter_test: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
 super_operator_index5_test: Crash # (super[0]=42): visitUnresolvedSuperIndexSet
@@ -351,6 +351,9 @@
 type_variable_field_initializer_test: RuntimeError # Please triage this failure.
 type_variable_nested_test: RuntimeError # Please triage this failure.
 
+[ $compiler == dart2js && $cps_ir && $host_checked == false ]
+regress_21795_test: RuntimeError # Due to inlining?
+
 [ $compiler == dart2js && $cps_ir && $host_checked ]
 async_throw_in_catch_test/forceAwait: Crash # Issue 24485
 async_throw_in_catch_test/none: Crash # Issue 24485
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 8c17e5b..5a8dcdb 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -186,7 +186,7 @@
 
 # 'js' tests import the dart:js library, so they only make sense in
 # a browser environment.
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
 js/*: Skip
 
 [ $compiler == dart2js && $minified ]
@@ -223,19 +223,19 @@
 # TODO(efortuna): Investigate.
 async/timer_test: Fail, Pass
 
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
 async/timer_not_available_test: Fail, OK
 mirrors/native_class_test: Fail, OK # This test is meant to run in a browser.
 mirrors/deferred_type_test: CompileTimeError, OK # Don't have a multitest marker for dynamic compile time errors.
 
-[ $compiler == none ]
+[ ($compiler == none || $compiler == precompiler) ]
 async/timer_not_available_test: SkipByDesign # only meant to test when there is no way to implement timer (currently only in d8)
 
 mirrors/symbol_validation_test: RuntimeError # Issue 13596
 
 mirrors/mirrors_used*: SkipByDesign # Invalid tests. MirrorsUsed does not have a specification, and dart:mirrors is not required to hide declarations that are not covered by any MirrorsUsed annotation.
 
-[ $compiler == none && ( $runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ( $runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 async/schedule_microtask6_test: Fail # Issue 10910
 async/timer_test: Fail, Pass # Issue 15487
 async/multiple_timer_test: Fail, Pass # Issue 15487
@@ -248,14 +248,14 @@
 mirrors/local_isolate_test: RuntimeError # Issue 12188
 mirrors/deferred_type_test: RuntimeError, OK # Should be CompileTimeError. Issue 22072
 
-[ $compiler == none && $runtime == drt && $system == windows ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == drt && $system == windows ]
 async/multiple_timer_test: Fail, Pass # See Issue 10982
 async/timer_test: Fail, Pass # See Issue 10982
 
-[ $compiler == none && $runtime == drt && $checked ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == drt && $checked ]
 async/slow_consumer_test: Fail, Pass # Dartium JsInterop failure, dartbug.com/24460
 
-[$compiler == none && $runtime == ContentShellOnAndroid ]
+[($compiler == none || $compiler == precompiler) && $runtime == ContentShellOnAndroid ]
 async/stream_timeout_test: RuntimeError, Pass # Issue 19127
 async/slow_consumer3_test: SkipSlow # Times out flakily. Issue 20956
 async/slow_consumer2_test: SkipSlow # Times out flakily. Issue 20956
@@ -305,7 +305,7 @@
 [ $compiler == dart2js && $mode == debug ]
 mirrors/native_class_test: Pass, Slow
 
-[ $compiler == none && $arch == mips ]
+[ ($compiler == none || $compiler == precompiler) && $arch == mips ]
 async/timer_regress22626_test: Pass, RuntimeError # Issue 22626
 
 [ $arch == simarm || $arch == simarmv5te ]
@@ -325,16 +325,16 @@
 [ $mode == debug && $arch == ia32 && $system == windows ]
 convert/streamed_conversion_json_utf8_decode_test: Skip  # Verification OOM.
 
-[ $runtime == vm && $mode == debug && $arch == x64 && $system == windows ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $mode == debug && $arch == x64 && $system == windows ]
 convert/streamed_conversion_json_utf8_decode_test: Pass, Slow
 
-[ $runtime == vm && $mode == release && $arch == ia32 && $system == windows ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $mode == release && $arch == ia32 && $system == windows ]
 convert/json_test: RuntimeError # Issue 24908
 
 [ $mode == debug && $arch != ia32 && $arch != x64 && $arch != simarm && $arch != simarmv5te ]
 convert/streamed_conversion_json_utf8_decode_test: Skip  # Verification not yet implemented.
 
-[ $runtime == vm && $mode == debug && $builder_tag == asan ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $mode == debug && $builder_tag == asan ]
 mirrors/immutable_collections_test: SkipSlow  # Timeout.
 convert/streamed_conversion_json_utf8_decode_test: Skip  # Timeout.
 
@@ -357,7 +357,7 @@
 [ $compiler != dart2js ]
 async/dart2js_uncaught_error_test: Skip  # JS-integration only test
 
-[ $noopt ]
+[ ($noopt || $compiler == precompiler) ]
 mirrors/*: SkipByDesign
 convert/chunked_conversion_utf88_test: Pass, Timeout
 convert/utf85_test: Pass, Timeout
diff --git a/tests/standalone/io/create_sample_certificates.sh b/tests/standalone/io/create_sample_certificates.sh
index 7ab6f75..cabe747 100755
--- a/tests/standalone/io/create_sample_certificates.sh
+++ b/tests/standalone/io/create_sample_certificates.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # 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.
diff --git a/tests/standalone/precompilation_dart2js_test.dart b/tests/standalone/precompilation_dart2js_test.dart
index 303c955..5d3900e 100644
--- a/tests/standalone/precompilation_dart2js_test.dart
+++ b/tests/standalone/precompilation_dart2js_test.dart
@@ -43,8 +43,7 @@
     return;
   }
 
-  var pkgRoot = Uri.parse(Platform.packageRoot);
-  var abs_package_root = new File.fromUri(pkgRoot).absolute.path;
+  var abs_package_root = Uri.parse(Platform.packageRoot).toFilePath();
   var dart_executable =
       Directory.current.path + Platform.pathSeparator + Platform.executable;
   Directory tmp;
diff --git a/tests/standalone/regress_25335_test.dart b/tests/standalone/regress_25335_test.dart
new file mode 100644
index 0000000..e4551a2
--- /dev/null
+++ b/tests/standalone/regress_25335_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Test that canonicalization inserts constants with correct representation.
+// VMOptions=--optimization-counter-threshold=10 --optimization-filter=bar
+
+import 'dart:typed_data';
+
+toSigned(v, width) {
+  var signMask = 1 << (width - 1);
+  return (v & (signMask - 1)) - (v & signMask);
+}
+
+foo(value) {
+  return value >> 32;
+}
+
+bar(td) {
+  return toSigned(foo(td[0]), 64);
+}
+
+main() {
+  toSigned(1 << 1, 32);
+  toSigned(1 << 32, 32);
+
+  var l = new Int64List(1);
+  l[0] = 0xf8f7f6f5f4f3f2f1;
+
+  for (var i = 0; i < 20; i++) {
+    bar(l);
+  }
+}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 241086a..948099d 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -17,15 +17,15 @@
 
 javascript_compatibility_errors_test/none: Fail, OK  # Not possible to exclude or annotate with '/// none:'
 
-[ $runtime != vm && ($runtime != drt || $compiler != none)) ]
+[ ($runtime != vm && $runtime != dart_precompiled) && ($runtime != drt || $compiler != none)) ]
 no_assert_test: Fail, OK # This is testing a vm flag.
 
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
 package/package_isolate_test: Fail # Issue 12474
 io/observatory_test: Fail
 package/scenarios/invalid/same_package_twice_test: Pass # Issue 24119
 
-[ $runtime == vm && $checked ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $checked ]
 # These tests have type errors on purpose.
 io/process_invalid_arguments_test: Fail, OK
 io/directory_invalid_arguments_test: Fail, OK
@@ -38,13 +38,13 @@
 io/file_fuzz_test: Skip
 io/directory_fuzz_test: Skip
 
-[ $runtime == vm && $system == macos ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $system == macos ]
 # This test fails with "Too many open files" on the Mac OS buildbot.
 # This is expected as MacOS by default runs with a very low number
 # of allowed open files ('ulimit -n' says something like 256).
 io/socket_many_connections_test: Skip
 
-[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 typed_array_test: Fail # Issue 13921
 typed_array_int64_uint64_test: Fail # Issue 13921
 typed_data_isolate_test: SkipByDesign # This test uses dart:io
@@ -106,6 +106,7 @@
 precompilation_test: Skip # Standalone only test.
 precompilation_dart2js_test: Skip # Standalone only test.
 noopt_test: Skip # Standalone only test.
+regress_25335_test: Skip # Int64List not supported.
 
 [ $runtime == vm && $mode == debug ]
 precompilation_dart2js_test: Pass, Slow
@@ -157,10 +158,10 @@
 full_coverage_test: SkipSlow # Times out. Issue 20352
 io/http_client_stays_alive_test: Skip # Timing dependent test, MIPS machine too slow.
 
-[ $compiler == none && ($runtime == dartium || $runtime == ContentShellOnAndroid) && $unchecked ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == dartium || $runtime == ContentShellOnAndroid) && $unchecked ]
 assert_test: Fail # Issue 14651.
 
-[ $compiler == none && ($runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == dartium || $runtime == ContentShellOnAndroid) ]
 javascript_int_overflow_literal_test/01: Fail # Issue 14651.
 javascript_int_overflow_test: Fail # Issue 14651.
 
@@ -205,19 +206,62 @@
 [ $arch != ia32 && $arch != x64 && $arch != simarm && $arch != simarmv5te && $mode == debug ]
 verified_mem_test: Skip  # Not yet implemented.
 
-[ $runtime == vm && $mode == debug && $builder_tag == asan ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $mode == debug && $builder_tag == asan ]
 full_coverage_test: Skip  # Timeout.
 io/file_lock_test: Skip  # Timeout.
 io/test_runner_test: Skip  # Timeout.
 io/http_client_stays_alive_test: Skip  # Timeout.
 
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
 # Failures in secure networking while NSS is replaced with BoringSSL
 io/https_client_certificate_test: RuntimeError # Issue 24070
 io/secure_socket_renegotiate_test: RuntimeError
 io/secure_socket_bad_data_test: RuntimeError  # An error in a secure connection just puts a READ_CLOSED on the stream, rather than signaling an error on the stream.
 
-[ $noopt ]
+[ ($noopt || $compiler == precompiler) ]
 map_literal_oom_test: Pass, Crash # Issue 24678
 javascript*: SkipByDesign # JS overflow flag unsupported
 io/web_socket_test: Pass, RuntimeError # Issue 24674
+
+[ $runtime == dart_precompiled ]
+debugger/*: Skip
+noopt_test: Skip
+precompilation_dart2js_test: Skip
+
+full_coverage_test: RuntimeError # Platform.executable
+http_launch_test: RuntimeError # Platform.executable
+io/addlatexhash_test: RuntimeError # Platform.executable
+io/compile_all_test: Crash # Incompatible flag --compile_all
+io/file_read_special_device_test: RuntimeError # Platform.executable
+io/file_stream_test: RuntimeError # Platform.executable
+io/file_test: RuntimeError # Platform.executable
+io/http_cross_process_test: RuntimeError # Platform.executable
+io/https_unauthorized_test: RuntimeError # Platform.executable
+io/platform_resolved_executable_test: RuntimeError # Platform.resolvedExecutable
+io/skipping_dart2js_compilations_test: RuntimeError # Platform.executable
+io/snapshot_fail_test: RuntimeError # Platform.executable
+io/stdin_sync_test: RuntimeError # Platform.executable
+io/test_extension_fail_test: RuntimeError # Platform.executable
+precompilation_test: RuntimeError # Platform.executable
+standalone/io/file_read_special_device_test: RuntimeError # Platform.executable
+verbose_gc_to_bmu_test: RuntimeError # Platform.executable
+io/http_server_close_response_after_error_test: RuntimeError # Platform.executable
+io/http_client_stays_alive_test: RuntimeError # Platform.executable
+io/print_sync_test: RuntimeError # Platform.executable
+io/signals_test: RuntimeError # Platform.executable
+io/stdio_nonblocking_test: RuntimeError # Platform.executable
+io/regress_7191_test: RuntimeError # Platform.executable
+io/secure_unauthorized_test: RuntimeError # Platform.executable
+io/dart_std_io_pipe_test: RuntimeError # Platform.executable
+io/platform_test: RuntimeError # Platform.executable
+io/socket_cross_process_test: RuntimeError # Platform.executable
+io/test_runner_test: RuntimeError # Platform.executable
+io/file_lock_test: RuntimeError # Platform.executable
+io/code_collection_test: RuntimeError # Platform.executable
+io/file_lock_test: RuntimeError # Platform.executable
+io/code_collection_test: RuntimeError # Platform.executable
+io/raw_socket_cross_process_test: RuntimeError # Platform.executable
+io/test_extension_test: RuntimeError # Platform.executable
+io/regress_7679_test: RuntimeError # Platform.executable
+
+io/process_*: Skip # Most use Platform.executable
\ No newline at end of file
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index 1f6c520..bf69360 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -13,14 +13,14 @@
 [ $compiler == dart2js && $browser ]
 *: Skip
 
-[ $compiler == none && $runtime != vm ]
+[ ($compiler == none || $compiler == precompiler) && $runtime != vm ]
 dart2js_test: SkipByDesign # Uses dart:io.
 
 
 [ $compiler == dart2js && $mode == debug ]
 dummy_compiler_test: Slow, Pass
 
-[ $compiler == none && $runtime == ContentShellOnAndroid ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == ContentShellOnAndroid ]
 dummy_compiler_test: Pass, RuntimeError # Issue 17662
 recursive_import_test: Pass, RuntimeError # Issue 17662
 source_mirrors_test: Pass, RuntimeError # Issue 17662
@@ -30,5 +30,5 @@
 recursive_import_test: Crash # (switch (function.na...  continue to a labeled switch case
 source_mirrors_test: Crash, Slow # (switch (function.na...  continue to a labeled switch case
 
-[ $noopt ]
+[ ($noopt || $compiler == precompiler) ]
 source_mirrors_test: SkipByDesign # Imports dart:mirrors
diff --git a/third_party/.gitignore b/third_party/.gitignore
index a55ad28..3f481f1 100644
--- a/third_party/.gitignore
+++ b/third_party/.gitignore
@@ -6,4 +6,9 @@
 !pkg
 !pkg_tested
 !boringssl
+!drt_resources
 !d8
+!7zip.tar.gz.sha1
+!firefox_jsshell
+!gsutil.tar.gz.sha1
+!clang.tar.gz.sha1
\ No newline at end of file
diff --git a/third_party/7zip.tar.gz.sha1 b/third_party/7zip.tar.gz.sha1
new file mode 100644
index 0000000..83e790b
--- /dev/null
+++ b/third_party/7zip.tar.gz.sha1
@@ -0,0 +1 @@
+22fe352b3c39c4281a599cf8576abef80ec44cc9
\ No newline at end of file
diff --git a/third_party/clang.tar.gz.sha1 b/third_party/clang.tar.gz.sha1
new file mode 100644
index 0000000..027ff64
--- /dev/null
+++ b/third_party/clang.tar.gz.sha1
@@ -0,0 +1 @@
+9eec86b20d62ad8d5bc6af617e91f01ae4354166
\ No newline at end of file
diff --git a/third_party/drt_resources/.gitignore b/third_party/drt_resources/.gitignore
new file mode 100644
index 0000000..7912236
--- /dev/null
+++ b/third_party/drt_resources/.gitignore
@@ -0,0 +1 @@
+AHEM____.TTF
diff --git a/third_party/drt_resources/AHEM____.TTF.sha1 b/third_party/drt_resources/AHEM____.TTF.sha1
new file mode 100644
index 0000000..bba0dbc
--- /dev/null
+++ b/third_party/drt_resources/AHEM____.TTF.sha1
@@ -0,0 +1 @@
+8cdc9e68594fbb6db8c7b4bff643ab2432b51db6
\ No newline at end of file
diff --git a/third_party/drt_resources/README.md b/third_party/drt_resources/README.md
new file mode 100644
index 0000000..c981e5b
--- /dev/null
+++ b/third_party/drt_resources/README.md
@@ -0,0 +1,6 @@
+# Content-shell resources
+
+The layout tests of content_shell (formerly called DumpRenderTree, drt)
+require a font called AHEM____.TTF on Windows. This resource is downloaded
+from cloud storage, using the hash in AHEM____.TTF.sha1, by a hook
+in the DEPS file, that is run by gclient sync or gclient runhooks.
diff --git a/third_party/firefox_jsshell/README.google b/third_party/firefox_jsshell/README.google
new file mode 100644
index 0000000..08b90f8
--- /dev/null
+++ b/third_party/firefox_jsshell/README.google
@@ -0,0 +1,12 @@
+Name: Firefox command line javascript shell.
+Short Name: js-shell
+URL: http://ftp.mozilla.org/pub/mozilla.org/firefox/candidates/38-candidates/build2/
+Version: JavaScript-C38
+Date: May 05 2015
+License: MPL, http://www.mozilla.org/MPL
+
+Description:
+This directory contains the firefox js-shell binaries for Windows, Mac and
+Linux.
+The binaries are used for testing dart code compiled to javascript.
+
diff --git a/third_party/firefox_jsshell/linux/jsshell.tar.gz.sha1 b/third_party/firefox_jsshell/linux/jsshell.tar.gz.sha1
new file mode 100644
index 0000000..8f8d719
--- /dev/null
+++ b/third_party/firefox_jsshell/linux/jsshell.tar.gz.sha1
@@ -0,0 +1 @@
+624241d790b53c24ea67997ed658f31f1ed9292d
\ No newline at end of file
diff --git a/third_party/firefox_jsshell/mac/jsshell.tar.gz.sha1 b/third_party/firefox_jsshell/mac/jsshell.tar.gz.sha1
new file mode 100644
index 0000000..a5c645a
--- /dev/null
+++ b/third_party/firefox_jsshell/mac/jsshell.tar.gz.sha1
@@ -0,0 +1 @@
+16c59a086b713720df0154cd4ceaed2ee8cf0d33
\ No newline at end of file
diff --git a/third_party/firefox_jsshell/win/jsshell.tar.gz.sha1 b/third_party/firefox_jsshell/win/jsshell.tar.gz.sha1
new file mode 100644
index 0000000..d43fcd1
--- /dev/null
+++ b/third_party/firefox_jsshell/win/jsshell.tar.gz.sha1
@@ -0,0 +1 @@
+a7ed194f518813a9915f67026ef138dd96adfec1
\ No newline at end of file
diff --git a/third_party/gsutil.tar.gz.sha1 b/third_party/gsutil.tar.gz.sha1
new file mode 100644
index 0000000..cfc510a
--- /dev/null
+++ b/third_party/gsutil.tar.gz.sha1
@@ -0,0 +1 @@
+99b82a42b98b78fc2a3f155995a16d8d7517b657
\ No newline at end of file
diff --git a/third_party/pkg/petitparser.tar.gz.sha1 b/third_party/pkg/petitparser.tar.gz.sha1
new file mode 100644
index 0000000..20b3196
--- /dev/null
+++ b/third_party/pkg/petitparser.tar.gz.sha1
@@ -0,0 +1 @@
+9626eed1ad9963e782f55a943ee8a1f82ff251a1
\ No newline at end of file
diff --git a/tools/FAKE_COMMITS b/tools/FAKE_COMMITS
index 709ba90..4a2c46d 100644
--- a/tools/FAKE_COMMITS
+++ b/tools/FAKE_COMMITS
@@ -15,3 +15,4 @@
 Trigger bots 
 Purple is the new green.
 googlecode back up
+CIT outage - all slaves rebooted
diff --git a/tools/VERSION b/tools/VERSION
index 083073e..d53b55e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 14
 PATCH 0
-PRERELEASE 5
+PRERELEASE 6
 PRERELEASE_PATCH 0
diff --git a/tools/apps/update_homebrew/bin/ssh_with_key b/tools/apps/update_homebrew/bin/ssh_with_key
index 210ad1c..6df4a04 100755
--- a/tools/apps/update_homebrew/bin/ssh_with_key
+++ b/tools/apps/update_homebrew/bin/ssh_with_key
@@ -1,2 +1,2 @@
-#!/bin/bash
+#!/usr/bin/env bash
 ssh -i $SSH_KEY_PATH $@
diff --git a/tools/apps/update_homebrew/bin/update_homebrew.dart b/tools/apps/update_homebrew/bin/update_homebrew.dart
index 50474c93..4623e9a 100644
--- a/tools/apps/update_homebrew/bin/update_homebrew.dart
+++ b/tools/apps/update_homebrew/bin/update_homebrew.dart
@@ -186,7 +186,7 @@
 
   def shim_script target
     <<-EOS.undent
-      #!/bin/bash
+      #!/usr/bin/env bash
       exec "#{prefix}/#{target}" "\$@"
     EOS
   end
diff --git a/tools/bots/run_android_tests.sh b/tools/bots/run_android_tests.sh
index 6bd2034..4b05094 100755
--- a/tools/bots/run_android_tests.sh
+++ b/tools/bots/run_android_tests.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # 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.
diff --git a/tools/create_debian_chroot.sh b/tools/create_debian_chroot.sh
index fdb1cf2..0f42c3e3 100755
--- a/tools/create_debian_chroot.sh
+++ b/tools/create_debian_chroot.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 #
 # 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
diff --git a/tools/dartium/download_shellscript_template.sh b/tools/dartium/download_shellscript_template.sh
index 3399945..5e44053 100644
--- a/tools/dartium/download_shellscript_template.sh
+++ b/tools/dartium/download_shellscript_template.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # 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.
diff --git a/tools/dartium/start_dartium_roll.sh b/tools/dartium/start_dartium_roll.sh
index 41aebbf..d908620 100755
--- a/tools/dartium/start_dartium_roll.sh
+++ b/tools/dartium/start_dartium_roll.sh
@@ -1,4 +1,6 @@
-#!/bin/bash -e
+#!/usr/bin/env bash
+
+set -e
 
 # Requirements:
 #    sudo apt-get install xclip
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index 08529ef..135dd34 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -69,6 +69,7 @@
   "yaml_rev": "@563a5ffd4a800a2897b8f4dd6b19f2a370df2f2b",
   "zlib_rev": "@c3d0a6190f2f8c924a05ab6cc97b8f975bddd33f",
   "web_components_rev": "@0e636b534d9b12c9e96f841e6679398e91a986ec",
+  "WebCore_rev": "@4f90b41b0165f23f412cecdba07b7d81d3fbb5b5",
 
   "co19_rev": "@3ed795ea02e022ef19c77cf1b6095b7c8f5584d0",
 })
@@ -186,7 +187,7 @@
       (Var("github_mirror") % "test") + Var("unittest_tag"),
 
   "src/dart/third_party/WebCore":
-    "http://dart.googlecode.com/svn/third_party/WebCore",
+    "https://github.com/dart-lang/webcore.git" + Var("WebCore_rev"),
 
   "src/dart/tests/co19/src":
       (Var("github_mirror") % "co19") + Var("co19_rev"),
diff --git a/tools/dom/scripts/go.sh b/tools/dom/scripts/go.sh
index 946bdb9..c17719f 100755
--- a/tools/dom/scripts/go.sh
+++ b/tools/dom/scripts/go.sh
@@ -1,5 +1,8 @@
-#!/bin/bash -x
+#!/usr/bin/env bash
 #
+
+set -x
+
 #   go.sh [systems]
 #
 # Convenience script to generate systems.  Do not call from build steps or tests
diff --git a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
index 1b4b7e6..191d2db 100644
--- a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
@@ -295,16 +295,9 @@
             createdParametersValid = createdParametersValid && parameter.isOptional;
           });
         }
-
-        // Get the created constructor source and look at the initializer;
-        // Must call super.created() if not its as an error.
-        var createdSource = methodMirror.source;
-        superCreatedCalled = createdSource.contains("super.created(");
       }
 
-      if (!superCreatedCalled) {
-        throw new DomException.jsInterop('created constructor initializer must call super.created()');
-      } else if (!createdParametersValid) {
+      if (!createdParametersValid) {
         throw new DomException.jsInterop('created constructor must have no parameters');
       }
 
diff --git a/tools/dom/templates/html/impl/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate
index 896e204..d891762 100644
--- a/tools/dom/templates/html/impl/impl_Window.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Window.darttemplate
@@ -47,10 +47,11 @@
    */
   Document get document => JS('Document', '#.document', this);
 
-  WindowBase _open2(url, name) => JS('Window', '#.open(#,#)', this, url, name);
+  WindowBase _open2(url, name) =>
+      JS('Window|Null', '#.open(#,#)', this, url, name);
 
   WindowBase _open3(url, name, options) =>
-      JS('Window', '#.open(#,#,#)', this, url, name, options);
+      JS('Window|Null', '#.open(#,#,#)', this, url, name, options);
 
   /**
    * Opens a new window.
diff --git a/tools/precompilation/precompiler.dart b/tools/precompilation/precompiler.dart
new file mode 100755
index 0000000..419875a
--- /dev/null
+++ b/tools/precompilation/precompiler.dart
@@ -0,0 +1,64 @@
+// 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 precompiler;
+
+import 'dart:io';
+
+void run(String executable, String arguments, [String workingDirectory]) {
+  print("+ $executable ${arguments.join(' ')}");
+  var result = Process.runSync(executable, arguments,
+                               workingDirectory: workingDirectory);
+  stdout.write(result.stdout);
+  stderr.write(result.stderr);
+  if (result.exitCode != 0) {
+    exit(result.exitCode);
+  }
+}
+
+void main(List<String> args) {
+  var configuration = Platform.environment["DART_CONFIGURATION"];
+
+  var cc, cc_flags, shared, libname;
+  if (Platform.isLinux) {
+    cc = 'gcc';
+    shared = '-shared';
+    libname = 'libprecompiled.so';
+  } else if (Platform.isMacOS) {
+    cc = 'clang';
+    shared = '-dynamiclib';
+    libname = 'libprecompiled.dylib';
+  } else {
+    print("Test only supports Linux and Mac");
+    return;
+  }
+
+  if (configuration.endsWith("X64")) {
+    cc_flags = "-m64";
+  } else if (configuration.endsWith("SIMARM64")) {
+    cc_flags = "-m64";
+  } else if (configuration.endsWith("SIMARM")) {
+    cc_flags = "-m32";
+  } else if (configuration.endsWith("SIMMIPS")) {
+    cc_flags = "-m32";
+  } else if (configuration.endsWith("ARM")) {
+    cc_flags = "";
+  } else if (configuration.endsWith("MIPS")) {
+    cc_flags = "-EL";
+  } else {
+    print("Architecture not supported: $configuration");
+    return;
+  }
+
+  var tmpDir;
+  for (var arg in args) {
+    if (arg.startsWith("--gen-precompiled-snapshot")) {
+      tmpDir = arg.substring("--gen-precompiled-snapshot".length + 1);
+    }
+  }
+  print("Using directory $tmpDir");
+
+  run(args[0], args.sublist(1));
+  run(cc, [shared, cc_flags, "-o", libname, "precompiled.S"], tmpDir);
+}
diff --git a/tools/precompilation/test_linux.sh b/tools/precompilation/test_linux.sh
index f5b1865..553dc18b 100755
--- a/tools/precompilation/test_linux.sh
+++ b/tools/precompilation/test_linux.sh
@@ -1,4 +1,6 @@
-#!/bin/bash -ex
+#!/usr/bin/env bash
+
+set -ex
 
 # Usage:
 #   cd sdk
diff --git a/tools/precompilation/test_linux_simarm.sh b/tools/precompilation/test_linux_simarm.sh
index f87c6a5..e61b58b 100755
--- a/tools/precompilation/test_linux_simarm.sh
+++ b/tools/precompilation/test_linux_simarm.sh
@@ -1,4 +1,6 @@
-#!/bin/bash -ex
+#!/usr/bin/env bash
+
+set -ex
 
 # Usage:
 #   cd sdk
diff --git a/tools/precompilation/test_macos.sh b/tools/precompilation/test_macos.sh
index 510478f..57e02dc 100755
--- a/tools/precompilation/test_macos.sh
+++ b/tools/precompilation/test_macos.sh
@@ -1,4 +1,6 @@
-#!/bin/bash -ex
+#!/usr/bin/env bash
+
+set -ex
 
 # Usage:
 #   cd sdk
diff --git a/tools/presubmit.sh b/tools/presubmit.sh
index a3e6f8a..bedee8b 100755
--- a/tools/presubmit.sh
+++ b/tools/presubmit.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 #
 # Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
diff --git a/tools/testing/bin/jsshell b/tools/testing/bin/jsshell
index 359950d..c9dc261 100755
--- a/tools/testing/bin/jsshell
+++ b/tools/testing/bin/jsshell
@@ -1,16 +1,17 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
+JSDIR=${0%/*}/../../../third_party/firefox_jsshell
 
 case $OSTYPE in
     *[Dd]arwin*)
-        exec ${0%/*}/../../../third_party/firefox_jsshell/macos/js "$@"
+        exec $JSDIR/mac/jsshell/js "$@"
         ;;
     *[Ll]inux*)
-        LD_LIBRARY_PATH=${0%/*}/../../../third_party/firefox_jsshell/linux/ \
-            exec ${0%/*}/../../../third_party/firefox_jsshell/linux/js "$@"
+        LD_LIBRARY_PATH=$JSDIR/linux/jsshell/ \
+            exec $JSDIR/linux/jsshell/js "$@"
         ;;
     *)
         echo No jsshell binary for $(uname) >2
diff --git a/tools/testing/bin/jsshell.bat b/tools/testing/bin/jsshell.bat
index e99335f..0666885 100644
--- a/tools/testing/bin/jsshell.bat
+++ b/tools/testing/bin/jsshell.bat
@@ -10,4 +10,4 @@
 

 set arguments=%*

 

-"%SCRIPTPATH%..\..\..\third_party\firefox_jsshell\windows\js.exe" %arguments%

+"%SCRIPTPATH%..\..\..\third_party\firefox_jsshell\win\jsshell\js.exe" %arguments%

diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index e901344..a89aad5 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -74,6 +74,9 @@
             isHostChecked: isHostChecked, useCps: useCps, useSdk: useSdk,
             isCsp: isCsp, extraDart2jsOptions:
                 TestUtils.getExtraOptions(configuration, 'dart2js_options'));
+      case 'precompiler':
+        return new PrecompilerCompilerConfiguration(
+            isDebug: isDebug, isChecked: isChecked);
       case 'none':
         return new NoneCompilerConfiguration(
             isDebug: isDebug, isChecked: isChecked,
@@ -119,6 +122,12 @@
     return new CommandArtifact([], null, null);
   }
 
+  List<String> computeCompilerArguments(vmOptions, sharedOptions, args) {
+    return new List<String>()
+        ..addAll(sharedOptions)
+        ..addAll(args);
+  }
+
   List<String> computeRuntimeArguments(
       RuntimeConfiguration runtimeConfiguration,
       String buildDir,
@@ -294,6 +303,92 @@
   }
 }
 
+
+class PrecompilerCompilerConfiguration extends CompilerConfiguration {
+  PrecompilerCompilerConfiguration({
+      bool isDebug,
+      bool isChecked})
+      : super._subclass(isDebug: isDebug, isChecked: isChecked);
+
+  int computeTimeoutMultiplier() {
+    int multiplier = 2;
+    if (isDebug) multiplier *= 4;
+    if (isChecked) multiplier *= 2;
+    return multiplier;
+  }
+
+  CommandArtifact computeCompilationArtifact(
+      String buildDir,
+      String tempDir,
+      CommandBuilder commandBuilder,
+      List arguments,
+      Map<String, String> environmentOverrides) {
+    return new CommandArtifact(
+        <Command>[
+            this.computeCompilationCommand(
+                tempDir,
+                buildDir,
+                CommandBuilder.instance,
+                arguments,
+                environmentOverrides)],
+        '$tempDir',
+        'application/dart-precompiled');
+  }
+
+  CompilationCommand computeCompilationCommand(
+      String tempDir,
+      String buildDir,
+      CommandBuilder commandBuilder,
+      List arguments,
+      Map<String, String> environmentOverrides) {
+    var exec = "$buildDir/dart";
+    var args = new List();
+    args.add("tools/precompilation/precompiler.dart");
+    args.add("$buildDir/dart_no_snapshot");
+    args.add("--gen-precompiled-snapshot=$tempDir");
+    args.addAll(arguments);
+
+    return commandBuilder.getCompilationCommand(
+        'precompiler.dart', tempDir, !useSdk,
+        bootstrapDependencies(buildDir),
+        exec, args, environmentOverrides);
+  }
+
+  List<String> computeCompilerArguments(vmOptions,
+                                        sharedOptions,
+                                        originalArguments) {
+    List<String> args = [];
+    if (isChecked) {
+      args.add('--enable_asserts');
+      args.add('--enable_type_checks');
+    }
+    return args
+        ..addAll(vmOptions)
+        ..addAll(sharedOptions)
+        ..addAll(originalArguments);
+  }
+
+  List<String> computeRuntimeArguments(
+      RuntimeConfiguration runtimeConfiguration,
+      String buildDir,
+      TestInformation info,
+      List<String> vmOptions,
+      List<String> sharedOptions,
+      List<String> originalArguments,
+      CommandArtifact artifact) {
+    List<String> args = [];
+    if (isChecked) {
+      args.add('--enable_asserts');
+      args.add('--enable_type_checks');
+    }
+    return args
+        ..addAll(vmOptions)
+        ..addAll(sharedOptions)
+        ..addAll(originalArguments);
+  }
+}
+
+
 class AnalyzerCompilerConfiguration extends CompilerConfiguration {
   AnalyzerCompilerConfiguration(
       {bool isDebug,
diff --git a/tools/testing/dart/runtime_configuration.dart b/tools/testing/dart/runtime_configuration.dart
index 1fbf54d..55810eb 100644
--- a/tools/testing/dart/runtime_configuration.dart
+++ b/tools/testing/dart/runtime_configuration.dart
@@ -52,6 +52,9 @@
       case 'vm':
         return new StandaloneDartRuntimeConfiguration();
 
+      case 'dart_precompiled':
+        return new DartPrecompiledRuntimeConfiguration();
+
       case 'drt':
         return new DrtRuntimeConfiguration();
 
@@ -218,6 +221,32 @@
   }
 }
 
+
+class DartPrecompiledRuntimeConfiguration extends DartVmRuntimeConfiguration {
+  List<Command> computeRuntimeCommands(
+      TestSuite suite,
+      CommandBuilder commandBuilder,
+      CommandArtifact artifact,
+      List<String> arguments,
+      Map<String, String> environmentOverrides) {
+    String script = artifact.filename;
+    String type = artifact.mimeType;
+    if (script != null && type != 'application/dart-precompiled') {
+      throw "dart_precompiled cannot run files of type '$type'.";
+    }
+
+    var augmentedArgs = new List();
+    augmentedArgs.add("--run-precompiled-snapshot=${artifact.filename}");
+    augmentedArgs.addAll(arguments);
+
+    var augmentedEnv = new Map.from(environmentOverrides);
+    augmentedEnv['LD_LIBRARY_PATH'] = artifact.filename;
+
+    return <Command>[commandBuilder.getVmCommand(
+          suite.dartPrecompiledBinaryFileName, augmentedArgs, augmentedEnv)];
+  }
+}
+
 /// Temporary runtime configuration for browser runtimes that haven't been
 /// migrated yet.
 // TODO(ahe): Remove this class.
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index a376f28..92514fe 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -67,7 +67,7 @@
    dart2analyzer: Perform static analysis on Dart code by running the analyzer
           (only valid with the following runtimes: none)''',
               ['-c', '--compiler'],
-              ['none', 'dart2js', 'dart2analyzer'],
+              ['none', 'precompiler', 'dart2js', 'dart2analyzer'],
               'none'),
           // TODO(antonm): fix the option drt.
           new _TestOptionSpecification(
@@ -75,6 +75,9 @@
               '''Where the tests should be run.
     vm: Run Dart code on the standalone dart vm.
 
+    dart_precompiled: Run a precompiled snapshot on a variant of the standalone
+                      dart vm lacking a JIT.
+
     d8: Run JavaScript from the command line using v8.
 
     jsshell: Run JavaScript from the command line using firefox js-shell.
@@ -95,7 +98,8 @@
     none: No runtime, compile only (for example, used for dart2analyzer static
           analysis tests).''',
               ['-r', '--runtime'],
-              ['vm', 'd8', 'jsshell', 'drt', 'dartium', 'ff', 'firefox',
+              ['vm', 'dart_precompiled', 'd8', 'jsshell', 'drt', 'dartium',
+               'ff', 'firefox',
                'chrome', 'safari', 'ie9', 'ie10', 'ie11', 'opera',
                'chromeOnAndroid', 'safarimobilesim',
                'ContentShellOnAndroid', 'DartiumOnAndroid', 'none'],
@@ -644,6 +648,9 @@
       case 'dart2analyzer':
         validRuntimes = const ['none'];
         break;
+      case 'precompiler':
+        validRuntimes = const ['dart_precompiled'];
+        break;
       case 'none':
         validRuntimes = const ['vm', 'drt', 'dartium',
                                'ContentShellOnAndroid', 'DartiumOnAndroid'];
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index eeb1d69..ffd9921 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -1679,6 +1679,10 @@
     return new VmCommandOutputImpl(
         command, exitCode, timedOut, stdout, stderr, time, pid);
   } else if (command is CompilationCommand) {
+    if (command.displayName == 'precompiler.dart') {
+      return new VmCommandOutputImpl(
+          command, exitCode, timedOut, stdout, stderr, time, pid);
+    }
     return new CompilationCommandOutputImpl(
         command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
   } else if (command is JSCommandlineCommand) {
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index bec08a8..533c01c 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -212,6 +212,19 @@
     return dartExecutable;
   }
 
+  String get dartPrecompiledBinaryFileName {
+    // Controlled by user with the option "--dart_precompiled".
+    String dartExecutable = configuration['dart_precompiled'];
+
+    if (dartExecutable == null || dartExecutable == '') {
+      String suffix = executableBinarySuffix;
+      dartExecutable = '$buildDir/dart_precompiled$suffix';
+    }
+
+    TestUtils.ensureExists(dartExecutable, configuration);
+    return dartExecutable;
+  }
+
   String get d8FileName {
     var suffix = getExecutableSuffix('d8');
     var d8Dir = TestUtils.dartDir.append('third_party/d8');
@@ -882,6 +895,12 @@
       var packageDirectories = {};
       if (configuration['use_repository_packages']) {
         packageDirectories = new Map.from(localPackageDirectories);
+
+        // Don't create a dependency override for pub, since it's an application
+        // package and it has a dependency on compiler_unsupported which isn't
+        // in the repo.
+        packageDirectories.remove('pub');
+
         // Do not create an dependency override for the package itself.
         if (packageDirectories.containsKey(packageName)) {
           packageDirectories.remove(packageName);
@@ -1009,9 +1028,10 @@
     List<String> compileTimeArguments = <String>[];
     String tempDir;
     if (compilerConfiguration.hasCompiler) {
-      compileTimeArguments
-          ..addAll(sharedOptions)
-          ..addAll(args);
+      compileTimeArguments =
+          compilerConfiguration.computeCompilerArguments(vmOptions,
+                                                         sharedOptions,
+                                                         args);
       // Avoid doing this for analyzer.
       tempDir = createCompilationOutputDirectory(info.filePath);
     }
@@ -1772,8 +1792,8 @@
   }
 
   List<List<String>> getVmOptions(Map optionsFromFile) {
-    var COMPILERS = const ['none'];
-    var RUNTIMES = const ['none', 'vm', 'drt', 'dartium',
+    var COMPILERS = const ['none', 'precompiler'];
+    var RUNTIMES = const ['none', 'dart_precompiled', 'vm', 'drt', 'dartium',
                           'ContentShellOnAndroid', 'DartiumOnAndroid'];
     var needsVmOptions = COMPILERS.contains(configuration['compiler']) &&
                          RUNTIMES.contains(configuration['runtime']);
@@ -1974,6 +1994,12 @@
         var packageDirectories = {};
         if (!configuration['use_public_packages']) {
           packageDirectories = new Map.from(localPackageDirectories);
+
+          // Don't create a dependency override for pub, since it's an
+          // application package and it has a dependency on compiler_unsupported
+          // which isn't in the repo.
+          packageDirectories.remove('pub');
+
           if (packageDirectories.containsKey(packageName)) {
             packageDirectories.remove(packageName);
           }